[tradein][scrapers] Phase 1 — avito на camoufox BrowserFetcher (#883) #885

Closed
opened 2026-05-31 10:37:56 +00:00 by lekss361 · 1 comment
Owner

Phase 1 эпика #883. Depends Phase 0 (BrowserFetcher готов). Переводит только avito на browser-fetch.

Задача

Заменить curl_cffi fetch в avito-пути на BrowserFetcher (из Phase 0). Парсинг (__preloadedState__→selectolax, _link_listing_to_house и пр.) НЕ меняется — на вход тот же HTML, теперь добытый браузером.

Files

  • tradein-mvp/backend/app/services/scrape_pipeline.py — сейчас создаёт AsyncSession(impersonate="chrome120", proxies=_avito_proxies()) и присваивает scraper._cffi. Заменить на BrowserFetcher shared на sweep; SERP/detail/house дёргают await fetcher.fetch(url).
  • app/services/scrapers/avito.py — SERP: _fetch_serp_html/fetch_around берут HTML через fetcher вместо self._cffi.get. Убрать _rotate_ip/_is_firewall_page/429-retry-loop (browser не упирается в hard-firewall; soft-block ловит BrowserFetcher).
  • app/services/scrapers/avito_detail.pyfetch_detail: HTML через fetcher (не cffi_session.get). Парсинг как есть (включая #871 house_catalog_url из detail SSR — в browser HTML он тоже есть, verified).
  • app/services/scrapers/avito_houses.pyfetch_house_catalog: HTML через fetcher.
  • app/core/config.pyscraper_fetch_mode для avito → "browser" (или per-source map).

Поведение

  • delay: снизить request_delay_sec для avito до 1-2с (verified: camoufox 9/10 на нулевой задержке, IP-rate-стены нет). Floor ge=3.0 на admin-endpoint можно опустить (отдельно).
  • proxy-rotation: не нужна как было (browser не банится по rate); оставить опц. soft-block-rotate в BrowserFetcher.
  • AvitoBlockedError/RateLimitedError: flow упрощается — hard-429 практически не возникает; оставить как safety для soft-block-detect.

Definition of Done (бинарно)

  • /scrape/avito-city-sweep (pages=1) через browser → scrape_runs.status='done' (НЕ banned), реальные listings (не заглушки).
  • counters.unique_houses > 0 И houses_enriched > 0 (browser SSR содержит house-link, #871).
  • counters.detail_enriched > 0 с реальными полями (rooms/area/price не-NULL на новых).
  • Полный city-sweep (5 анкоров) доходит до конца без banned (recycle+relaunch из Phase 0 держит).
  • uv run pytest -k "avito or sweep or pipeline" зелёный (моки fetcher); ruff clean.

Не делать

  • НЕ трогать cian/n1/yandex (Phase 2).
  • НЕ удалять curl_cffi-код целиком — оставить за флагом scraper_fetch_mode для отката.

Эпик #883. Depends: Phase 0. Дальше: Phase 2.

> Phase 1 эпика #883. Depends Phase 0 (BrowserFetcher готов). Переводит **только avito** на browser-fetch. ## Задача Заменить curl_cffi fetch в avito-пути на `BrowserFetcher` (из Phase 0). Парсинг (`__preloadedState__`→selectolax, `_link_listing_to_house` и пр.) НЕ меняется — на вход тот же HTML, теперь добытый браузером. ## Files - `tradein-mvp/backend/app/services/scrape_pipeline.py` — сейчас создаёт `AsyncSession(impersonate="chrome120", proxies=_avito_proxies())` и присваивает `scraper._cffi`. Заменить на `BrowserFetcher` shared на sweep; SERP/detail/house дёргают `await fetcher.fetch(url)`. - `app/services/scrapers/avito.py` — SERP: `_fetch_serp_html`/`fetch_around` берут HTML через fetcher вместо `self._cffi.get`. Убрать `_rotate_ip`/`_is_firewall_page`/429-retry-loop (browser не упирается в hard-firewall; soft-block ловит BrowserFetcher). - `app/services/scrapers/avito_detail.py` — `fetch_detail`: HTML через fetcher (не `cffi_session.get`). Парсинг как есть (включая #871 house_catalog_url из detail SSR — в browser HTML он тоже есть, verified). - `app/services/scrapers/avito_houses.py` — `fetch_house_catalog`: HTML через fetcher. - `app/core/config.py` — `scraper_fetch_mode` для avito → `"browser"` (или per-source map). ## Поведение - **delay:** снизить `request_delay_sec` для avito до 1-2с (verified: camoufox 9/10 на нулевой задержке, IP-rate-стены нет). Floor `ge=3.0` на admin-endpoint можно опустить (отдельно). - **proxy-rotation:** не нужна как было (browser не банится по rate); оставить опц. soft-block-rotate в BrowserFetcher. - **AvitoBlockedError/RateLimitedError:** flow упрощается — hard-429 практически не возникает; оставить как safety для soft-block-detect. ## Definition of Done (бинарно) - [ ] `/scrape/avito-city-sweep` (pages=1) через browser → `scrape_runs.status='done'` (НЕ `banned`), реальные listings (не заглушки). - [ ] `counters.unique_houses > 0` И `houses_enriched > 0` (browser SSR содержит house-link, #871). - [ ] `counters.detail_enriched > 0` с реальными полями (rooms/area/price не-NULL на новых). - [ ] Полный city-sweep (5 анкоров) доходит до конца без `banned` (recycle+relaunch из Phase 0 держит). - [ ] `uv run pytest -k "avito or sweep or pipeline"` зелёный (моки fetcher); ruff clean. ## Не делать - НЕ трогать cian/n1/yandex (Phase 2). - НЕ удалять curl_cffi-код целиком — оставить за флагом `scraper_fetch_mode` для отката. Эпик #883. Depends: Phase 0. Дальше: Phase 2.
lekss361 added the
scrapers
scope/backend
status/blocked
priority/p1
tradein
labels 2026-05-31 10:37:56 +00:00
Collaborator

Закрыто — avito на camoufox BrowserFetcher живёт: scraper_fetch_mode='browser' дефолт с #1805, _fetch_serp_html_fetch_serp_html_browser (camoufox) с curl_cffi-fallback на firewall; curl_cffi сохранён за флагом (как требовала секция «Не делать»).

✅ Закрыто — avito на camoufox BrowserFetcher живёт: `scraper_fetch_mode='browser'` дефолт с #1805, `_fetch_serp_html` → `_fetch_serp_html_browser` (camoufox) с curl_cffi-fallback на firewall; curl_cffi сохранён за флагом (как требовала секция «Не делать»).
Sign in to join this conversation.
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#885
No description provided.