fix(avito): считать HTTP 439 блокировкой, а не концом выдачи #3065

Merged
lekss361 merged 1 commit from fix/avito-439-and-context into main 2026-08-23 21:49:36 +00:00

1 commit

Author SHA1 Message Date
bot-backend
5d0206d972 fix(avito): считать HTTP 439 блокировкой, а не концом выдачи
All checks were successful
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / changes (pull_request) Successful in 10s
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
CI Trade-In / changes (pull_request) Successful in 8s
CI Trade-In / backend-tests (pull_request) Successful in 4m26s
439 — нестандартный код, которым QRATOR отвечает на странице-челлендже
Avito. Его нет ни в одном RFC, поэтому он не попал ни в один список
«это блок» — и обе точки входа трактовали его как штатный исход:

  SERP   проваливался в `if sc != 200: return None` — пагинация мирно
         останавливалась, будто страницы кончились. Ни ротации IP, ни
         _report_ban, ни пометки прогона banned.
  detail доходил до `if sc != 200: raise ValueError` — то есть считался
         ошибкой разбора страницы, без реконнекта на свежий exit-IP и
         без ban-сигнала.

То есть обе ветки молчали ровно там, где нас блокировали. Отсюда
прогоны с диагнозом «причина НЕ установлена» (#2700) при том, что у
отказа был вполне чёткий HTTP-код: за 14 дней 43 из 82 прогонов
avito-семейства (52%) завершились failed/banned, и часть из них —
именно этот класс тихого отказа.

439 подключён к УЖЕ СУЩЕСТВУЮЩЕЙ 403-ветке, а не новым механизмом:
тот же смысл (текущий exit-IP признан подозрительным), то же лечение
(смена IP, а не повтор на той же сессии). В serp.py — в условие
блока и в backconnect-reconnect; в detail.py — в блок-ветку.

Заодно текст AvitoBlockedError в detail.py перестал жёстко печатать
"403": на 439 он врал бы в логах ровно там, где по логу и ставят
диагноз.

Тест test_3044 параметризован по [403, 439] намеренно — не ради
полноты, а чтобы стеречь ПАРИТЕТ: 403 заведомо рабочая ветка, и если
кто-то перепишет блок-логику и уронит только 439, упадёт половина
кейсов и сразу покажет, что ветки разъехались.

Проверено:
  - фальсификация на коде до правки: 403-кейсы проходят, 439-кейсы
    падают (SERP «DID NOT RAISE», detail «ValueError: HTTP 439»)
  - регрессия: 421 passed, 2 skipped (-k "avito or ban_kind or
    proxy_pool or browser_routing")

#3035 (обрезка ?context= в avito_detail_backfill) в этот коммит НЕ
входит — см. комментарий в issue: замер показал, что query несут все
55 140 avito-URL, а та же обрезка стоит ещё в двух местах kit'а, и
знак эффекта от её снятия неизвестен.

Refs #3044, #2700
2026-08-24 00:20:38 +03:00