feat(tradein/scripts): local Playwright runners для Cian backfill (bypass server-IP anti-bot) #553
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#553
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "feat/local-cian-runners"
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?
What
Добавляет
tradein-mvp/scripts/local-cian/— production-ready локальные Playwright scrapers которые backfill'ят Cian historical data + valuation с домашнего IP разработчика. Решает проблему обнаруженную при попытке server-side backfill (PR #535/#539): Cian блокирует server-IP anti-bot'ом → возвращает captcha challenge на все requests с tradein-backend. Локальный запуск через real Chrome + persistent profile успешно обходит.Files (4)
playwright_history.py— production-ready. Backfilloffer_price_history. Real Chrome через Playwright, paginateid > last_id, JS extractdefaultState.offerData.priceChanges→ INSERT с UNIQUE дедупом. Темп ~25 listings/min, идёт прямо сейчас на машине разработчика, 1500+ rows записано.playwright_valuation.py— best-effort. Backfillexternal_valuationsчерез Calculator URL. Persistent Chrome profile для стабильности сессии. Auto-reload cookies из БД при auth loss. Skip листинги где Cian не отдаёт оценку (новостройки без аналогов).upload_cookies_local.py— записывает Cian session cookies вcian_session_cookiesчерез прямой psycopg connect к prod БД (через SSH tunnel), обходит brokenverify_session(httpx fingerprint не проходит, см. PR #543 context).README.md— setup (psycopg, playwright, chromium), SSH tunnel инструкции, как залить cookies, usage examples, limitations.Why
tradein-backendлокально вызываетcian_detail.fetch_detailчерезcurl_cffi chrome120— но Cian определяет паттерн и блокирует →defaultState extraction failedдля всех URL с прод-IP. Backfill endpoint (PR #535) фактически не работает в проде.cian_session_cookiesдля backend Calculator scraper тоже не работают — этим скриптом мы их инжектим напрямую в Playwright context.Не покрывает (out of scope)
houses_price_dynamics—housestable не имеетcian_zhk_urlcolumn (TODO mig 065, см. PR #535).Test plan
playwright_history.pyнаписал 1500+ rows вoffer_price_historyза часplaywright_valuation.pyнаписал 6 rows для домов с оценкойchrome_profile/локально + перепрогнать на свежей машинеFollow-ups
References: 6-PR Cian activation series (#523/#525/#530/#535/#539/#543). Vault:
decisions/Decision_Cian_History_Valuation_Activation_May24.md.Deep Code Review — PR #553
Status: APPROVE
Files: 4 (all new, P2 — local-only scripts) · +831 / -0 · scope:
tradein-mvp/scripts/local-cian/SHA verified:
5555ea2f6750b564e170c0f37ae1300e3306e6dfScope context
Local-machine Playwright backfill runners для Cian — обход server-IP anti-bot. Authorized by vault
decisions/Decision_Cian_History_Valuation_Activation_May24.md+ runbookrunbooks/cian_local_playwright_backfill.md(already references this PR #553). User reported 1500+ rows backfilled successfully за час — production-validated.This is not a server-side scraper — pure dev tooling что runs from user's workstation. The
feedback_playwright_mcp_not_npxrule applies к qa-tester smoke tests, не к standalone backfill scripts (которые legitimately нуждаются в local Playwright runtime).Security — clean
<PASTE_FROM_BROWSER_DEVTOOLS>,999999999 # TODO).TRADEIN_DB_DSN/COOKIE_ENCRYPTION_KEY— env vars, README указывает source (vaultmeta/00_credentials.md).pgp_sym_encrypt(matches existingcian_session_cookiescontract from migration 027).%sпараметры, никакого f-string interpolation.DMIR_AUTH={yes/no}).Correctness
CAST(:x AS type)(e.g.CAST(%s AS bigint)/CAST(%s AS numeric)) — соответствует backend rule.cian_valuation._save_to_cache(line 418-462 of backend/app/services/scrapers/cian_valuation.py).ON CONFLICT (listing_id, change_time) DO NOTHINGmatchesoffer_price_history_listing_change_uq(migration 047)ON CONFLICT (source, cache_key) DO UPDATEmatches existing service patternON CONFLICT (account_user_id)matches migration 027 PKid > last_id ASC— устойчиво к 0-change результатам, не зацикливается.Anti-bot / rate-limiting respect
--delay 2(30 req/min) + Valuation--delay 5(12 req/min) — conservative для logged-in Cian session.--disable-blink-features=AutomationControlled— standard fingerprint stabilization.location.href.includes('captcha')) → STOP execution, prompts user for--headedmanual solve.Minor (non-blocking)
upload_cookies_local.py:_yasc/_ym_isad/uxfb_card_satisfactiondefaults как литерал"<optional>"— если user забыл удалить/заполнить, эти cookies загрузятся как мусорные строки. Не блокирует (Cian игнорирует unknown values), но в README стоит указать «удалите optional поля если не заполняете».playwright_valuation.pyINSERT:filters_hashвсегда NULL (hardcoded%s, NULL), хотя existing service-layer пишет реальныйsale.filtersHash. Backward compat — старые записи получат NULL filters_hash. Не критично для backfill, но можно подобратьsale.get("filtersHash")без overhead.chrome_profile/hardcoded в Windows-only path — README указываетCIAN_PROFILE_DIRoverride для override.Vault cross-check
decisions/Decision_Cian_History_Valuation_Activation_May24.md— авторизует full 6-PR sequence (#523/#525/#530/#535/#539/#543) + PR #553 как post-launch tooling.runbooks/cian_local_playwright_backfill.md— уже описывает exactly эти скрипты и process. README в PR строго соответствует runbook.Positive
unwraphelper для Cian{data, isFetching, isError}wrapper pattern — defensively применён ко всем nested fields.Verdict
Production-validated dev tooling, vault-authorized, security clean. APPROVE → merge.