fix(avito): reconnect-retry on SERP 403/firewall under backconnect proxy #1764
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#1764
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/avito-403-backconnect-reconnect-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?
Problem (prod run 211, banned)
avito_full_loadaborts the entire 7-room×price sweep on the first HTTP 403 under the backconnect proxy.In
_fetch_serp_html(curl_cffi path),max_rot = avito_proxy_max_rotations if avito_proxy_rotate_url else 0. The backconnect proxy (mproxy.site:14619) has noavito_proxy_rotate_url→max_rot=0→ the existing changeip-rotation path is skipped → the first 403 (or HTTP-200 firewall interstitial) raisesAvitoBlockedError→run_avito_full_loadcatches it →mark_banned→ whole run aborts.Run 211 banned at room 2/7 on a 403 at
room_1_komn13–17M, page 2 (firewall=False— not DataDome, not 429). The existing 429 short-retry didn't apply. So conc=1 is not actually "clean" — it survives only until the first flagged exit IP.Verified: the backconnect proxy assigns a fresh exit IP per new connection (5 sequential requests → 5 distinct IPs). A 403 means only the current exit IP is flagged; opening a new connection escapes it. A keep-alive curl_cffi session reuses the same CONNECT tunnel (same IP), so the retry must rebuild the session.
Fix
Mirror the existing
_AVITO_429_MAX_RETRIESpattern for 403/firewall under backconnect mode:_AVITO_403_MAX_RETRIES = 5,_AVITO_403_BACKOFF_SEC = 2.0._build_cffi_session()from__aenter__; added_reset_cffi()(close + rebuild → new tunnel → fresh exit IP)._fetch_serp_html:backconnect = bool(scraper_proxy_url) and not avito_proxy_rotate_url; on 403/firewall (NOT 429) under backconnect,_reset_cffi()+ backoff + retry up to 5× before raising.Legacy single-IP changeip rotation and browser-mode paths are unchanged; the new branch is gated off whenever a
rotate_urlexists.Tests
New
tests/scrapers/test_avito_403_backconnect_reconnect.py(4 tests): 403→403→200 reconnect, firewall→200 reconnect, 403 exhausted → still raises, non-backconnect (rotate_url set) → no reconnect path. Full avito suite: 274 passed. Ruff clean.Fixes the run-211 abort; needed regardless of the backconnect-purchase decision.