feat(scrapers): route cian sessions through mobile proxy (Refs #806) #818
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#818
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/806-cian-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?
Что
Снимает egress-часть #639: cian-скрейперы ходили с datacenter-IP (без
proxies) → даже валидные куки не фетчили с прод-бокса. Прокидываем тот же mobile-proxy, что у avito (#623/#805).Как
scraper_proxy_url— envSCRAPER_PROXY_URL→ fallbackAVITO_PROXY_URL→ None/direct. Прод.env.runtime(где ужеAVITO_PROXY_URL) работает без изменений env.avito.py+scrape_pipeline._avito_proxies()→ наsettings.scraper_proxy_url(поведение идентично, тот же прокси).cian.py/cian_detail.fetch_detail/cian_session.verify_session:proxies={http,https}изsettings.scraper_proxy_url. Пусто → direct (dev no-op, прокси не хардкодится).Не входит
Cookie-refresh DMIR_AUTH (#639) — НЕ тронут (needs-human).
Тесты
tests/test_scraper_proxy.py(7): precedence SCRAPER→AVITO→None, dict-shape{http,https}, fallback-резолв.pytest -k "proxy or cian or avito"pass, ruff clean.Post-deploy QA:
cian_session.test-authс валидными куками с прод-бокса → ok (не блок по IP).Refs #806, #639, #623, #805
🟠 FIX — env-binding баг: новый
SCRAPER_PROXY_URLне привязывается.Проблема (config.py):
Settingsиспользует дефолтный pydantic-settings mapping (SettingsConfigDictбезenv_prefix/alias). Полеscraper_proxy_url_env→ читает envSCRAPER_PROXY_URL_ENV, а НЕSCRAPER_PROXY_URL(как заявлено в комменте и PR-описании). Сextra="ignore"реальныйSCRAPER_PROXY_URLмолча игнорируется.→ Заявленный precedence «SCRAPER_PROXY_URL > AVITO_PROXY_URL» не работает: выставить
SCRAPER_PROXY_URL= no-op. Чтобы переопределить, пришлось бы ставитьSCRAPER_PROXY_URL_ENV(что никто не знает).Почему не BLOCK: прод не ломается — там стоит
AVITO_PROXY_URL, property падает в fallback → cian+avito проксируются корректно. Но контракт нового env сломан = footgun.Почему тесты не поймали:
test_scraper_proxy.pyтестирует inline-реплику_resolve_scraper_proxy_url(...), минуя pydantic env-binding. OR-логика проверена, привязка env — нет.Fix (1 строка):
(
validation_aliasзадаёт имя env для pydantic-settings; propertyscraper_proxy_urlостаётся как есть.)Плюс тест на реальную привязку: сконструировать
Settingsс monkeypatchedSCRAPER_PROXY_URLв env и проверить, чтоsettings.scraper_proxy_urlего подхватил (а не только inline-реплику).Остальное — ✅ корректно: dict-shape
{http,https}, единыйscraper_proxy_urlво всех сессиях (avito__aenter__,_avito_proxies, cian__aenter__,fetch_detail,verify_session), пусто→direct (dev no-op), AVITO fallback для zero-env-change на проде. Cookie-refresh #639 корректно вынесен (needs-human). Ставлюstatus/needs-fix— поправь alias + тест, и пере-апрувлю.fixup 1/1 (
d815d7b) — поправил env-binding ровно как указал reviewer:config.py:scraper_proxy_url_env: str | None = Field(default=None, validation_alias="SCRAPER_PROXY_URL")— теперь поле реально привязано к envSCRAPER_PROXY_URL(не кSCRAPER_PROXY_URL_ENVпо имени поля). Заявленный precedence SCRAPER_PROXY_URL > AVITO_PROXY_URL заработал.Settings(_env_file=None)с monkeypatched env, а не inline-реплику):test_settings_binds_scraper_proxy_url_env—SCRAPER_PROXY_URLподхватывается;test_settings_scraper_env_overrides_avito— override над AVITO;test_settings_falls_back_to_avito_env— fallback на AVITO (zero-env-change на проде);test_settings_ignores_misnamed_scraper_proxy_url_env— regression: старое неправильное имяSCRAPER_PROXY_URL_ENVбольше НЕ биндится → None (доказывает, что alias чинит баг).uv run pytest tests/test_scraper_proxy.py→ 11 passed;ruff checkclean. → status/review.✅ APPROVE — fixup корректен, env-binding баг устранён.
Проверка fixup:
scraper_proxy_url_env = Field(default=None, validation_alias="SCRAPER_PROXY_URL")— теперь поле привязано к envSCRAPER_PROXY_URL(validation_alias переопределяет дефолтный name-mapping).import Fieldдобавлен.Settings(_env_file=None)+monkeypatch.setenv) закрывают ровно тот gap, что был:test_settings_binds_scraper_proxy_url_env(binding),_scraper_env_overrides_avito(precedence),_falls_back_to_avito_env(fallback), и regressiontest_settings_ignores_misnamed_scraper_proxy_url_env(старое имяSCRAPER_PROXY_URL_ENV→ НЕ биндится → None). Inline-реплика осталась как доп. unit-проверка OR-логики.Остальное (без изменений с прошлого ревью): единый
settings.scraper_proxy_urlво всех сессиях (avito__aenter__/_avito_proxies, cian__aenter__/fetch_detail/verify_session), dict-shape{http,https}, пусто→direct, AVITO fallback (zero-env-change на проде).Hot-file overlap #819 (
cian_session.py): #819 уже смержен; rebase прошёл,mergeable:true— #818 трогаетverify_session, #819 трогал_classify_verify_response/_MFE_AUTH(разные функции). Конфликта нет.Anti-regression: self-extending файлы не затронуты, секретов нет (тест-фикстуры
user:pass@…— placeholder'ы). Cookie-refresh #639 не тронут (needs-human). Мержу.