tradein: Avito-баны режут покрытие аналогов и кросс-валидацию оценки #1796

Closed
opened 2026-06-19 16:07:26 +00:00 by lekss361 · 1 comment
Owner

Симптом

В live cross-class smoke (2026-06-19) Avito как источник аналогов почти пуст: в основном n=1, местами n=0, тогда как Циан даёт n=3-10. Это:

  • сужает выборку для headline (Циан остаётся единственной рабочей лошадкой),
  • ломает кросс-валидацию (по части адресов нечем сверить Циан/Яндекс).

Evidence

scrape_runs за 24-48ч (tradein-postgres):

avito_full_load:  6 banned / 7 cancelled / 1 failed / 1 zombie / 1 done
avito_city_sweep: banned (+5 zombie/48ч)

Прокси задеплоен (#788/#805, runbook avito_mobile_proxy.md), но avito_full_load массово ловит banned/zombie → свежих Avito-листингов мало → в estimate Avito-аналогов 0-1.

Что разобрать

  1. Работает ли прокси сейчас (env в tradein-scraper, ротация IP, runbook avito_mobile_proxy.md) — или деградировал.
  2. Триггер бана: IP / rate / fingerprint / captcha — docker logs tradein-scraper + tradein-browser на конкретику.
  3. zombie = worker умер по heartbeat (память/таймаут/краш) vs реальный бан — разделить.
  4. Свежесть: SELECT max(scraped_at), count(*) FILTER (WHERE scraped_at > now()-interval '7 days') FROM listings WHERE source='avito' — реально ли что-то льётся.
  5. Покрытие vs Циан: сколько активных avito-листингов по районам.

Эффект если починить

  • Больше аналогов на estimate → стабильнее headline (особенно тонкие выборки бизнес/премиум, см. #1795).
  • Полноценная кросс-валидация Авито↔Циан↔Яндекс.

Связано

  • #1795 (завышение премиума — частично из-за тонких выборок; Avito-покрытие усугубляет).
  • #788/#805 (avito mobile proxy), runbook avito_mobile_proxy.md.
  • Web-пробинг Avito — ТОЛЬКО через playwright MCP (антибот), не curl (правило проекта).

Источник: live smoke 2026-06-19 + scrape_runs аудит.

## Симптом В live cross-class smoke (2026-06-19) Avito как источник аналогов почти пуст: **в основном n=1, местами n=0**, тогда как Циан даёт n=3-10. Это: - сужает выборку для headline (Циан остаётся единственной рабочей лошадкой), - ломает кросс-валидацию (по части адресов нечем сверить Циан/Яндекс). ## Evidence `scrape_runs` за 24-48ч (tradein-postgres): ``` avito_full_load: 6 banned / 7 cancelled / 1 failed / 1 zombie / 1 done avito_city_sweep: banned (+5 zombie/48ч) ``` Прокси задеплоен (#788/#805, runbook avito_mobile_proxy.md), но `avito_full_load` массово ловит `banned`/`zombie` → свежих Avito-листингов мало → в estimate Avito-аналогов 0-1. ## Что разобрать 1. Работает ли прокси сейчас (env в `tradein-scraper`, ротация IP, runbook avito_mobile_proxy.md) — или деградировал. 2. Триггер бана: IP / rate / fingerprint / captcha — `docker logs tradein-scraper` + `tradein-browser` на конкретику. 3. `zombie` = worker умер по heartbeat (память/таймаут/краш) vs реальный бан — разделить. 4. Свежесть: `SELECT max(scraped_at), count(*) FILTER (WHERE scraped_at > now()-interval '7 days') FROM listings WHERE source='avito'` — реально ли что-то льётся. 5. Покрытие vs Циан: сколько активных avito-листингов по районам. ## Эффект если починить - Больше аналогов на estimate → стабильнее headline (особенно тонкие выборки бизнес/премиум, см. #1795). - Полноценная кросс-валидация Авито↔Циан↔Яндекс. ## Связано - #1795 (завышение премиума — частично из-за тонких выборок; Avito-покрытие усугубляет). - #788/#805 (avito mobile proxy), runbook `avito_mobile_proxy.md`. - Web-пробинг Avito — ТОЛЬКО через playwright MCP (антибот), не curl (правило проекта). Источник: live smoke 2026-06-19 + scrape_runs аудит.
Author
Owner

Решено (2026-06-20) — root cause: прод-override AVITO_PROXY_MAX_ROTATIONS=0

Диагноз

Прокси (auv.mobileproxy.space:10049) + camoufox здоровы — одиночные фетчи работают: тест fetch_around(56.8332, 60.5946)page=1: 58 lots, без бана. Avito — крупнейший источник (23877 листингов за 7д). Detail_backfill / newbuilding_sweep отрабатывают.

Банились только длинные свипы (avito_full_load, avito_city_sweep). Причина — в .env.runtime стоял AVITO_PROXY_MAX_ROTATIONS=0, перебивая код-дефолт 4 (config.py:250). В avito.py:458 max_rot = avito_proxy_max_rotations if rotate_url else 0 → при 0 цикл if rot_done < max_rot НИКОГДА не ротирует реактивно. Проактивная ротация одна на старте; первый же firewall в середине свипа → AvitoBlockedErrormark_banned. Сам код это комментирует: «реактивного бюджета max_rotations не хватает (3 подряд блока → mark_banned)».

(Вероятно 0 выставили при отладке прокси 18–19.06 и забыли вернуть.)

Фикс (env, без деплоя)

/opt/gendesign/tradein-mvp/backend/.env.runtime: AVITO_PROXY_MAX_ROTATIONS=0 → 4 (бэкап .env.runtime.bak-20260620-avitorot), пересозданы browser + scraper (docker compose -p gendesign-tradein up -d --force-recreate browser scraper), env=4 подтверждён в обоих контейнерах. Переживёт деплои (.env.runtime ведётся вручную на VPS).

Подтверждено на реальной загрузке (run_id=260, avito_full_load INCREMENTAL)

07:38:24  avito page=1 browser firewall — retry after rotation #1   ← реактивная ротация (была отключена при =0)
07:39:25  bucket studii 0–4M  saved → 58 уникальных
07:42:07  bucket studii 4–5M  saved → 138
07:43:49  bucket studii 5–6M  saved → 199

Свип поймал firewall на page=1, ротировал IP и продолжил (вместо мгновенного бана), идёт по бакетам room×price, run держался running ≥8 мин без banned. Именно тот сценарий, что раньше = instant ban.

Эффект

Свипы восстанавливают свежее покрытие Avito → больше аналогов на estimate (особенно тонкие бизнес/премиум выборки, #1795) + полноценная кросс-валидация Авито↔Циан↔Яндекс.

Follow-up (опционально)

Можно вовсе убрать строку AVITO_PROXY_MAX_ROTATIONS из .env.runtime → упадёт на код-дефолт 4 (чище, чем явный override). Сейчас оставлен =4 явно.

Закрываю.

## ✅ Решено (2026-06-20) — root cause: прод-override `AVITO_PROXY_MAX_ROTATIONS=0` ### Диагноз Прокси (`auv.mobileproxy.space:10049`) + camoufox **здоровы** — одиночные фетчи работают: тест `fetch_around(56.8332, 60.5946)` → `page=1: 58 lots`, без бана. Avito — крупнейший источник (23877 листингов за 7д). Detail_backfill / newbuilding_sweep отрабатывают. Банились только **длинные свипы** (`avito_full_load`, `avito_city_sweep`). Причина — в `.env.runtime` стоял **`AVITO_PROXY_MAX_ROTATIONS=0`**, перебивая код-дефолт `4` (`config.py:250`). В `avito.py:458` `max_rot = avito_proxy_max_rotations if rotate_url else 0` → при `0` цикл `if rot_done < max_rot` НИКОГДА не ротирует реактивно. Проактивная ротация одна на старте; первый же firewall в середине свипа → `AvitoBlockedError` → `mark_banned`. Сам код это комментирует: «реактивного бюджета max_rotations не хватает (3 подряд блока → mark_banned)». (Вероятно `0` выставили при отладке прокси 18–19.06 и забыли вернуть.) ### Фикс (env, без деплоя) `/opt/gendesign/tradein-mvp/backend/.env.runtime`: `AVITO_PROXY_MAX_ROTATIONS=0 → 4` (бэкап `.env.runtime.bak-20260620-avitorot`), пересозданы `browser` + `scraper` (`docker compose -p gendesign-tradein up -d --force-recreate browser scraper`), env=4 подтверждён в обоих контейнерах. Переживёт деплои (`.env.runtime` ведётся вручную на VPS). ### Подтверждено на реальной загрузке (run_id=260, avito_full_load INCREMENTAL) ``` 07:38:24 avito page=1 browser firewall — retry after rotation #1 ← реактивная ротация (была отключена при =0) 07:39:25 bucket studii 0–4M saved → 58 уникальных 07:42:07 bucket studii 4–5M saved → 138 07:43:49 bucket studii 5–6M saved → 199 ``` Свип поймал firewall на page=1, **ротировал IP и продолжил** (вместо мгновенного бана), идёт по бакетам room×price, run держался `running` ≥8 мин без `banned`. Именно тот сценарий, что раньше = instant ban. ### Эффект Свипы восстанавливают свежее покрытие Avito → больше аналогов на estimate (особенно тонкие бизнес/премиум выборки, #1795) + полноценная кросс-валидация Авито↔Циан↔Яндекс. ### Follow-up (опционально) Можно вовсе убрать строку `AVITO_PROXY_MAX_ROTATIONS` из `.env.runtime` → упадёт на код-дефолт `4` (чище, чем явный override). Сейчас оставлен `=4` явно. Закрываю.
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#1796
No description provided.