gendesign/tradein-mvp/scripts
bot-backend 8fcef103c2 feat(msk-collector): Циан как вторая площадка сбора по Москве и МО
Сборщик получает ключ --platform {avito,cian}: платформо-зависимые куски
(URL коридора, счётчик, парс, потолок пагинации, целевая таблица) вынесены
в PlatformAdapter, общая часть — бисекция по цене, guard на блок, накопитель
и заливка — одна на обе площадки.

Скоуп Циан проверен живыми запросами 10.09, а не взят из документации:

- region=1 и region=4593 двумя параметрами НЕ объединяются, сервер берёт
  последний. Прежний базовый URL собрал бы одну Московскую область и молча
  потерял Москву целиком (92 817 объявлений). Правильный скоуп — region=-1.
- object_type[0]=1 обязателен: без него счётчик считает новостройки, которые
  дальше не сохраняются, и расходится с числом карточек вдвое.
- Итоговый скоуп: 62 548 объявлений вторички по Москве и МО.
- Потолок пагинации 54 страницы подтверждён: страница 55 пуста.

Фильтра новостроек в адаптере нет, и это сознательное отличие от кита. Кит
считает новостройкой всё, у чего есть offer.newbuilding.id (serp.py:401-402),
потому что для ЕКБ выдача бралась без object_type. На московской странице из
28 карточек 16 имеют этот блок, и у всех шестнадцати isFromBuilder=false,
isFromLeadFactory=false — это вторичка в ЖК, а не лоты застройщика. С китовым
фильтром прогон терял бы 57 % корпуса безвозвратно. msk_raw — сырьё, payload
несёт listing_segment целиком, сегмент отделяется на импорте в listings.

Детект блока Циан. Капча приходит как HTTP 200 с обычной на вид страницей:
поймана живьём, 40 КБ, title «Captcha - база объявлений ЦИАН», без
window._cianConfig. По статусу её не отличить, поэтому маркер ищется в первых
4 КБ (в нормальной выдаче на 2,6 МБ там ни одного вхождения). Вторая сеть в
parse_page: счётчик None при нуле сырых карточек — тоже стоп. Без этого блок
засчитывался бы как пустая страница, коридор уходил в done, а --resume его
уже не перебрал бы.

Гвард empty_page считает карточки ДО фильтра: иначе штатный ноль после
фильтрации был бы неотличим от блока. У Авито атрибута нет, дефолт — длина
итогового списка, поведение прежнее.

Заливка. Целевая таблица берётся из адаптера, staging создаётся с
INCLUDING IDENTITY (без него identity-колонка не переносится, а NOT NULL
переносится всегда, и \copy падал бы на каждом батче). Наличие таблицы
проверяется на старте одним SELECT to_regclass — иначе прогон умирал бы
на первой заливке, после часов планирования.

Миграция 299 заводит cian_cards, domclick_cards, yandex_cards и три вью
по образцу avito_cards/avito_latest. id — bigserial, а не IDENTITY, ровно
по причине выше.

Заодно: _wt-mskcol/ выведен из индекса и закрыт в .gitignore. Копия-worktree
попала в репозиторий 09.09, и три фикса ушли в дубликат мимо канонического
collect.py — дефект нашёлся только при сверке размера страницы.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VQ8jqr4SFirX5tFLwdSrXh
2026-09-10 13:23:46 +03:00
..
local-avito-msk feat(msk-collector): Циан как вторая площадка сбора по Москве и МО 2026-09-10 13:23:46 +03:00
local-cian feat(tradein/scripts): local Playwright runners для Cian backfill (bypass server-IP anti-bot) (#553) 2026-05-24 20:00:59 +00:00
sql fix(#3376): первая точка — только по третьей точке истории; числа под критерием 2026-09-06 05:12:30 +05:00
backfill-yandex-addresses-ekb.py feat(tradein-scripts): scrapers + probes + Phase C improvements (#551) 2026-05-24 19:58:38 +00:00
backfill_001_address_fingerprints.py feat(tradein): Phase 1.3 backfill scripts — fingerprints + house/listing_sources (#475) 2026-05-23 14:29:39 +00:00
backfill_002_house_sources.sql feat(tradein): Phase 1.3 backfill scripts — fingerprints + house/listing_sources (#475) 2026-05-23 14:29:39 +00:00
backfill_003_listing_sources.sql feat(tradein): Phase 1.3 backfill scripts — fingerprints + house/listing_sources (#475) 2026-05-23 14:29:39 +00:00
browser-smoke.sh chore(tradein): browser-smoke.sh — verify tradein-browser /health + /fetch (#905) 2026-05-31 18:42:17 +03:00
cian_backfill_all.sh feat(tradein): houses.cian_zhk_url column + backfill (#568) (#627) 2026-05-28 13:57:43 +00:00
inspect-houses-html.py feat(tradein-scripts): scrapers + probes + Phase C improvements (#551) 2026-05-24 19:58:38 +00:00
inspect-search-html.py feat(tradein-scripts): scrapers + probes + Phase C improvements (#551) 2026-05-24 19:58:38 +00:00
probe-confidence-distribution.py feat(tradein-estimator): unique-address-based confidence threshold (#513) 2026-05-24 11:52:00 +00:00
probe-db-counts.py feat(tradein-scripts): scrapers + probes + Phase C improvements (#551) 2026-05-24 19:58:38 +00:00
probe-db-leak-full.py feat(tradein-scripts): scrapers + probes + Phase C improvements (#551) 2026-05-24 19:58:38 +00:00
probe-db-region-leak.py feat(tradein-scripts): scrapers + probes + Phase C improvements (#551) 2026-05-24 19:58:38 +00:00
probe-db-url-leak.py feat(tradein-scripts): scrapers + probes + Phase C improvements (#551) 2026-05-24 19:58:38 +00:00
probe-migration-028.py feat(tradein-scripts): scrapers + probes + Phase C improvements (#551) 2026-05-24 19:58:38 +00:00
probe-migration-status.py feat(tradein-scripts): scrapers + probes + Phase C improvements (#551) 2026-05-24 19:58:38 +00:00
README.md feat(tradein): Phase 1.3 backfill scripts — fingerprints + house/listing_sources (#475) 2026-05-23 14:29:39 +00:00
test-playwright.py feat(tradein-scripts): scrapers + probes + Phase C improvements (#551) 2026-05-24 19:58:38 +00:00
trigger-schedules.py chore(tradein): полное выключение источника n1 — миграция 165 + вычистка backend/ops (#2204) 2026-07-03 10:08:56 +03:00
upload-cian-cookies.sh fix(tradein): убрать require_admin полностью — Caddy basic_auth достаточен (#474) 2026-05-23 14:21:01 +00:00

tradein-mvp scripts -- backfill

One-shot manual operator scripts. NOT auto-applied by deploy.yml (which only runs tradein-mvp/backend/data/sql/NN_*.sql).

Order

Run in numbered sequence after PR #470 (matching module) merged:

cd tradein-mvp/backend
export DATABASE_URL="postgresql+psycopg://user:pass@host:5432/tradein"

# 001 -- backfill houses.address_fingerprint (Python, idempotent)
uv run python ../scripts/backfill_001_address_fingerprints.py

# 002 -- backfill house_sources link rows (SQL, idempotent)
psql "${DATABASE_URL/postgresql+psycopg/postgresql}" -f ../scripts/backfill_002_house_sources.sql

# 003 -- backfill listing_sources link rows (SQL, idempotent)
psql "${DATABASE_URL/postgresql+psycopg/postgresql}" -f ../scripts/backfill_003_listing_sources.sql

All scripts idempotent -- re-running is safe (ON CONFLICT DO NOTHING on the SQL; row-level UPDATE WHERE NULL on the Python).

Other scripts

  • upload-cian-cookies.sh -- one-shot Cian session cookie upload (see inline docs)