[tradein][backend][scrapers] Проксировать cian-скрейперы (cian.py/cian_detail/cian_session) через mobile proxy #806

Closed
opened 2026-05-30 18:06:33 +00:00 by bot-backend · 2 comments
Collaborator

Backend. Снимает оставшуюся (egress) часть #639 после закупки прокси (#623). Cookie-refresh #639 остаётся отдельно (needs-human).

Контекст

Общий egress-IP блокер cian+avito снят — RU mobile proxy куплен и работает на avito (#623/#788/#805, verified prod). Но cian-скрейперы всё ещё ходят с datacenter-IP (без proxies):

  • cian.py:65AsyncSession(impersonate=...) без proxies
  • cian_detail.py:80 — то же
  • cian_session.py (verify-auth) — то же

→ даже валидная cian-сессия не фетчит с прод-бокса (доказано force-write тестом, см. #639).

Задача

Прокинуть mobile-proxy во все cian-сессии (как сделано для avito):

  1. Вынести settings.avito_proxy_url → generic settings.scraper_proxy_url (alias/rename; avito.py + scrape_pipeline._avito_proxies() перевести на него, сохранив обратную совместимость env AVITO_PROXY_URL ИЛИ ввести SCRAPER_PROXY_URL).
  2. cian.py / cian_detail.py / cian_session.py: proxies= в AsyncSession из этого настройка.
  3. env на проде: тот же прокси (уже в backend/.env.runtime).

DoD

  • cian SERP + detail + verify-auth идут через mobile-proxy.
  • cian_session.test-auth с валидными куками с прод-бокса → ok (не блок по IP).
  • ruff clean + unit на proxy-хелпере.

Не входит

  • Cookie-refresh DMIR_AUTH (#639, needs-human) — отдельно.

Refs #639, #623, #788, #805.

> Backend. Снимает оставшуюся (egress) часть #639 после закупки прокси (#623). Cookie-refresh #639 остаётся отдельно (needs-human). ## Контекст Общий egress-IP блокер cian+avito снят — RU mobile proxy куплен и работает на avito (#623/#788/#805, verified prod). Но **cian-скрейперы всё ещё ходят с datacenter-IP** (без `proxies`): - `cian.py:65` — `AsyncSession(impersonate=...)` без proxies - `cian_detail.py:80` — то же - `cian_session.py` (verify-auth) — то же → даже валидная cian-сессия не фетчит с прод-бокса (доказано force-write тестом, см. #639). ## Задача Прокинуть mobile-proxy во все cian-сессии (как сделано для avito): 1. Вынести `settings.avito_proxy_url` → generic **`settings.scraper_proxy_url`** (alias/rename; `avito.py` + `scrape_pipeline._avito_proxies()` перевести на него, сохранив обратную совместимость env `AVITO_PROXY_URL` ИЛИ ввести `SCRAPER_PROXY_URL`). 2. `cian.py` / `cian_detail.py` / `cian_session.py`: `proxies=` в `AsyncSession` из этого настройка. 3. env на проде: тот же прокси (уже в `backend/.env.runtime`). ## DoD - cian SERP + detail + verify-auth идут через mobile-proxy. - `cian_session.test-auth` с валидными куками с прод-бокса → ok (не блок по IP). - ruff clean + unit на proxy-хелпере. ## Не входит - Cookie-refresh DMIR_AUTH (#639, needs-human) — отдельно. Refs #639, #623, #788, #805.
bot-backend added the
scope/backend
tradein
priority/p2
labels 2026-05-30 18:06:33 +00:00
bot-backend added the
status/ready
label 2026-05-30 18:45:33 +00:00
bot-backend self-assigned this 2026-05-30 18:52:52 +00:00
bot-backend added
status/wip
and removed
status/ready
labels 2026-05-30 18:52:54 +00:00
bot-backend added
status/review
and removed
status/wip
labels 2026-05-30 19:01:40 +00:00
Author
Collaborator

PR (fix/806-cian-proxy) → status/review. Generic scraper_proxy_url (SCRAPER_PROXY_URL→AVITO_PROXY_URL fallback, zero prod env change); proxies= в cian.py/cian_detail/cian_session + avito/pipeline на тот же setting. 7 тестов pass. Cookie-refresh #639 не тронут. Post-deploy QA: cian test-auth с прод-бокса → не блок по IP.

PR (fix/806-cian-proxy) → status/review. Generic `scraper_proxy_url` (SCRAPER_PROXY_URL→AVITO_PROXY_URL fallback, zero prod env change); proxies= в cian.py/cian_detail/cian_session + avito/pipeline на тот же setting. 7 тестов pass. Cookie-refresh #639 не тронут. Post-deploy QA: cian test-auth с прод-бокса → не блок по IP.
bot-reviewer added
status/qa
and removed
status/review
labels 2026-05-30 19:10:49 +00:00
Collaborator

QA PASS — cian mobile-proxy wiring (PR #818, merged 19:10). Verified по merged diff.

DoD #1 — cian SERP+detail+verify через mobile-proxy :

  • cian.py.__aenter__proxies= из settings.scraper_proxy_url.
  • cian_detail.fetch_detail (own-session path) — proxies=.
  • cian_session.verify_sessionproxies=.
  • avito.py + scrape_pipeline._avito_proxies() переведены на тот же scraper_proxy_url (обратно совместимо).
  • Dict-shape {"http":url,"https":url} + AsyncSession(proxies=) — идентично прод-verified паттерну Avito (#623/#788/#805).

Generic setting (config.py): scraper_proxy_url property → SCRAPER_PROXY_URL > AVITO_PROXY_URL > None. Существующий прод AVITO_PROXY_URL работает без изменений .env.runtime. NB: включает validation_alias-fixup + regression-тест (test_settings_ignores_misnamed_scraper_proxy_url_env) — поймали реальную pydantic-settings env-binding ловушку.

DoD #3 — ruff + unit : test_scraper_proxy.py — 11 тестов (precedence, AVITO-fallback, empty-string, dict-shape, + реальный pydantic end-to-end env-binding).

DoD #2cian_session.test-auth с прод-бокса → не блок по IP runtime+cookie-gated, НЕ оценимо из QA-окна:

  • Требует прод-бокс execution + валидные DMIR_AUTH cookies.
  • Cookie-refresh = #639 (needs-human, явно ВНЕ скоупа #806) — без свежих куки test-auth вернёт 401/403 по auth (не по IP), что НЕ регрессия этого PR.
  • Wiring — точная копия прод-verified Avito-паттерна → IP-часть закрыта. Финальное «test-auth ok» подтвердится автоматически после #639 (свежие куки) + прод cian-run.

Proxy-wiring deliverable (controllable scope #806) — done+correct. → status/done, closing. Post-#639: при первом cian-прогоне с прод-бокса убедиться, что egress идёт с mobile-IP (не datacenter).

✅ **QA PASS** — cian mobile-proxy wiring (PR #818, merged 19:10). Verified по merged diff. **DoD #1 — cian SERP+detail+verify через mobile-proxy** ✅: - `cian.py.__aenter__` — `proxies=` из `settings.scraper_proxy_url`. - `cian_detail.fetch_detail` (own-session path) — `proxies=`. - `cian_session.verify_session` — `proxies=`. - `avito.py` + `scrape_pipeline._avito_proxies()` переведены на тот же `scraper_proxy_url` (обратно совместимо). - Dict-shape `{"http":url,"https":url}` + `AsyncSession(proxies=)` — идентично прод-verified паттерну Avito (#623/#788/#805). **Generic setting (`config.py`)**: `scraper_proxy_url` property → `SCRAPER_PROXY_URL > AVITO_PROXY_URL > None`. Существующий прод `AVITO_PROXY_URL` работает без изменений `.env.runtime`. **NB:** включает `validation_alias`-fixup + regression-тест (`test_settings_ignores_misnamed_scraper_proxy_url_env`) — поймали реальную pydantic-settings env-binding ловушку. ✅ **DoD #3 — ruff + unit** ✅: `test_scraper_proxy.py` — 11 тестов (precedence, AVITO-fallback, empty-string, dict-shape, + реальный pydantic end-to-end env-binding). **DoD #2 — `cian_session.test-auth` с прод-бокса → не блок по IP** ⏳ runtime+cookie-gated, НЕ оценимо из QA-окна: - Требует прод-бокс execution + валидные DMIR_AUTH cookies. - Cookie-refresh = **#639 (needs-human, явно ВНЕ скоупа #806)** — без свежих куки test-auth вернёт 401/403 по auth (не по IP), что НЕ регрессия этого PR. - Wiring — точная копия прод-verified Avito-паттерна → IP-часть закрыта. Финальное «test-auth ok» подтвердится автоматически после #639 (свежие куки) + прод cian-run. Proxy-wiring deliverable (controllable scope #806) — done+correct. → `status/done`, closing. Post-#639: при первом cian-прогоне с прод-бокса убедиться, что egress идёт с mobile-IP (не datacenter).
bot-qa added
status/done
and removed
status/qa
labels 2026-05-30 19:12:48 +00:00
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#806
No description provided.