[tradein] scraper_kit Group F4: shared base classes + consistent naming/layout providers/* #2352

Closed
opened 2026-07-03 23:51:20 +00:00 by lekss361 · 2 comments
Owner

Родительский: #2309 (Group F). F1/F2/F3 все завершены — разблокирован.

Пересмотр размера (2026-07-04)

Замер: providers/* = 13 201 строк (avito 5462, cian 3222, yandex 2854, domclick 1312,
ekb_geoportal 261). Структурная неоднородность подтверждена: avito/serp.py — 11
функций/классов, cian/serp.py — 4, yandex/serp.py — 15, domclick/serp.py — 7. Retry/backoff
паттерн повторяется 30 раз, BrowserFetcher(...) конструируется в 11 местах независимо.

Это L по .claude/rules/delegation.md (>5 файлов, заведомо >500 строк diff при реальном
рефакторе) — один PR на весь scope нарушил бы пороги дробления. Разбито дальше на
Foundation → Workers (см. дочерние issues, будут созданы отдельно: F4-Foundation, F4a-avito,
F4b-cian, F4c-yandex, F4d-domclick). ekb_geoportal (261 строк, уже "clean minimal precedent" по
SPEC) — вне scope миграции на новую базу, слишком мал чтобы того стоило.

Порядок

  1. F4-Foundation — спроектировать и реализовать общий base/utils (retry/error-handling/
    session-management паттерн, DRY-извлечение из повторяющегося кода) в НОВОМ модуле
    (например scraper_kit/providers/_base.py или common.py) — аддитивно, НЕ трогает
    существующие provider-файлы
    . Плюс scraper_adapters.py docstring фикс (тривиален, влезает
    сюда же). Низкий риск — новый код, старый не тронут.
  2. F4a/F4b/F4c/F4d (avito/cian/yandex/domclick) — миграция каждого provider-submodule на
    новую базу из Foundation. Параллельно между собой (непересекающиеся файлы), НО каждый зависит
    от F4-Foundation (последовательно после неё).

DoD (не изменился)

  • Общие паттерны вынесены в shared base/utils, дублирование снижено (замерить строк до/после)
  • Не ломает существующих consumers (kit scheduler, orchestration) — полный test suite +
    smoke на проде после деплоя
  • scraper_adapters.py docstring исправлен
  • НЕ трогает legacy app/services/scrapers/*

Refs #2309

Родительский: #2309 (Group F). F1/F2/F3 все завершены — разблокирован. ## Пересмотр размера (2026-07-04) Замер: `providers/*` = 13 201 строк (avito 5462, cian 3222, yandex 2854, domclick 1312, ekb_geoportal 261). Структурная неоднородность подтверждена: `avito/serp.py` — 11 функций/классов, `cian/serp.py` — 4, `yandex/serp.py` — 15, `domclick/serp.py` — 7. Retry/backoff паттерн повторяется 30 раз, `BrowserFetcher(...)` конструируется в 11 местах независимо. Это **L по `.claude/rules/delegation.md`** (>5 файлов, заведомо >500 строк diff при реальном рефакторе) — один PR на весь scope нарушил бы пороги дробления. Разбито дальше на Foundation → Workers (см. дочерние issues, будут созданы отдельно: F4-Foundation, F4a-avito, F4b-cian, F4c-yandex, F4d-domclick). ekb_geoportal (261 строк, уже "clean minimal precedent" по SPEC) — вне scope миграции на новую базу, слишком мал чтобы того стоило. ## Порядок 1. **F4-Foundation** — спроектировать и реализовать общий base/utils (retry/error-handling/ session-management паттерн, DRY-извлечение из повторяющегося кода) в НОВОМ модуле (например `scraper_kit/providers/_base.py` или `common.py`) — **аддитивно, НЕ трогает существующие provider-файлы**. Плюс `scraper_adapters.py` docstring фикс (тривиален, влезает сюда же). Низкий риск — новый код, старый не тронут. 2. **F4a/F4b/F4c/F4d** (avito/cian/yandex/domclick) — миграция каждого provider-submodule на новую базу из Foundation. Параллельно между собой (непересекающиеся файлы), НО каждый зависит от F4-Foundation (последовательно после неё). ## DoD (не изменился) - [ ] Общие паттерны вынесены в shared base/utils, дублирование снижено (замерить строк до/после) - [ ] Не ломает существующих consumers (kit scheduler, orchestration) — полный test suite + smoke на проде после деплоя - [ ] `scraper_adapters.py` docstring исправлен - [ ] НЕ трогает legacy `app/services/scrapers/*` Refs #2309
Author
Owner

Доп. DoD-пункт из F3-аудита (#2351, завершён): найдена системная неоднородность — некоторые providers/* функции делают config: ScraperConfig mandatory (cian/yandex valuation), другие — optional с молчаливым fallback (avito fetch_detail, build_warmed_session после фикса #2330, evaluate_via_imv). Optional-паттерн — источник всех 5 footgun-инстансов этого эпика (caller забыл передать = тихая потеря proxy/throttle).

Рекомендация для F4: рассмотреть конвенцию — mandatory config по умолчанию для ЛЮБОЙ функции с сетевым I/O в providers/*, optional только там, где есть явное архитектурное обоснование (например cian/detail.py::fetch_detail с browser_fetcher= путём, где config не нужен по дизайну — задокументировано в docstring). Это не blocking для уже смерженных/одобренных фиксов (#2322/#2330 fixes), но должно стать частью consistency-рефактора.

Полный аудит-отчёт (11 находок разобраны, 0 новых issues) см. в результатах агента F3 — можно запросить у main-сессии при необходимости, здесь не дублирую целиком.

Доп. DoD-пункт из F3-аудита (#2351, завершён): найдена системная неоднородность — некоторые providers/* функции делают `config: ScraperConfig` **mandatory** (cian/yandex valuation), другие — **optional с молчаливым fallback** (avito fetch_detail, build_warmed_session после фикса #2330, evaluate_via_imv). Optional-паттерн — источник всех 5 footgun-инстансов этого эпика (caller забыл передать = тихая потеря proxy/throttle). Рекомендация для F4: рассмотреть конвенцию — mandatory `config` по умолчанию для ЛЮБОЙ функции с сетевым I/O в providers/*, optional только там, где есть явное архитектурное обоснование (например `cian/detail.py::fetch_detail` с `browser_fetcher=` путём, где config не нужен по дизайну — задокументировано в docstring). Это не blocking для уже смерженных/одобренных фиксов (#2322/#2330 fixes), но должно стать частью consistency-рефактора. Полный аудит-отчёт (11 находок разобраны, 0 новых issues) см. в результатах агента F3 — можно запросить у main-сессии при необходимости, здесь не дублирую целиком.
lekss361 added the
scope/backend
scrapers
tech-debt
tradein
labels 2026-07-04 10:23:50 +00:00
Author
Owner

Верификация DoD (2026-07-04, live против текущего main)

Проверено напрямую в коде (не по памяти):

  • Foundation существует и используется: scraper_kit/providers/_base.py (207 строк) — build_browser_fetcher, build_curl_cffi_session, build_document_session, DOCUMENT_HEADERS, http_proxies().
  • Все 4 провайдера мигрированы: avito/detail.py, avito/serp.py, cian/detail.py, cian/newbuilding.py, cian/serp.py, cian/session.py, domclick/serp.py, yandex/serp.py — все реально импортируют из _base (grep подтверждён).
  • scraper_adapters.py docstring исправлен — сейчас корректно документирует app.scheduler_main._run_kit_scheduler как реальную wiring-точку (не "никто не использует").
  • Consumers не сломаны — dispatch-таблица (product_handlers.py + scraper_kit/orchestration/scheduler.py) активно используется прод-планировщиком; PR #2375/#2374/#2384/#2372 (avito/cian/yandex/domclick миграция на _base) все смерджены с полным test suite green по своим PR.

DoD выполнен полностью. Закрываю issue.

## Верификация DoD (2026-07-04, live против текущего main) Проверено напрямую в коде (не по памяти): - **Foundation существует и используется**: `scraper_kit/providers/_base.py` (207 строк) — `build_browser_fetcher`, `build_curl_cffi_session`, `build_document_session`, `DOCUMENT_HEADERS`, `http_proxies()`. - **Все 4 провайдера мигрированы**: `avito/detail.py`, `avito/serp.py`, `cian/detail.py`, `cian/newbuilding.py`, `cian/serp.py`, `cian/session.py`, `domclick/serp.py`, `yandex/serp.py` — все реально импортируют из `_base` (grep подтверждён). - **`scraper_adapters.py` docstring исправлен** — сейчас корректно документирует `app.scheduler_main._run_kit_scheduler` как реальную wiring-точку (не "никто не использует"). - **Consumers не сломаны** — dispatch-таблица (`product_handlers.py` + `scraper_kit/orchestration/scheduler.py`) активно используется прод-планировщиком; PR #2375/#2374/#2384/#2372 (avito/cian/yandex/domclick миграция на `_base`) все смерджены с полным test suite green по своим PR. DoD выполнен полностью. Закрываю issue.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
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#2352
No description provided.