feat(tradein/scrapers): detail_backfill через curl_cffi+backconnect вместо браузера/auv (развязка прокси) #1838

Merged
lekss361 merged 1 commit from feat/tradein-detail-backfill-curl into main 2026-06-20 12:59:56 +00:00
Owner

Зачем

avito SERP (full_load/city_sweep) и avito detail_backfill делили ОДИН прокси-аккаунт auv (~5 параллельных коннектов). Браузерный page.goto фанится в десятки под-ресурсных коннектов → кап превышается → HTTP 500 → краши/зомби full_load и backfill при наложении. (Сегодня так упал avito run 263 и зомбил yandex_city_sweep.)

Решение — развязка прокси БЕЗ покупки аккаунта

detail_backfill → curl_cffi через backconnect (mproxy) (авто-ротация IP, 1 коннект/запрос — 5-кап backconnect не проблема). SERP остаётся на браузере/auv. Разные аккаунты → нет контеншна, можно гонять параллельно.

Проверено вживую (100 ЕКБ-карточек curl/backconnect)

ok=85, blocked=0, err=15 (транзиентные таймаут/302 мёртвых листингов). 0 антибот-блоков. floor/total_floors 100%, living_area_m2 67% (в БД было 2% — curl добавляет поле). year_built/house_type/bedrooms = 0% у avito в любом случае (ни curl, ни браузер не берут — приходят из cian/yandex/кадастра) → регресса полей нет.

Что (tradein-mvp/backend/)

  • app/core/config.py (349-359): флаг avito_detail_backfill_use_curl: bool = True (ENV AVITO_DETAIL_BACKFILL_USE_CURL; False = старое browser/auv поведение).
  • app/tasks/avito_detail_backfill.py (92-133): browser_mode = scraper_fetch_mode=="browser" and not use_curl. При use_curl → BrowserFetcher не создаётся, fetch_detail(url, browser_fetcher=None) → curl-путь; fetch_detail сам строит эфемерную сессию через _build_detail_session() (egress scraper_proxy_url = backconnect mproxy, новый CONNECT-туннель/IP на запрос). Логируется режим на старте.
  • Legacy ветки (browser/auv и curl_cffi-shared) сохранены под флагом False.

НЕ затронуто

scrape_pipeline.py full_load/city_sweep inline-detail — остаются на браузере (проверено grep).

Тесты

  • tests/tasks/test_avito_detail_backfill.py: 10/10 (8 + 2 новых на флаг).
  • Полный pytest: 2232 passed, 1 skipped, 2 failed (pre-existing на main: cian cache + search auth — не относятся).
  • ruff green.

Связано: #1796 (avito rotation), #1814 (detail→browser, частично откатывается для backfill — на мобильном backconnect curl проходит).

## Зачем avito SERP (full_load/city_sweep) и avito detail_backfill делили ОДИН прокси-аккаунт **auv** (~5 параллельных коннектов). Браузерный `page.goto` фанится в десятки под-ресурсных коннектов → кап превышается → **HTTP 500** → краши/зомби full_load и backfill при наложении. (Сегодня так упал avito run 263 и зомбил yandex_city_sweep.) ## Решение — развязка прокси БЕЗ покупки аккаунта detail_backfill → **curl_cffi через backconnect (mproxy)** (авто-ротация IP, 1 коннект/запрос — 5-кап backconnect не проблема). SERP остаётся на браузере/auv. Разные аккаунты → нет контеншна, можно гонять параллельно. ## Проверено вживую (100 ЕКБ-карточек curl/backconnect) `ok=85, blocked=0, err=15` (транзиентные таймаут/302 мёртвых листингов). **0 антибот-блоков.** floor/total_floors 100%, living_area_m2 67% (в БД было 2% — curl **добавляет** поле). year_built/house_type/bedrooms = 0% у avito в любом случае (ни curl, ни браузер не берут — приходят из cian/yandex/кадастра) → регресса полей нет. ## Что (`tradein-mvp/backend/`) - **`app/core/config.py`** (349-359): флаг `avito_detail_backfill_use_curl: bool = True` (ENV `AVITO_DETAIL_BACKFILL_USE_CURL`; False = старое browser/auv поведение). - **`app/tasks/avito_detail_backfill.py`** (92-133): `browser_mode = scraper_fetch_mode=="browser" and not use_curl`. При `use_curl` → BrowserFetcher не создаётся, `fetch_detail(url, browser_fetcher=None)` → curl-путь; `fetch_detail` сам строит эфемерную сессию через `_build_detail_session()` (egress `scraper_proxy_url` = backconnect mproxy, новый CONNECT-туннель/IP на запрос). Логируется режим на старте. - Legacy ветки (browser/auv и curl_cffi-shared) сохранены под флагом False. ## НЕ затронуто `scrape_pipeline.py` full_load/city_sweep inline-detail — остаются на браузере (проверено grep). ## Тесты - `tests/tasks/test_avito_detail_backfill.py`: 10/10 (8 + 2 новых на флаг). - Полный pytest: **2232 passed, 1 skipped, 2 failed** (pre-existing на main: cian cache + search auth — не относятся). - ruff green. Связано: #1796 (avito rotation), #1814 (detail→browser, частично откатывается для backfill — на мобильном backconnect curl проходит).
lekss361 added 1 commit 2026-06-20 12:57:09 +00:00
feat(tradein/scrapers): detail_backfill через curl_cffi+backconnect вместо браузера/auv (развязка прокси)
All checks were successful
CI / changes (pull_request) Successful in 7s
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
cc3ff7c3d2
SERP (full_load/city_sweep) и detail_backfill делили один прокси-аккаунт auv (~5 коннектов).
Browser-фетч в backfill открывал десятки CONNECT-туннелей → cap превышался → HTTP 500/краши.

- config.py: avito_detail_backfill_use_curl=True (ENV AVITO_DETAIL_BACKFILL_USE_CURL)
- avito_detail_backfill.py: browser_mode гейтится флагом; use_curl=True → session=None,
  browser_fetcher=None → fetch_detail строит _build_detail_session() через scraper_proxy_url
  (backconnect mproxy, авто-ротация, 1 коннект/запрос)
- tests: 2 новых теста (use_curl=True → BrowserFetcher не создаётся; False → создаётся)
lekss361 merged commit 8bf3d24190 into main 2026-06-20 12:59:56 +00:00
lekss361 deleted branch feat/tradein-detail-backfill-curl 2026-06-20 12:59:57 +00:00
Sign in to join this conversation.
No reviewers
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#1838
No description provided.