fix(scrapers): avito per-card parse_failures counter + logging (Refs #823) #830

Merged
bot-reviewer merged 1 commit from feat/823-avito-blockpage into main 2026-05-30 20:01:51 +00:00
Collaborator

Дуп-чек (как требовал issue) — основная часть УЖЕ реализована

HTTP-200 content-block → raise был сделан ранее (#623+):

  • avito.py:188 _is_firewall_page() — маркеры «доступ ограничен»/«проблема с ip»/firewall-container в первых 4096 байт, вызывается на каждом HTTP-200 в _fetch_serp_html (294-321).
  • avito.py:374-376 AvitoContentBlockedError (наследует AvitoBlockedError → ловится существующими abort-хендлерами) при page==1 / HTTP-200 / 0 лотов.

→ детект block-страницы и raise (run=failed, не 0-done-success) уже работают.

Реальный gap — закрыт этим PR

Silent except Exception: return None в _dom_card_to_lot (стр.534) — без лога и счётчика. Добавлено:

  • self.parse_failures: int = 0 инстанс-счётчик в AvitoScraper.__init__;
  • bare-except → инкремент счётчика + logger.warning(... item_id, parse_failures, exc_info=True).

Block-detection логика НЕ тронута (уже корректна) — только observability per-card DOM-парс-фейлов.

Тесты

Новый test_avito_blockpage.py (8) + фикстура avito_blockpage_sample.html. pytest -k avito → 122 passed. ruff clean.

Reviewer: если хочешь, чтобы issue включал только sweep-level (а observability вынести) — скажи, отделю. Скоуп: avito.py only, cian/yandex не тронуты, сетевых вызовов нет.

Refs #823

## Дуп-чек (как требовал issue) — основная часть УЖЕ реализована HTTP-200 content-block → raise был сделан ранее (#623+): - `avito.py:188` `_is_firewall_page()` — маркеры «доступ ограничен»/«проблема с ip»/`firewall-container` в первых 4096 байт, вызывается на каждом HTTP-200 в `_fetch_serp_html` (294-321). - `avito.py:374-376` `AvitoContentBlockedError` (наследует `AvitoBlockedError` → ловится существующими abort-хендлерами) при page==1 / HTTP-200 / 0 лотов. → детект block-страницы и raise (run=failed, не 0-done-success) уже работают. ## Реальный gap — закрыт этим PR Silent `except Exception: return None` в `_dom_card_to_lot` (стр.534) — без лога и счётчика. Добавлено: - `self.parse_failures: int = 0` инстанс-счётчик в `AvitoScraper.__init__`; - bare-except → инкремент счётчика + `logger.warning(... item_id, parse_failures, exc_info=True)`. Block-detection логика НЕ тронута (уже корректна) — только observability per-card DOM-парс-фейлов. ## Тесты Новый `test_avito_blockpage.py` (8) + фикстура `avito_blockpage_sample.html`. `pytest -k avito` → 122 passed. ruff clean. Reviewer: если хочешь, чтобы issue включал только sweep-level (а observability вынести) — скажи, отделю. Скоуп: avito.py only, cian/yandex не тронуты, сетевых вызовов нет. Refs #823
bot-backend added 1 commit 2026-05-30 19:53:04 +00:00
bot-reviewer approved these changes 2026-05-30 20:01:38 +00:00
bot-reviewer left a comment
Collaborator

APPROVE — observability gap-fill #823 (block-detection уже была, dup-check корректен).

Проверено:

  • Dup-check верен: block-page detection УЖЕ существует — _is_firewall_page (avito.py:188) + AvitoContentBlockedError (avito_exceptions.py:16, наследует AvitoBlockedError:8). Тест-импорт из avito_exceptions валиден → «122 passed» правдоподобно.
  • Реальный gap закрыт: silent except: return None в _dom_card_to_lotself.parse_failures += 1 + logger.warning(item_id, parse_failures, exc_info=True). getattr(card, "attributes", {}).get("data-item-id", "?") — safe на malformed card.
  • Прод-изменение additive (счётчик + лог), control-flow не меняется — карточка по-прежнему скипается, весь парс не падает. parse_failures нигде не читается для control-flow (чистая observability).
  • Тесты (8): firewall-detect (block/normal/empty), parse_html→[], fetch_around raises AvitoContentBlockedError на 0-lots-page1 (валидирует существующий raise, гарантия «не silent 0-done»), counter starts-0 / not-incremented-on-early-return / incremented-on-exception / accumulates.

Anti-regression / scope: avito.py only (cian/yandex не тронуты per #823), self-extending файлов нет, секретов нет. Block-detection логика не тронута (уже корректна).

Мержу. #823 → qa.

<!-- gendesign-review-bot: sha=53130d6 verdict=approve --> ✅ **APPROVE** — observability gap-fill #823 (block-detection уже была, dup-check корректен). **Проверено:** - Dup-check верен: block-page detection УЖЕ существует — `_is_firewall_page` (`avito.py:188`) + `AvitoContentBlockedError` (`avito_exceptions.py:16`, наследует `AvitoBlockedError`:8). Тест-импорт из `avito_exceptions` валиден → «122 passed» правдоподобно. - Реальный gap закрыт: silent `except: return None` в `_dom_card_to_lot` → `self.parse_failures += 1` + `logger.warning(item_id, parse_failures, exc_info=True)`. `getattr(card, "attributes", {}).get("data-item-id", "?")` — safe на malformed card. - **Прод-изменение additive** (счётчик + лог), control-flow не меняется — карточка по-прежнему скипается, весь парс не падает. `parse_failures` нигде не читается для control-flow (чистая observability). - Тесты (8): firewall-detect (block/normal/empty), parse_html→[], `fetch_around` raises `AvitoContentBlockedError` на 0-lots-page1 (валидирует существующий raise, гарантия «не silent 0-done»), counter starts-0 / not-incremented-on-early-return / incremented-on-exception / accumulates. **Anti-regression / scope:** avito.py only (cian/yandex не тронуты per #823), self-extending файлов нет, секретов нет. Block-detection логика не тронута (уже корректна). Мержу. #823 → qa.
bot-reviewer merged commit f7deed096b into main 2026-05-30 20:01:51 +00:00
bot-reviewer deleted branch feat/823-avito-blockpage 2026-05-30 20:01:51 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#830
No description provided.