gendesign/tradein-mvp/scripts/local-cian
lekss361 136202dc80
All checks were successful
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / deploy (push) Successful in 32s
feat(tradein/scripts): local Playwright runners для Cian backfill (bypass server-IP anti-bot) (#553)
2026-05-24 20:00:59 +00:00
..
playwright_history.py feat(tradein/scripts): local Playwright runners для Cian backfill (bypass server-IP anti-bot) (#553) 2026-05-24 20:00:59 +00:00
playwright_valuation.py feat(tradein/scripts): local Playwright runners для Cian backfill (bypass server-IP anti-bot) (#553) 2026-05-24 20:00:59 +00:00
README.md feat(tradein/scripts): local Playwright runners для Cian backfill (bypass server-IP anti-bot) (#553) 2026-05-24 20:00:59 +00:00
upload_cookies_local.py feat(tradein/scripts): local Playwright runners для Cian backfill (bypass server-IP anti-bot) (#553) 2026-05-24 20:00:59 +00:00

Local Cian backfill scrapers (Playwright, real browser)

Cian блокирует server-IP scraping anti-bot. Эти скрипты запускаются с локальной машины разработчика через SSH-tunnel к prod tradein-postgres — обходят bot detection, используют real Chrome с persistent profile.

Когда использовать

  • Backfill offer_price_history для активных Cian listings (history scraper, надёжно)
  • Best-effort backfill external_valuations для домов где Calculator отдаёт оценку без agent-wizard

Prerequisites

pip install playwright "psycopg[binary]" sqlalchemy
python -m playwright install chromium

Setup

1. SSH tunnel к tradein-postgres (отдельное окно, держать открытым)

$IP = (ssh gendesign 'docker inspect tradein-postgres --format "{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}"').Trim()
ssh -L "15433:${IP}:5432" gendesign -N

2. Env vars (creds из vault meta/00_credentials.md)

$env:TRADEIN_DB_DSN = "postgresql+psycopg://tradein:<PASSWORD>@localhost:15433/tradein"
$env:COOKIE_ENCRYPTION_KEY = (ssh gendesign 'grep ^COOKIE_ENCRYPTION_KEY= /opt/gendesign/tradein-mvp/.env.runtime | cut -d= -f2').Trim()

3. Залить Cian cookies (один раз / по мере истечения)

  1. Login на cian.ru в обычном Chrome.
  2. DevTools → Application → Cookies → www.cian.ru → скопировать DMIR_AUTH (httpOnly) + _CIAN_GK.
  3. Вставить значения в upload_cookies_local.py (поля с плейсхолдером <PASTE_FROM_BROWSER_DEVTOOLS>).
  4. Вставить реальный Cian userId в ACCOUNT_USER_ID (найти: DevTools → Network → XHR → /v1/get-my-id/userId).
  5. Run:
python upload_cookies_local.py

Usage

History backfill (production-ready, не блокируется)

python -u playwright_history.py --batch 20 --delay 2 2>&1 | Tee-Object -FilePath cian_history.log
  • Темп: ~25 listings/min
  • Идёт по id > last_id ASC pagination
  • Записывает в offer_price_history (UNIQUE listing_id + change_time)
  • Скорость дрейна 5к листингов: ~3-4 часа

Valuation backfill (best-effort, partial)

python -u playwright_valuation.py --batch 10 --delay 5 --wait 8 2>&1 | Tee-Object -FilePath cian_valuation.log
  • Использует persistent profile ./chrome_profile/ для сохранения сессии между runs (переопределяется через $env:CIAN_PROFILE_DIR)
  • На not auth в --headed mode — ждёт manual login в открытом окне
  • Skip листинги где Cian не отдаёт оценку (~70% таких — новостройки, нет аналогов)

Если auth теряется

Playwright Chrome имеет другой fingerprint чем твой обычный Chrome → Cian может invalidate сессию. Решения:

  • Запустить с --headed → login manually в окне.
  • Re-upload cookies через upload_cookies_local.py.

Pre-existing knowledge

См. vault decisions/Decision_Cian_History_Valuation_Activation_May24.md — full 6-PR sequence (#523/#525/#530/#535/#539/#543) + open follow-ups.

Limitations

  • Calculator (external_valuations) собирается только для домов с готовой оценкой в _cianConfig['valuation-for-agent-frontend'].initialState.estimation. Полный wizard-flow не автоматизируется.
  • DMIR_AUTH expires ~30-60 min — нужно периодически перезаливать cookies.
  • Не покрывает Cian listings вне нашего SERP (старые не-active, нестандартные region/category).