feat(tradein): avito curl_cffi 429 short-retry — enables backconnect curl SERP (×50 faster than browser) #1762
No reviewers
Labels
No labels
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
Fable 5 ревью
feedback/max
generative
GG-форсайт
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#1762
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "feat/avito-curl-429-retry"
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?
Прорыв
avito SERP можно тянуть curl_cffi (chrome-impersonation) через backconnect rotating mobile-прокси БЕЗ браузера — провалидировано на проде:
_parse_htmlкорректно вытащил 36 лотов из curl-HTML (source_id/price/rooms/floor/address/segment/url).avito.py УЖЕ поддерживает curl-режим (
settings.scraper_fetch_mode="curl_cffi") — прод был форсирован вbrowser(#901, когда curl банился на datacenter-IP). Backconnect (rotating mobile + curl_cffi chrome-TLS) снимает бан.Проблема, которую чинит этот PR
Backconnect имеет лимит 5 одновременных соединений → при параллельной пагинации отдаёт 429 (transient — проходит на коротком retry). Текущий код трактует 429 как ban:
_rotate_ip()(9с!) илиraise AvitoRateLimitedError→ весь прогон mark_banned. Объёмный тест: 8% запросов ловили 429 от лимита соединений.Решение
В curl-пути
_fetch_serp_html— 429 short-retry ОТДЕЛЬНО от 403/firewall:sc == 429→ до_AVITO_429_MAX_RETRIES=4коротких retry (sleep _AVITO_429_BACKOFF_SEC=1.5с+ jitter, re-GET), БЕЗ ротации. Backconnect conn-limit = transient.AvitoRateLimitedError).AvitoBlockedError).transient_left/rot_done/r429независимы и ограничены (нет вечного цикла). Browser-режим/_parse_html/seed-grid/proxy не тронуты.Изменения
scrapers/avito.py(+22) — константы_AVITO_429_MAX_RETRIES/_AVITO_429_BACKOFF_SEC+ 429-retry ветка в curl while-цикле.tests/scrapers/test_avito_anti_bot.py(+136, 5 тестов) — 429×2→200 без rotate; 429-persistent→AvitoRateLimitedError после 4×; 429+rotate-url→rotation; 403→немедленный AvitoBlockedError (не через 429-путь).Тесты
Full suite: 2004 passed, 1 skipped, 0 failed.
Деплой-конфиг (применяю после merge, .env.runtime — изолировано от cian/yandex)
SCRAPER_FETCH_MODE=curl_cffi(avito → curl; cian/yandex не зависят от него).SCRAPER_PROXY_URL=<backconnect http endpoint>(avito curl egress; cian=CIAN_PROXY_URL/kf, yandex=YANDEX_PROXY_URL/ti — НЕ тронуты).concurrency=4(headroom под 5-конн backconnect).BROWSER_PROXY_AVITO— остаётся (browser для avito detail/newbuilding путей).Прод-смоук после merge+deploy
Запустить avito_full_load (curl-режим) → полный свип: измерить покрытие (active вторичка) + темп (ожидается минуты vs часы) + watch 429/DataDome.