vek-parser


Namevek-parser JSON
Version 0.1.7 PyPI version JSON
download
home_pageNone
SummaryУниверсальный парсер для сбора структурированных данных с веб-сайтов
upload_time2025-07-27 01:21:50
maintainerNone
docs_urlNone
authorEmil Markov
requires_python>=3.9
licenseMIT
keywords web parser scraping crawler
VCS
bugtrack_url
requirements requests selectorlib parsel PyYAML playwright
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # VekParser: Расширяемый парсер для веб-сайтов

## Основные возможности

- Многоступенчатая обработка данных через YAML-конфигурацию
- Поддержка параллельного выполнения задач
- Встроенные механизмы для работы с динамическим контентом (через Playwright)
- Кастомные обработчики данных
- Автоматическое сохранение результатов в JSON

## Ключевые концепции

### Типы шагов обработки

| Тип       | Назначение                          | Особенности                         |
|-----------|-------------------------------------|-------------------------------------|
| static    | Инициализация статических значений | Задает начальный контекст выполнения|
| extract   | Извлечение данных со страницы       | Использует CSS/XPath селекторы      |
| list      | Параллельная обработка коллекций    | Запускает вложенные цепочки шагов   |
| save      | Финализация и сохранение результата | Экспорт в JSON-файл                |

### Жизненный цикл данных
1. Инициализация контекста (static)
2. Извлечение данных (extract)
3. Обработка списка (list)
4. Сохранение (save)

## Полная структура конфигурации

```yaml
steps:
  - name: уникальное_имя_шага
    type: [static|extract|list|save|свой тип]
    
    # Параметры для static
    values: { ключ: значение }
    
    # Параметры для extract
    url: "шаблон_URL"
    data: { селекторы }
    
    # Параметры для list
    source: "ключ_в_контексте"
    output: "выходной_ключ"
    handler_name: [string|link|dict|свой обработчик]
    
    # Общие параметры
    next_steps:
      - step: "имя_следующего_шага"
        context_map: { ключ: "значение_из_контекста" }
```

## Расширенные возможности

### 1. Кастомные обработчики шагов

Регистрация пользовательской логики:
```python
class DataProcessor:
    @staticmethod
    def process_data(step_config: Dict, context: Dict) -> Dict:
        return {"processed": True}

parser.register_step_handler('transform', DataProcessor.process_data)
```

Пример использования в конфиге:
```yaml
- name: advanced_transform
  type: transform
  next_steps: [...]
```

### 2. Обработчики элементов списка

Поддерживаемые типы:
- `string` - текстовые элементы
- `link` - URL-адреса

Регистрация обработчика для словарей:
```python
parser.register_item_handler('dict', lambda item, _: item)
```

Конфигурация:
```yaml
- name: process_items
  type: list
  handler_name: dict
  steps: [...]
```

### 3. Механизм сохранения данных

Конфигурация шага сохранения:
```yaml
- name: save_results
  type: save
  fields:
    - field1
    - field2
```

Результат:
```json
[
  {
    "field1": "value1",
    "field2": "value2"
  },
  {
    "field1": "value3",
    "field2": "value4"
  }
]
```

## Полный пример парсера

### 1. Код обработчика

```python
class AreaCalculator:
    @staticmethod
    def calculate_dimensions(step_config: Dict, context: Dict) -> Dict:
        # Логика вычислений
        return {
            'area': width * height,
            'volume': width * height * depth
        }
```

### 2. Конфигурация

```yaml
steps:
  - name: product_processing
    type: list
    handler_name: dict
    steps:
      - name: extract_data
        type: extract
        url: "{link}"
        data:
          price: "#price::text"
          dimensions: ".specs::text"
        next_steps:
          - step: calculate_metrics
          
      - name: calculate_metrics
        type: transform
        next_steps:
          - step: save_product
          
  - name: save_product
    type: save
    fields:
      - title
      - price
      - area
      - volume
```

### 3. Инициализация парсера

```python
parser = WebParser(
    config_path='config.yml',
    base_url='https://example.com',
    render_js=True
)
parser.register_step_handler('transform', AreaCalculator.calculate_dimensions)
parser.register_item_handler('dict', lambda item, _: item)
```

## Отладка и мониторинг

### Логирование
Уровни логирования:
- DEBUG: детальная информация о выполнении шагов
- INFO: основные этапы работы
- WARNING: проблемы с доступностью ресурсов
- ERROR: критические ошибки выполнения

Настройка:
```python
logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
```

### Советы по оптимизации
1. Настройка параллелизма:
```python
WebParser(max_workers=10)
```

2. Интервал запросов:
```python
HttpClient(request_interval=1.0)
```

3. JS-рендеринг:
```python
WebParser(render_js=True)
```

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "vek-parser",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.9",
    "maintainer_email": null,
    "keywords": "web, parser, scraping, crawler",
    "author": "Emil Markov",
    "author_email": "Emil Markov <markovemil2@gmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/b9/05/4882802d9740354b305108bd00439e121e0c5f9b7683f9a39a8f708cc161/vek_parser-0.1.7.tar.gz",
    "platform": null,
    "description": "# VekParser: \u0420\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u043c\u044b\u0439 \u043f\u0430\u0440\u0441\u0435\u0440 \u0434\u043b\u044f \u0432\u0435\u0431-\u0441\u0430\u0439\u0442\u043e\u0432\n\n## \u041e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438\n\n- \u041c\u043d\u043e\u0433\u043e\u0441\u0442\u0443\u043f\u0435\u043d\u0447\u0430\u0442\u0430\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0447\u0435\u0440\u0435\u0437 YAML-\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e\n- \u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0437\u0430\u0434\u0430\u0447\n- \u0412\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u043c \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u043e\u043c (\u0447\u0435\u0440\u0435\u0437 Playwright)\n- \u041a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445\n- \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u0432 JSON\n\n## \u041a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u0438\n\n### \u0422\u0438\u043f\u044b \u0448\u0430\u0433\u043e\u0432 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438\n\n| \u0422\u0438\u043f       | \u041d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435                          | \u041e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438                         |\n|-----------|-------------------------------------|-------------------------------------|\n| static    | \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 | \u0417\u0430\u0434\u0430\u0435\u0442 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f|\n| extract   | \u0418\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u043e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b       | \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 CSS/XPath \u0441\u0435\u043b\u0435\u043a\u0442\u043e\u0440\u044b      |\n| list      | \u041f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u0430\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439    | \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0435 \u0446\u0435\u043f\u043e\u0447\u043a\u0438 \u0448\u0430\u0433\u043e\u0432   |\n| save      | \u0424\u0438\u043d\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 | \u042d\u043a\u0441\u043f\u043e\u0440\u0442 \u0432 JSON-\u0444\u0430\u0439\u043b                |\n\n### \u0416\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u0439 \u0446\u0438\u043a\u043b \u0434\u0430\u043d\u043d\u044b\u0445\n1. \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 (static)\n2. \u0418\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 (extract)\n3. \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0441\u043f\u0438\u0441\u043a\u0430 (list)\n4. \u0421\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 (save)\n\n## \u041f\u043e\u043b\u043d\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438\n\n```yaml\nsteps:\n  - name: \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0435_\u0438\u043c\u044f_\u0448\u0430\u0433\u0430\n    type: [static|extract|list|save|\u0441\u0432\u043e\u0439 \u0442\u0438\u043f]\n    \n    # \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0434\u043b\u044f static\n    values: { \u043a\u043b\u044e\u0447: \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 }\n    \n    # \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0434\u043b\u044f extract\n    url: \"\u0448\u0430\u0431\u043b\u043e\u043d_URL\"\n    data: { \u0441\u0435\u043b\u0435\u043a\u0442\u043e\u0440\u044b }\n    \n    # \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0434\u043b\u044f list\n    source: \"\u043a\u043b\u044e\u0447_\u0432_\u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435\"\n    output: \"\u0432\u044b\u0445\u043e\u0434\u043d\u043e\u0439_\u043a\u043b\u044e\u0447\"\n    handler_name: [string|link|dict|\u0441\u0432\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a]\n    \n    # \u041e\u0431\u0449\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b\n    next_steps:\n      - step: \"\u0438\u043c\u044f_\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e_\u0448\u0430\u0433\u0430\"\n        context_map: { \u043a\u043b\u044e\u0447: \"\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435_\u0438\u0437_\u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430\" }\n```\n\n## \u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438\n\n### 1. \u041a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u0448\u0430\u0433\u043e\u0432\n\n\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438:\n```python\nclass DataProcessor:\n    @staticmethod\n    def process_data(step_config: Dict, context: Dict) -> Dict:\n        return {\"processed\": True}\n\nparser.register_step_handler('transform', DataProcessor.process_data)\n```\n\n\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0435:\n```yaml\n- name: advanced_transform\n  type: transform\n  next_steps: [...]\n```\n\n### 2. \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0441\u043f\u0438\u0441\u043a\u0430\n\n\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0435 \u0442\u0438\u043f\u044b:\n- `string` - \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b\n- `link` - URL-\u0430\u0434\u0440\u0435\u0441\u0430\n\n\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u0434\u043b\u044f \u0441\u043b\u043e\u0432\u0430\u0440\u0435\u0439:\n```python\nparser.register_item_handler('dict', lambda item, _: item)\n```\n\n\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f:\n```yaml\n- name: process_items\n  type: list\n  handler_name: dict\n  steps: [...]\n```\n\n### 3. \u041c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445\n\n\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u0448\u0430\u0433\u0430 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f:\n```yaml\n- name: save_results\n  type: save\n  fields:\n    - field1\n    - field2\n```\n\n\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442:\n```json\n[\n  {\n    \"field1\": \"value1\",\n    \"field2\": \"value2\"\n  },\n  {\n    \"field1\": \"value3\",\n    \"field2\": \"value4\"\n  }\n]\n```\n\n## \u041f\u043e\u043b\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u043f\u0430\u0440\u0441\u0435\u0440\u0430\n\n### 1. \u041a\u043e\u0434 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\n\n```python\nclass AreaCalculator:\n    @staticmethod\n    def calculate_dimensions(step_config: Dict, context: Dict) -> Dict:\n        # \u041b\u043e\u0433\u0438\u043a\u0430 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439\n        return {\n            'area': width * height,\n            'volume': width * height * depth\n        }\n```\n\n### 2. \u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f\n\n```yaml\nsteps:\n  - name: product_processing\n    type: list\n    handler_name: dict\n    steps:\n      - name: extract_data\n        type: extract\n        url: \"{link}\"\n        data:\n          price: \"#price::text\"\n          dimensions: \".specs::text\"\n        next_steps:\n          - step: calculate_metrics\n          \n      - name: calculate_metrics\n        type: transform\n        next_steps:\n          - step: save_product\n          \n  - name: save_product\n    type: save\n    fields:\n      - title\n      - price\n      - area\n      - volume\n```\n\n### 3. \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u0430\u0440\u0441\u0435\u0440\u0430\n\n```python\nparser = WebParser(\n    config_path='config.yml',\n    base_url='https://example.com',\n    render_js=True\n)\nparser.register_step_handler('transform', AreaCalculator.calculate_dimensions)\nparser.register_item_handler('dict', lambda item, _: item)\n```\n\n## \u041e\u0442\u043b\u0430\u0434\u043a\u0430 \u0438 \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433\n\n### \u041b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\n\u0423\u0440\u043e\u0432\u043d\u0438 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f:\n- DEBUG: \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 \u0448\u0430\u0433\u043e\u0432\n- INFO: \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u044d\u0442\u0430\u043f\u044b \u0440\u0430\u0431\u043e\u0442\u044b\n- WARNING: \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0441 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u044c\u044e \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432\n- ERROR: \u043a\u0440\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f\n\n\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430:\n```python\nlogging.basicConfig(\n    level=logging.DEBUG,\n    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'\n)\n```\n\n### \u0421\u043e\u0432\u0435\u0442\u044b \u043f\u043e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438\n1. \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u0438\u0437\u043c\u0430:\n```python\nWebParser(max_workers=10)\n```\n\n2. \u0418\u043d\u0442\u0435\u0440\u0432\u0430\u043b \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432:\n```python\nHttpClient(request_interval=1.0)\n```\n\n3. JS-\u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433:\n```python\nWebParser(render_js=True)\n```\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "\u0423\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u0430\u0440\u0441\u0435\u0440 \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u0430 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441 \u0432\u0435\u0431-\u0441\u0430\u0439\u0442\u043e\u0432",
    "version": "0.1.7",
    "project_urls": {
        "Documentation": "https://github.com/EmilMarkov/VekParser#readme",
        "Homepage": "https://github.com/EmilMarkov/VekParser",
        "Repository": "https://github.com/EmilMarkov/VekParser.git"
    },
    "split_keywords": [
        "web",
        " parser",
        " scraping",
        " crawler"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "dc153eb706185923eb7512728a7c0426a8b1ac1fbe64e968e8e275bd4aa213bf",
                "md5": "a8c393aeaeeece78bb47ee684e9c7e23",
                "sha256": "743213998cdbf51da3515beda9f9cd4f4b0f4bb2bad6eeace4c8eefda2431523"
            },
            "downloads": -1,
            "filename": "vek_parser-0.1.7-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "a8c393aeaeeece78bb47ee684e9c7e23",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.9",
            "size": 9559,
            "upload_time": "2025-07-27T01:21:49",
            "upload_time_iso_8601": "2025-07-27T01:21:49.847389Z",
            "url": "https://files.pythonhosted.org/packages/dc/15/3eb706185923eb7512728a7c0426a8b1ac1fbe64e968e8e275bd4aa213bf/vek_parser-0.1.7-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "b9054882802d9740354b305108bd00439e121e0c5f9b7683f9a39a8f708cc161",
                "md5": "be657a6c3d5ec563e43bc394662c375c",
                "sha256": "089bcddcef169ccf3be711c842a596c6a661cdbc4c818e4de01ed83532c8057a"
            },
            "downloads": -1,
            "filename": "vek_parser-0.1.7.tar.gz",
            "has_sig": false,
            "md5_digest": "be657a6c3d5ec563e43bc394662c375c",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.9",
            "size": 10592,
            "upload_time": "2025-07-27T01:21:50",
            "upload_time_iso_8601": "2025-07-27T01:21:50.902011Z",
            "url": "https://files.pythonhosted.org/packages/b9/05/4882802d9740354b305108bd00439e121e0c5f9b7683f9a39a8f708cc161/vek_parser-0.1.7.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-07-27 01:21:50",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "EmilMarkov",
    "github_project": "VekParser#readme",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "requirements": [
        {
            "name": "requests",
            "specs": [
                [
                    ">=",
                    "2.25.0"
                ]
            ]
        },
        {
            "name": "selectorlib",
            "specs": [
                [
                    ">=",
                    "0.16.0"
                ]
            ]
        },
        {
            "name": "parsel",
            "specs": [
                [
                    ">=",
                    "1.7.0"
                ]
            ]
        },
        {
            "name": "PyYAML",
            "specs": [
                [
                    ">=",
                    "5.4.0"
                ]
            ]
        },
        {
            "name": "playwright",
            "specs": [
                [
                    "~=",
                    "1.50.0"
                ]
            ]
        }
    ],
    "lcname": "vek-parser"
}
        
Elapsed time: 1.09221s