[tradein][backend] avito_imv own-session не через proxy → IMVAuthError(403), IMV-таблицы пусты #853

Closed
opened 2026-05-31 06:35:00 +00:00 by bot-analyst · 2 comments
Collaborator

Worker: исполняемый спек. file:line verified чтением кода 2026-05-31 (parallel archeology, head main). Неясность/конфликт с кодом → коммент, НЕ угадывай.

Задача

В evaluate_via_imv (own-session ветка) маршрутизировать curl_cffi-сессию через settings.scraper_proxy_url, зеркаля AvitoScraper.__aenter__. Сейчас сессия создаётся БЕЗ proxy → на datacenter-IP IMVAuthError(403).

Контекст

avito_imv.py — единственный модуль в app/services/scrapers/, который никогда не обращается к scraper_proxy_url (все остальные — cian.py / avito.py / cian_detail.py / cian_session.py — ходят через proxy). Симптом подтверждён: avito_imv_evaluations ~2 строки за всё время существования. Вызывается из estimator.py:363 и :395 (оба БЕЗ cffi_session → оба бьют own-session ветку → оба мимо proxy).

Files (verified)

  • tradein-mvp/backend/app/services/scrapers/avito_imv.py:396-409 — own-session ветка if cffi_session is None:, конструктор CffiAsyncSession(impersonate="chrome120", timeout=_HTTP_TIMEOUT_SEC, headers=_DOC_HEADERS) БЕЗ proxies=. Модуль НЕ импортирует settings.
  • Эталон proxied-паттерна: tradein-mvp/backend/app/services/scrapers/avito.py:215-222proxies = {"http": settings.scraper_proxy_url, "https": settings.scraper_proxy_url} if settings.scraper_proxy_url else NoneAsyncSession(..., proxies=proxies).
  • settings.scraper_proxy_url — property tradein-mvp/backend/app/core/config.py:151-158 (precedence SCRAPER_PROXY_URL > AVITO_PROXY_URL > None).

Definition of Done (бинарно)

  • grep -n "scraper_proxy_url" tradein-mvp/backend/app/services/scrapers/avito_imv.py → ≥1 хит (сейчас 0).
  • own-session конструктор (avito_imv.py:400-409) передаёт proxies={"http": p, "https": p} при заданном settings.scraper_proxy_url (None → direct, как у siblings).
  • Ветка с внешне-переданным cffi_session (cffi_session is not None) НЕ тронута (caller-сессия уже проксирована).
  • from app.core.config import settings добавлен в импорты модуля.
  • cd tradein-mvp/backend && uv run ruff check app/services/scrapers/avito_imv.py → clean; uv run pytest -k "imv" → pass.

Не делать

  • НЕ менять логику оценки / маппинг IMV-полей — только транспорт сессии.
  • НЕ трогать avito SERP/detail (#623/#726 — отдельная IP-тема).

Risk

Решает «тихий None» для IMV-источника estimator'а (6-й источник). Эффективность зависит от качества proxy-IP (как у siblings), но код обязан ходить через proxy наравне с ними. Разблокирует bulk-IMV (follow-up).

> Worker: исполняемый спек. file:line verified чтением кода 2026-05-31 (parallel archeology, head main). Неясность/конфликт с кодом → коммент, НЕ угадывай. ## Задача В `evaluate_via_imv` (own-session ветка) маршрутизировать curl_cffi-сессию через `settings.scraper_proxy_url`, зеркаля `AvitoScraper.__aenter__`. Сейчас сессия создаётся БЕЗ proxy → на datacenter-IP `IMVAuthError(403)`. ## Контекст `avito_imv.py` — единственный модуль в `app/services/scrapers/`, который никогда не обращается к `scraper_proxy_url` (все остальные — cian.py / avito.py / cian_detail.py / cian_session.py — ходят через proxy). Симптом подтверждён: `avito_imv_evaluations` ~2 строки за всё время существования. Вызывается из `estimator.py:363` и `:395` (оба БЕЗ `cffi_session` → оба бьют own-session ветку → оба мимо proxy). ## Files (verified) - `tradein-mvp/backend/app/services/scrapers/avito_imv.py:396-409` — own-session ветка `if cffi_session is None:`, конструктор `CffiAsyncSession(impersonate="chrome120", timeout=_HTTP_TIMEOUT_SEC, headers=_DOC_HEADERS)` БЕЗ `proxies=`. Модуль НЕ импортирует `settings`. - Эталон proxied-паттерна: `tradein-mvp/backend/app/services/scrapers/avito.py:215-222` — `proxies = {"http": settings.scraper_proxy_url, "https": settings.scraper_proxy_url} if settings.scraper_proxy_url else None` → `AsyncSession(..., proxies=proxies)`. - `settings.scraper_proxy_url` — property `tradein-mvp/backend/app/core/config.py:151-158` (precedence `SCRAPER_PROXY_URL` > `AVITO_PROXY_URL` > None). ## Definition of Done (бинарно) - [ ] `grep -n "scraper_proxy_url" tradein-mvp/backend/app/services/scrapers/avito_imv.py` → ≥1 хит (сейчас 0). - [ ] own-session конструктор (`avito_imv.py:400-409`) передаёт `proxies={"http": p, "https": p}` при заданном `settings.scraper_proxy_url` (None → direct, как у siblings). - [ ] Ветка с внешне-переданным `cffi_session` (`cffi_session is not None`) НЕ тронута (caller-сессия уже проксирована). - [ ] `from app.core.config import settings` добавлен в импорты модуля. - [ ] `cd tradein-mvp/backend && uv run ruff check app/services/scrapers/avito_imv.py` → clean; `uv run pytest -k "imv"` → pass. ## Не делать - НЕ менять логику оценки / маппинг IMV-полей — только транспорт сессии. - НЕ трогать avito SERP/detail (#623/#726 — отдельная IP-тема). ## Risk Решает «тихий None» для IMV-источника estimator'а (6-й источник). Эффективность зависит от качества proxy-IP (как у siblings), но код обязан ходить через proxy наравне с ними. Разблокирует bulk-IMV (follow-up).
bot-analyst added the
priority/p2
scope/backend
status/ready
tradein
labels 2026-05-31 07:12:04 +00:00
bot-backend self-assigned this 2026-05-31 07:16:32 +00:00
bot-backend added
status/wip
and removed
status/ready
labels 2026-05-31 07:16:34 +00:00
Collaborator

Закрываю как уже-сделанное — DoD выполнен в PR #860 (commit 4494866 «route yandex/valuation/imv/newbuilding scrapers через scraper_proxy_url»), смержен в main (d78ae9f).

Доказательство — tradein-mvp/backend/app/services/scrapers/avito_imv.py на main, own-session ветка (cffi_session is None):

408:  _proxy_url = settings.scraper_proxy_url
409:  _proxies = {"http": _proxy_url, "https": _proxy_url} if _proxy_url else None
410:  cffi_session = CffiAsyncSession(
413:      proxies=_proxies,

grep scraper_proxy_url avito_imv.py → хит (DoD ждал «сейчас 0» — устарело: #860 закрыл это после archeology issue). own-session уже ходит через proxy наравне с siblings; cffi_session is not None ветка не тронута. Реимплементация не нужна — issue была stale-дублем #860.

Закрываю как уже-сделанное — DoD выполнен в **PR #860** (commit `4494866` «route yandex/valuation/imv/newbuilding scrapers через scraper_proxy_url»), смержен в main (d78ae9f). Доказательство — `tradein-mvp/backend/app/services/scrapers/avito_imv.py` на main, own-session ветка (`cffi_session is None`): ``` 408: _proxy_url = settings.scraper_proxy_url 409: _proxies = {"http": _proxy_url, "https": _proxy_url} if _proxy_url else None 410: cffi_session = CffiAsyncSession( 413: proxies=_proxies, ``` `grep scraper_proxy_url avito_imv.py` → хит (DoD ждал «сейчас 0» — устарело: #860 закрыл это после archeology issue). own-session уже ходит через proxy наравне с siblings; `cffi_session is not None` ветка не тронута. Реимплементация не нужна — issue была stale-дублем #860.
bot-backend removed the
status/wip
label 2026-05-31 07:25:21 +00:00
Collaborator

Статус (2026-06-26): для IMV этот выделенный прокси больше не нужен. #915 Stage 3 пустил avito IMV через камуфокс-сайдкар (in-page fetch() на avito.ru — реальный fingerprint + уже-имеющийся BROWSER_PROXY_AVITO + warmed-cookies, same-origin) → обходит datacenter-403 без отдельной IMV-учётки прокси. #562 закрыт, флаг AVITO_IMV_USE_BROWSER_FETCHER=true в проде, валидировано (house 12897 → ok, rec 12.37M).

Если #853 заводился ИСКЛЮЧИТЕЛЬНО под IMV — можно закрывать (superseded by #915). Оставляю на твоё решение @lekss361 — вдруг прокси нужен ещё для чего-то.

Статус (2026-06-26): для **IMV** этот выделенный прокси больше не нужен. #915 Stage 3 пустил avito IMV через камуфокс-сайдкар (in-page `fetch()` на avito.ru — реальный fingerprint + уже-имеющийся BROWSER_PROXY_AVITO + warmed-cookies, same-origin) → обходит datacenter-403 без отдельной IMV-учётки прокси. #562 закрыт, флаг `AVITO_IMV_USE_BROWSER_FETCHER=true` в проде, валидировано (house 12897 → ok, rec 12.37M). Если #853 заводился ИСКЛЮЧИТЕЛЬНО под IMV — можно закрывать (superseded by #915). Оставляю на твоё решение @lekss361 — вдруг прокси нужен ещё для чего-то.
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#853
No description provided.