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
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#788
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "feat/623-avito-mobile-proxy"
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 банит datacenter-IP прод-сервера (TIMEWEB) — отдаёт HTTP 200 с firewall-страницей «Доступ ограничен: проблема с IP», а не 403. Из-за этого SERP-скрейпер не получает ни карточек, ни дат (#623), а
sortTimeStamp-фикс #726 инертен (нет HTML для парса). Проверено вживую с сервера: мобильный прокси (mobileproxy.space) снимает firewall — 0 → 48 карточек.Изменения
avito.py__aenter__: если заданAVITO_PROXY_URL→proxies=вcurl_cffi.AsyncSession. Пусто → прямое подключение (dev, поведение не меняется)._is_firewall_page(): детект firewall-интерстициала по маркерам в<head>→ HTTP 200-бан больше не проходит молча._fetch_serp_html(): единая точка fetch — на 403/429/firewall дёргает_rotate_ip()(changeip,&format=json, sleep ~9с) и повторяет доavito_proxy_max_rotations; транзиентные сетевые обрывы — retry без ротации.fetch_aroundпереведён на_fetch_serp_html(парс/пагинация не тронуты;AvitoContentBlockedErrorна честных 0-cards сохранён — селектор-дрейф, не IP-бан).config.py—avito_proxy_url,avito_proxy_rotate_url,avito_proxy_max_rotations.#726 (TZ-фикс) —
sortTimeStamp(UTC epoch-ms) →.date()в MSK (UTC+3 fixed offset). Совпадает с датой на сайте; устраняет off-by-one для постов 00:00–03:00 MSK. Fixed offset — без зависимости от tzdata в контейнере.Тесты
test_avito_anti_bot.py: firewall на HTTP 200 →AvitoBlockedError; ротация IP + успешный повтор; исчерпанная ротация → raise.test_avito_serp_date.py: переведён на MSK.Live-verification (прод 94.228.121.73)
188.162.65.168 → 94.25.229.234за ~9с.sortTimeStampсверен сitem-view/item-datedetail-страницы (UTC+3 совпало).Деплой (вне PR)
Требует #659 deploy + env на VPS
/opt/gendesign/tradein-mvp/.env.runtime:AVITO_PROXY_URL,AVITO_PROXY_ROTATE_URL(значения — vaultmeta/00_credentials.md→ Mobile Proxy). Без env поведение не меняется.Refs #623, #726. Detail-скрейпер через прокси — follow-up.
✅ APPROVE
Avito mobile-proxy egress + firewall-детект + MSK-дата (#623/#726).
Security tripwire — clear: литеральных credentials в диффе нет.
avito_proxy_url/avito_proxy_rotate_urldefaultNone, значения из env/.env.runtime (vault, вне PR); тесты используют фейковыйhttps://changeip.example/?proxy_key=x. Нет 40-char hex/key/JWT.Correctness
_MSK = timezone(timedelta(hours=3)),.date()в MSK — закрывает ровно UTC off-by-one advisory, который я отметил на #729. Fixed offset (без DST/tzdata-зависимости), совпадает с датой на сайте.proxies=только еслиavito_proxy_urlзадан, иначе direct (dev не меняется). curl_cffi зеркалит requests'proxiesdict — live-verified (48 карточек через прокси)._is_firewall_pageсканит первые 4096 символов на маркеры — ловит HTTP-200 IP-бан интерстициал (корень #623, из-за которого #726 был инертен)._fetch_serp_html: bounded loop — транзиентные ошибки retry ≤2 (без ротации), 403/429/firewall → rotate ≤max_rotзатем raise (429→RateLimited, else→Blocked), non-200→None. Терминируется.AvitoContentBlockedError(page-1 empty-parse, #779) сохранён и отличается от firewall-бана._rotate_ip: changeip API дёргается напрямую (не через прокси), 9с на modem settle, best-effort.Tests — firewall→Blocked, rotate-then-success (2 get), rotation-exhausted→Blocked, date→MSK. 17 passed, ruff + pre-commit clean. Live prod-верификация задокументирована.
Deploy safety — инертно без env (direct = текущее поведение); прокси активируется только после ops-настройки VPS env (задокументировано, вне PR). Нет миграции.
Scope/security — config.py + avito.py + тесты; нет secrets, нет self-extending триггера.
Verdict: ✅ APPROVE (#623/#726). Deploy требует ops env-config; live re-scrape coverage → qa.
bot-analyst referenced this pull request2026-05-31 07:04:24 +00:00