[BLOCKED #2000] feat(tradein/domclick): Layer B detail-backfill + local runner + JSONL ingest #2005

Closed
lekss361 wants to merge 8 commits from feat/tradein-domclick-detail-backfill into main

8 commits

Author SHA1 Message Date
5f994cc300 feat(tradein/domclick-local): --enum-cache — enumerate один раз, resume detail поверх
All checks were successful
CI / frontend-tests (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 7s
CI / openapi-codegen-check (pull_request) Has been skipped
enumerate (~6422 id через SERP, ~1.5-2ч) теперь пишет полный список id в файл-кэш
(--enum-cache PATH) с sentinel завершённости; следующий запуск грузит кэш и полностью
пропускает enumerate → сразу detail. detail-resume по done (JSONL) композится поверх.
Кэш пишется только после реально завершённого свода (прерванный enumerate не кэшируется).
Тест: run1 записал 5 id+sentinel, run2 загрузил и пропустил SERP.
2026-06-27 23:37:07 +03:00
0f7f5ea0ab fix(tradein/domclick-local): resume — убрать преждевременный added==0 break в _paginate
All checks were successful
CI / changes (pull_request) Successful in 14s
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
При resume первые страницы каждого бакета = топ-qi офферы, уже лежащие в done →
_add_offers возвращал added=0 → _paginate делал break → enumerate собирал 0 новых
(st=0 при resume; на первом прогоне done пуст, не проявлялось). Терминаторы пагинации
— только пустая страница и offset>=bound. Подтверждено: resume со 114 done → st собрал
546 новых студий (660-114).
2026-06-27 22:39:47 +03:00
3cc015c249 fix(tradein/domclick-local): SERP enumerate — wait_for_selector вместо слепого render-wait
Карточки SERP появляются клиентской гидрацией через ~6-12с после domcontentloaded.
Фиксированный render-sleep ловил пустой DOM при медленном ответе → enumerate молча
собирал 0 ids (silent 0-coverage; всплыло при ускоренном профиле render 3-5).
Теперь fetch_serp_page ждёт 'a[href*=/card/]' явно (timeout 12с) → пустой ценовой
band корректно даёт 0 по таймауту, render_wait остаётся коротким settle. Подтверждено
enumerate-only --limit 5 с render 3-5.
2026-06-27 22:26:48 +03:00
9b1f064069 feat(tradein/domclick-local): SERP-enumerate (QRATOR-обход) + offer-card v3 extras
All checks were successful
CI / changes (pull_request) Successful in 7s
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
(а) enumerate: прямой bff-search offers/v1+count/v1 режет QRATOR-403 с home-IP →
переведён на навигацию по фронтовому SERP (page.goto, тот же чистый транспорт что
card-detail): id из DOM (a[href*=/card/]), total из <title>, пагинация offset=20,
price-bisection при total>2000 ("5+"→5%2B через urlencode). Layer-A
(price/area/rooms/floor/total_floors/lat/lon/address) теперь из card-SSR
(productCard.priceInfo/objectInfo + address.position + houseInfo.info), т.к.
enumerate отдаёт только id+url. Удалены мёртвые BFF-функции. Схема JSONL не изменилась.

(б) detail: дозабор с offer-card v3 (200 с home-IP, в отличие от прод-прокси):
price_prediction (AVM заполненный + repair_quality + аренда, всегда) и sold_similar
(опц., --with-sold-similar/--sold-limit) через page.evaluate из QRATOR-сессии карточки.
XHR-AVM переопределяет пустой SSR pricePrediction; sold_similar в raw_extra.

Live-tested: enum-only собрал ids без QRATOR-аборта; full --limit 2 → price_rub
6.1M/3.1M, area/floor/coords/address из card-SSR, AVM market_price 4.99M/3.01M,
sold_similar.total≈1691. ruff clean.
2026-06-27 20:03:05 +03:00
f7426dc12b feat(tradein/domclick): JSONL ingest script for local detail-backfill runner
All checks were successful
CI / changes (pull_request) Successful in 7s
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
scripts/ingest_domclick_jsonl.py — idempotent ingest of domclick_local_runner
output: filter ok+price, upsert via save_listings (fault-tolerant house-match
hook in SAVEPOINT — non-matched listings still persist), deep-detail enrichment
via save_detail_enrichment (owners/encumbrances/kitchen/views/wall/floor/
price-history). --limit / --dry-run. psycopg v3 ANY(:ids) list-bind.
Per-record try/except in enrichment loop so one bad row never aborts the tail.

Live-tested in tradein-backend on 30 records: updated=30, house_matched=30,
detail_applied=30, price_history idempotent (75->75), enrich_failed=0.
2026-06-27 19:14:10 +03:00
75f1d36505 chore(tradein/domclick): configurable human-break (--break-min/--break-max, default 40-60s) 2026-06-27 18:50:46 +03:00
480ecc90e5 feat(tradein/domclick): local Layer-B runner — home-IP + new-headless chromium, paced
Self-contained script (playwright chromium, NO app imports) для сбора DomClick EKB
detail с домашнего residential IP (обходит QRATOR — verified live: 2 карточки ok,
repair/areas/priceHistory/egrn/owners собраны). Enumerate via bff (Layer A) + card
__SSR_STATE__ parse (Layer B) → JSONL (resume/idempotent).

KEY: дифференциатор — РЕЖИМ HEADLESS, не только IP. С того же IP старый headless=True
→ 403, new-headless → 200 + SSR. Раннер дефолтит на new-headless.

Пейсинг: рандом 12-30с между карточками, render-jitter 6-10с, human-break каждые
25-40 (60-180с), 1 retry на 403. ~100-150 карточек/час, full ~6400 ≈ 45-65ч.
JSONL ингестится в tradein DB отдельным шагом. НЕ deploy — локальный ops-инструмент.
2026-06-27 18:24:08 +03:00
eef23071c5 feat(tradein/domclick): Layer B detail-backfill (SSR parse + AVM) — DORMANT/parked
ПАРКОВКА (не мержить до прокси): код готов — parser на реальных __SSR_STATE__ путях
(productCard.objectInfo/priceInfo.priceHistory/egrnData/houseInfo.info + pricePrediction AVM),
orchestrator зеркало avito_detail_backfill, schedule 139 enabled=false. Деплоить нельзя:
DomClick card/offer-card за QRATOR reputation-403 на прод mobile-прокси (нужен dedicated
residential RU IP). Детали/аудит транспорта — Forgejo issue.
2026-06-27 16:39:16 +03:00