fix(cian): капча/страница ошибки Циана (HTTP 200) — отказ площадки в сайдкаре и kit, ротация аренды внутри батча (#3402) #3403
No reviewers
Labels
No labels
Fable 5 ревью
GG-форсайт
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
feedback/max
generative
needs-discussion
needs-human
observability
pause-bots
performance
priority/p0
priority/p1
priority/p2
priority/p3
scope/backend
scope/db
scope/devops
scope/frontend
scope/qa
scrapers
security
site-finder
stage/1
stage/2
status/blocked
status/done
status/needs-analysis
status/needs-fix
status/qa
status/ready
status/review
status/wip
tech-debt
tradein
ux
week ревью 1
wontfix
ИРД
вторичка
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#3403
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/cian-captcha-is-platform-refusal"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #3402.
Дефект. Циан отдаёт капчу (
Captcha - база объявлений ЦИАН, 44 КБ) и «Ошибка - Циан» с HTTP 200; детектор бан-страниц сайдкара их не знал → HTML уходил как успех →extract_state(... "defaultState")→ None → «defaultState extraction failed» →cian_history_backfill(=cian_detail_backfill) держал одну аренду на весь батч и сжигал 210–400 карточек через капча-узел (6200: 0/210; шесть прогонов 04–05.09: 0/400; через здоровый узел 13: 161/162). Проба одной карточки по узлам: 13 — карточка, 14 — капча, 1 — «Ошибка». База: 14 028 из 20 451 активных cian без detail.Слой 1 — сайдкар (
browser/server.py:1978-1994, хуки:2374,:2417):_CIAN_REFUSAL_TITLESпо<title>(нормализация пробелов/регистра/тире), per-providercian→BanPageDetectedError→ существующий путь (#3379): 403 +ban_page: true+status: 200(upstream честно). Словоcaptchaв нормальной карточке (×11) не триггер — только title.Слой 2 — kit (
providers/cian/detail.py:109-117, :243-256, :170-181; образы деплоятся раздельно): при провалеextract_stateс опознанным title →report_platform_banпо живой аренде +raise CianBlockedError(лог «капча/страница ошибки Циана (title=…)»); без маркеров — прежнийNone;except SidecarBanPageErrorперед общимexcept— отказ, опознанный сайдкаром, больше не гасится вNone(иначе ротация чинилась бы, а прогон рапортовал «0/400 done»).Ротация внутри батча — правок в
cian_history_backfillне потребовалось:report_platform_ban(browser_fetcher.py:886, публичное имя вместо_report_platform_ban— переименованы 2 внутренних вызова + комментарии) →report_ban(mark_bannedпары узел×cian,acquire("cian")его больше не выдаст) +_report_fetch_result(False, health=False)→ на 3-й капче_LEASE_ROTATE_AFTER_FAILS→_acquire_lease()(:861-884), следующий/fetchс нового узла.Тесты:
browser/test_server_cian_captcha.py(7: маркеры, «captcha в карточке ≠ бан», тире,_fetch_once→BanPageDetectedError,fetch_handler→ 403+ban_page+status:200, чужой провайдер не банится);tests/test_3402_cian_captcha_http200.py(капча/ошибка →CianBlockedError+ рапорт; HTML без state и маркеров →None; батч через настоящийfetch_detail+ фейковый фетчер: капча на первом узле → рапорт, второй листинг обогащён).Фальсификация (
git apply -Rkit-файлов): 3 failed — оба листинга сожжены на одном узле,капча не отрапортована пулу — узел доработает батч, в логе прежние «extraction failed». Восстановлено.Прогоны: backend
5598 passed, 35 skipped(rc=0); сайдкар241 passed(rc=0); ruff OK (server.pyвне скоупа хуков, не форматировался).Приёмка на проде (после ОБОИХ образов): следующий
cian_detail_backfill—listings_succeeded > 0; в логах капча-узлаlease id=N (cian) BANNED — reporting to pool: … капча/страница ошибки Цианаи при трёх подрядпровалил 3 /fetch подряд — меняем прокси; «defaultState extraction failed» на капче — 0; строка вscrape_proxy_source_bansдля пары узел×cian. Не в PR:ban_kindдля капчи остаётсяNone(_note_refusalсудит по статусу, тут честный 200) — решение уровня #3196.Циан отдаёт капчу (`<title>Captcha - база объявлений ЦИАН`, 44 КБ) и страницу ошибки (`<title>Ошибка - Циан`, 374 КБ) с кодом 200. Детектор сайдкара их не знал (_REFUSAL_STATUSES {403,429} + маркеры Авито/Домклика), HTML уезжал клиенту как успех, extract_state возвращал None и провайдер печатал «defaultState extraction failed» — отказ ПЛОЩАДКИ читался как дрейф НАШЕЙ разметки. Аренда при этом не менялась: fetch() уже отрапортовал mark_health(ok=True), fail-streak обнулялся, и один капча-узел сжигал батч целиком (6200: 0/210; 6123/6091/6052/6032/6010/5981: 0/400 — против 161/162 через здоровый узел на прогоне 13). Два слоя, потому что образы backend и browser деплоятся раздельно и расходятся на часы: * сайдкар (browser/server.py) — детект по <title> на обоих путях (navigate и подзапрос) → BanPageDetectedError → прежний путь #3288/#3379: 403 + ban_page + ЧЕСТНЫЙ upstream-статус 200; * kit (providers/cian/detail.py) — при провале extract_state те же маркеры → CianBlockedError вместо тихого None, плюс report_platform_ban по живому lease. Там же ветка SidecarBanPageError: отказ, опознанный сайдкаром, больше не гасится общим `except` в «не смогли разобрать». Слово `captcha` признаком быть не может: в нормальной карточке оно встречается 11 раз, на капче 17. Детект по <title> с нормализацией тире. `_report_platform_ban` → `report_platform_ban` (публичный): тем же путём обязан идти отказ, распознанный не сайдкаром, а провайдером. report_ban один только пишет бан пары «узел×источник» — сменить сожжённую аренду ВНУТРИ батча позволяет только fail-streak (_LEASE_ROTATE_AFTER_FAILS).Code-review (06.09): ⚠️ minor. Подтверждено: маркеры только по
<title>в обоих слоях (кортежи побайтово равны), SERP-путь не регрессирует (except Exception → [], но теперь узел рапортуется),acquire("cian")забаненный узел не вернёт (scrape_proxy_source_bansфильтруется),NoProxyAvailableErrorиз ре-acquire намеренно глотается вreport_platform_ban(#3288), изfetch_detailпо-прежнему летит;CianBlockedErrorв бэкфилле не раститban_kinds(статус 200/None) → преждевременногоbannedнет; переименование чистое (0 вхождений старого имени); тесты через настоящие_fetch_once/fetch_handler/fetch_detail.Прод-датум по вопросу ревью (09:25 UTC, повторная проба по узлам): узел 14 — уже настоящая карточка (капча снялась за ~2 ч); узел 1 — третий вариант:
<title>Вы не робот?</title>, 16 КБ (час назад там была «Ошибка - Циан», 374 КБ). Доработка: капча = «Captcha…» + «Вы не робот?» (бан+ротация); «Ошибка - Циан» — на цикл наблюдения только лог (без бана/raise) в обоих слоях. Follow-up после деплоя:ban_kinds["platform"]по ТИПУCianBlockedError(сейчас капча-волна в отчёте прогона всё ещё «не разобрали»); curl-путьfetch_detail(pipeline.py:3113/3750,session=) детектит, но не банит — узел успевает получитьmark_health(ok=True); первый cian-sweep после деплоя — посмотретьerrors_count/abort detail-фазы (капча теперь не обнуляет_cian_detail_consec_failures).