fix(tradein/browser): снятый PoW-челлендж отдавался с протухшим статусом, и карточка выбрасывалась (#3283) #3306
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
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#3306
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/3283e-pow-resolved-page-discarded"
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?
Проблема
Сайдкар уже пережидает челлендж QRATOR и уже его снимает. Но
_last_response_status[provider]пишется один раз, из ответа первогоgoto(server.py:2103), а_wait_out_pow_challengeего не обновляет. Наружу уходило{"html": <нормальная карточка>, "status": 439}— и клиентavito/detail.pyбраковал её по одному коду, не заглянув в HTML.Замер на проде
Прогон 5606, одни и те же объявления:
Минимум 3 блока из 7 в прогоне — страницы, которые сайдкар уже вытащил, а клиент выбросил.
Почему не «поймать свежий статус»
Рассматривался вариант с
page.on("response"). Он не работает: PoW-страница чинит себя собственнымwindow.location = location.href, Response на который мы не наблюдаем (опрашиваемcontent()), а собственныйpage.reload()включается только послеBROWSER_CHALLENGE_RELOAD_AFTER_MS=8000. На проде челлендж снимался за 1-9 с — то есть в типичном случае наш reload вообще не срабатывает и достоверного ответа на устоявшийся контент нет.Поэтому на успешном выходе статус сбрасывается в
None(«неизвестен»), а не тащится протухшим.Почему клиента править не нужно
providers/avito/detail.py:606—if status is not None:; приNoneработа идёт по html-эвристикам_is_firewall_page/_is_detail_soft_block, которые на настоящем контенте не срабатывают, а на настоящем отказе — срабатывают. Прямой403/439отgoto(без прохода через_wait_out_pow_challenge) по-прежнему ловится как блок. SERPlast_response_statusвообще не читает.backend/tests/test_3044_avito_439_classified_as_block.py— зелёный без единой правки (4 passed).Побочные эффекты
ChallengeTimeoutError) остаётся отказом — сброс стоит после всехraise, единственный успешный выход._wait_out_pow_challenge.Проверка
219 passed— набор сайдкара, запущенный так же, как его гоняет CI (отдельный envpytest + aiohttp, а не backend-венв).Сайдкар уже пережидает челлендж QRATOR и уже его снимает, но _last_response_status[provider] остаётся статусом challenge-страницы: он пишется один раз, из ответа первого goto, а _wait_out_pow_challenge его не обновляет. Наружу уходило {"html": <нормальная карточка>, "status": 439}, и клиент avito/detail.py браковал её по одному коду, не заглянув в HTML. Прод, прогон 5606 — одни и те же объявления: 13:15:23 сайдкар: PoW снят за ~9000мс, догидрация ...8242031370 13:15:28 скрапер: BLOCKED #1 HTTP 439 ...8242031370 13:22:33 сайдкар: PoW снят за ~3000мс, догидрация ...8272722582 13:22:37 скрапер: BLOCKED #11 HTTP 439 ...8272722582 Минимум 3 блока из 7 в прогоне — выброшенные страницы, уже вытащенные. Ловить «свежий» статус нечем: PoW-страница чинит себя своим window.location-редиректом, Response на который мы не наблюдаем, а собственный page.reload() включается только после 8с — при снятии за 1-9с он обычно не срабатывает вовсе. Поэтому на успешном выходе статус сбрасывается в None («неизвестен»), а не тащится протухшим. Клиент None блоком не считает (detail.py: `if status is not None`) и падает на html-эвристики, которые на настоящем контенте не срабатывают. Правка в общей функции, поэтому чинит и ветку DomClick. Провал ожидания (ChallengeTimeoutError) остаётся отказом: сброс стоит после всех raise. Клиента править не потребовалось — test_3044_avito_439_classified_as_block зелёный без изменений. Тесты сайдкара: 219 passed.