Commit graph

82 commits

Author SHA1 Message Date
587564153f fix(tradein): cian _rotate_ip uses cian_proxy_rotate_url; page-scope idiom
Review #926 fixups:
- _rotate_ip: cian_proxy_rotate_url or avito_proxy_rotate_url (was avito-only →
  rotated wrong proxy IP on Cian ban, ignored CIAN_PROXY_ROTATE_URL).
- pagination log: dir() → locals() for local-var existence check.
2026-05-31 22:51:52 +03:00
46269b527a feat(tradein): exhaustive Cian EKB secondary load — room×price partitioning
Обходит Cian SERP-cap (~54 стр): адаптивно бьёт цену на бакеты внутри комнатности
(totalOffers-driven split, minprice/maxprice), пагинирует каждый полностью, дедуп
по source_id. Region-wide один проход (anchor'ы для Cian избыточны) + IP-rotation
(cian_proxy_rotate_url). Endpoint POST /admin/scrape/cian-full-load.
2026-05-31 22:43:05 +03:00
62d989b8a3 feat(tradein): Cian browser auto-login — POST /admin/scrape/cian/auto-login (#639) (#917)
All checks were successful
Deploy Trade-In / changes (push) Successful in 6s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / test (push) Successful in 32s
Deploy Trade-In / deploy (push) Successful in 1m17s
Deploy Trade-In / build-backend (push) Successful in 50s
Deploy Trade-In / build-browser (push) Successful in 2m8s
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-31 18:24:51 +00:00
92f44ac968 feat(tradein): route avito pipeline SERP+detail+houses through BrowserFetcher (#915) (#916)
All checks were successful
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / test (push) Successful in 30s
Deploy Trade-In / build-backend (push) Successful in 46s
Deploy Trade-In / deploy (push) Successful in 37s
Deploy Trade-In / build-browser (push) Has been skipped
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-31 18:10:38 +00:00
441e48141b feat(tradein): avito SERP via BrowserFetcher behind scraper_fetch_mode (#901)
All checks were successful
Deploy Trade-In / changes (push) Successful in 4s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Successful in 31s
Deploy Trade-In / build-backend (push) Successful in 44s
Deploy Trade-In / deploy (push) Successful in 36s
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-31 16:49:35 +00:00
6044a1fe3c fix(browser): local camoufox + HTTP wrapper, drop broken playwright WS server (#905)
The playwright WS-server path (camoufox.server.launch_server) is incompatible
with playwright >=1.45: camoufox 0.4.11's launchServer.js requires
playwright/driver/package/lib/browserServerImpl.js, which no longer exists in
any playwright 1.45-1.60 → tradein-browser crash-looped with MODULE_NOT_FOUND
('Server process terminated unexpectedly'). Verified by running the built image.

Pivot (no playwright protocol between containers):
- browser/server.py: aiohttp service holding a local AsyncCamoufox (headless,
  os/locale/geoip/humanize, proxy from SCRAPER_PROXY_URL). POST /fetch {url} →
  new_page/goto/content/close → {html}; GET /health. Page-recycle every N +
  crash-recovery (relaunch + 1 retry), serialized via asyncio.Lock.
- browser/Dockerfile: +aiohttp (camoufox fetch-as-root/#908 block untouched).
- backend BrowserFetcher: playwright.connect → httpx POST to the browser service
  (one retry on transport/HTTP error). All playwright imports dropped.
- config: browser_ws_endpoint → browser_http_endpoint (http://tradein-browser:3000).

Verified by a REAL local image build + run: image builds, container stays Up
(Restarts=0, no crash-loop), GET /health=200, POST /fetch launches camoufox and
drives Firefox (only NS_ERROR_UNKNOWN_HOST = no DNS egress in the local build env,
proving the full HTTP→camoufox→Firefox chain; real fetch validates on prod with
network+proxy). 7 unit tests + ruff clean.

Dormant: scraper_fetch_mode stays curl_cffi. Refs #905, #883, #884
2026-05-31 18:25:00 +03:00
d6479c13b9 Merge pull request 'feat(browser): split camoufox into a separate tradein-browser container (Phase 0.5, #905)' (#907) from feat/884-browser-separate-container into main
Some checks failed
Deploy Trade-In / build-frontend (push) Successful in 26s
Deploy Trade-In / test (push) Successful in 32s
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-browser (push) Failing after 1m16s
Deploy Trade-In / build-backend (push) Successful in 1m14s
Deploy Trade-In / deploy (push) Has been skipped
Reviewed-on: #907
2026-05-31 14:44:00 +00:00
5fb367295a feat(browser): split camoufox into tradein-browser container, connect-mode (#905)
Phase 0.5 — revise #884's in-backend camoufox into a dedicated browser service.
camoufox.server.launch_server exposes a Playwright WS endpoint (fingerprint/geoip/
proxy configured server-side); the backend connects remotely via playwright, so it
no longer ships Firefox.

- NEW tradein-mvp/browser/{server.py,Dockerfile}: camoufox WS server on :3000;
  Firefox fetch under app-user + ENV HOME (carries the #899 cache-path fix)
- BrowserFetcher rewritten launch-in-process → playwright.firefox.connect(ws_endpoint);
  recycle (close+reconnect every N) + crash-recovery (TargetClosed → reconnect + 1 retry)
- backend Dockerfile slimmed: drop 5 Firefox libs + camoufox fetch layer
- pyproject: remove camoufox[geoip] from backend, promote playwright to main deps
- docker-compose.prod.yml: add browser service (mem_limit 2.5g moves here), remove
  mem_limit from backend, backend depends_on browser (service_started)
- config: browser_ws_endpoint default ws://tradein-browser:3000/playwright
- tests/scrapers/test_browser_fetcher.py rewritten for connect-mode (6 pass)

Dormant: scraper_fetch_mode stays curl_cffi → no prod behavior change.
launch_server signature verified (**kwargs→launch_options, port passes through).

Refs #905, #883, #884, #899
2026-05-31 17:24:35 +03:00
4c0338ce1d fix(tradein): domklik source name, scraper delay, DataDome block detect (#796 fixup) 2026-05-31 17:21:30 +03:00
3c5e9ad368 feat(tradein): DomClick вторичка scraper via BrowserFetcher (#796) 2026-05-31 16:58:12 +03:00
fa2bd20ac6 refactor(tradein): drop dead schema — sale_type_text column + audit_log (#731) (#893)
Some checks failed
Deploy Trade-In / build-backend (push) Blocked by required conditions
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / changes (push) Successful in 4s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / test (push) Has been cancelled
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-31 13:13:43 +00:00
2890199d07 Merge pull request 'feat(tradein): BrowserFetcher camoufox wrapper + Docker/config infra (Phase 0, #884)' (#892) from feat/884-browserfetcher-camoufox into main
All checks were successful
Deploy Trade-In / changes (push) Successful in 4s
Deploy Trade-In / build-backend (push) Successful in 2m45s
Deploy Trade-In / build-frontend (push) Successful in 24s
Deploy Trade-In / test (push) Successful in 33s
Deploy Trade-In / deploy (push) Successful in 1m5s
Reviewed-on: #892
2026-05-31 12:47:49 +00:00
e03f4e4534 feat(tradein): BrowserFetcher camoufox wrapper + Docker/config infra (Phase 0, #884)
Epic #883 foundation. Provider-agnostic BrowserFetcher (camoufox headless Firefox):
async ctx mgr + page-recycle + crash-recovery + proxy. camoufox/playwright lazy
imports (won't break app import). scraper_fetch_mode defaults curl_cffi -> DORMANT
(no parser/estimator/avito/cian change). config: 4 browser_* settings. Dockerfile:
+5 Firefox libs + camoufox fetch layer. compose: mem_limit 2.5g. (uv.lock gitignored
-> re-resolved at build.) 9 mocked tests pass, ruff clean.

WARN: Docker build + container fetch UNVERIFIED (no local Docker); ~960MB image;
merge auto-deploys to prod. MERGE-GATE post-demo + CI-build-verify.

Refs #884, #883
2026-05-31 15:41:56 +03:00
42de30cd5c refactor(tradein): unify kadastr_num -> cadastral_number (#732)
p3 naming-consistency (cadastral cols 0% filled). Migration 094_cadastral_unify.sql
(idempotent DO-block IF EXISTS): drop+recreate listings_search_mv (MV) +
v_data_quality (view), RENAME deals/house_metadata kadastr_num->cadastral_number,
DROP listings.kadastr_num + listings_kadastr_idx. Code SQL-string renames in
search_query/estimator/base (Lot dataclass field NOT renamed). 240 tests pass.

WARN: destructive DDL auto-applies to prod on deploy -> MERGE-GATE post-demo.
Reviewer: verify recreated MV/view DDL vs LIVE pg_get_viewdef before apply
(reconstructed from migration history 050/046, not live capture).

Refs #732
2026-05-31 15:41:52 +03:00
70838c7dfe fix(tradein): avito house-link из detail SSR — SERP-карточка JS-only (#871) (#873)
All checks were successful
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / test (push) Successful in 30s
Deploy Trade-In / build-backend (push) Successful in 41s
Deploy Trade-In / deploy (push) Successful in 36s
Co-authored-by: lekss361 <lekss361@gendsgn.local>
Co-committed-by: lekss361 <lekss361@gendsgn.local>
2026-05-31 08:27:47 +00:00
65b9247369 fix(matching): Tier 2b alias sync + collapse double SAVEPOINT (#849) (#870)
All checks were successful
Deploy Trade-In / test (push) Successful in 30s
Deploy Trade-In / deploy (push) Successful in 46s
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 40s
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-31 08:05:48 +00:00
4494866574 fix(tradein): route yandex/valuation/imv/newbuilding scrapers через scraper_proxy_url (#860)
All checks were successful
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / test (push) Successful in 28s
Deploy Trade-In / deploy (push) Successful in 35s
Deploy Trade-In / build-backend (push) Successful in 40s
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-31 07:04:31 +00:00
da28a52067 feat(tradein): avito citywide + byrooms sweep mode (T6) (#848)
Some checks failed
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / test (push) Failing after 24s
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / deploy (push) Has been skipped
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-31 06:13:19 +00:00
571be4233b feat(tradein): yandex SERP curl_cffi+cookies transport + rooms×price combos (T4+T5) (#847)
Some checks failed
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / test (push) Failing after 26s
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / deploy (push) Has been skipped
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-31 06:11:30 +00:00
5d2af47b87 fix(tradein): cian SERP warm-up GET для seed cookies (_CIAN_GK/_yasc) (T2) (#846)
Some checks failed
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / test (push) Failing after 25s
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / deploy (push) Has been skipped
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-31 06:01:30 +00:00
08509b1b78 fix(scrapers): normalize cian descriptionMinhash list[int]→str + silent-0 guard (Refs #836) (#840)
Some checks failed
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / test (push) Failing after 25s
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / deploy (push) Has been skipped
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-30 20:28:56 +00:00
f7deed096b fix(scrapers): avito per-card parse_failures counter + logging (Refs #823) (#830)
Some checks failed
Deploy Trade-In / changes (push) Successful in 4s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / test (push) Successful in 25s
Deploy Trade-In / build-backend (push) Successful in 1m11s
Deploy Trade-In / deploy (push) Has been cancelled
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-30 20:01:50 +00:00
2739973285 fix(scrapers): COALESCE-backfill listing_date/area_m2 in save_listings ON CONFLICT (Refs #821) (#829)
All checks were successful
Deploy Trade-In / changes (push) Successful in 6s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / test (push) Successful in 25s
Deploy Trade-In / build-backend (push) Successful in 40s
Deploy Trade-In / deploy (push) Successful in 36s
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-30 19:58:06 +00:00
01593be438 feat(scrapers): route cian sessions through mobile proxy (Refs #806) (#818)
All checks were successful
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / test (push) Successful in 25s
Deploy Trade-In / build-backend (push) Successful in 39s
Deploy Trade-In / deploy (push) Successful in 35s
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-30 19:10:36 +00:00
7bd5a834dc fix(tradein): cian _cianConfig concat-формат + auth из header-frontend (#639) (#819)
All checks were successful
Deploy Trade-In / test (push) Successful in 25s
Deploy Trade-In / build-backend (push) Successful in 41s
Deploy Trade-In / deploy (push) Successful in 35s
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-30 19:08:01 +00:00
b736d7b7e0 feat(estimator): exclude city-centroid listings from radius analogs (Refs #769 Part E)
Закрывает последнюю часть #769 (A1/A2/B/C/D в #798/#804). Finding #17:
bare-city адреса геокодились в city-центроид и сохранялись как точные lat/lon →
mislocated листинги участвовали в radius ST_DWithin-аналогах.

- 089: ALTER TABLE listings ADD COLUMN IF NOT EXISTS geo_precision text (idempot).
- ScrapedLot.geo_precision + проброс в save_listings.
- geocode_missing.py: geo_precision='city' через существующий _geocode_is_coarse.
- estimator _fetch_analogs Tier H+W: + AND (geo_precision IS DISTINCT FROM 'city').
  NULL проходит (консервативно, сдвига до backfill нет). Pricing не тронут.

7 тестов; 270 passed, ruff clean.
2026-05-30 21:22:21 +03:00
c76785308b feat(scrapers/n1): извлекать floor/total_floors из ведущего N/M-токена (Refs #795) (#802)
All checks were successful
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / test (push) Successful in 25s
Deploy Trade-In / build-backend (push) Successful in 41s
Deploy Trade-In / deploy (push) Successful in 34s
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-30 17:31:13 +00:00
4c275e04ea fix(tradein): word-boundary street match + cian unescape robustness (Refs #769 A1+D) (#798)
All checks were successful
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / test (push) Successful in 24s
Deploy Trade-In / build-backend (push) Successful in 40s
Deploy Trade-In / deploy (push) Successful in 35s
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-30 17:18:33 +00:00
96027357b5 feat(tradein): Avito mobile proxy egress + firewall detect + MSK date (#623, #726) (#788)
All checks were successful
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / test (push) Successful in 24s
Deploy Trade-In / deploy (push) Successful in 33s
Deploy Trade-In / build-backend (push) Successful in 39s
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-30 16:52:35 +00:00
30ae4841a4 fix(scrapers): yandex area из embedded-state JSON (Refs #775) (#783)
Some checks failed
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / test (push) Successful in 24s
Deploy Trade-In / build-backend (push) Has been cancelled
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-30 16:38:12 +00:00
489666c735 fix(tradein): avito content-block (HTTP-200) не маскируется под end-of-pagination (Refs #754) (#779)
Some checks failed
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / test (push) Successful in 24s
Deploy Trade-In / build-backend (push) Has been cancelled
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-30 16:28:23 +00:00
79a79004cf fix(scrapers): stable dedup_hash — drop price_rub + strip URL query (Refs #753) (#761)
All checks were successful
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / test (push) Successful in 25s
Deploy Trade-In / build-backend (push) Successful in 40s
Deploy Trade-In / deploy (push) Successful in 34s
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-30 16:10:27 +00:00
e94929159b fix(scrapers): avito listing_date from sortTimeStamp JSON (#726) (#729)
All checks were successful
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / test (push) Successful in 24s
Deploy Trade-In / build-backend (push) Successful in 39s
Deploy Trade-In / deploy (push) Successful in 34s
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-30 14:13:38 +00:00
312df8536a feat(tradein): infer repair_state from listing description text (#622) (#632)
All checks were successful
Deploy Trade-In / changes (push) Successful in 6s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / deploy (push) Successful in 38s
Deploy Trade-In / build-backend (push) Successful in 48s
2026-05-28 15:37:34 +00:00
d842811390 refactor(tradein): normalize repair_state raw→enum at ingest (#621) (#629)
All checks were successful
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 49s
Deploy Trade-In / deploy (push) Successful in 36s
2026-05-28 15:18:11 +00:00
1731704ddc feat(tradein): houses.cian_zhk_url column + backfill (#568) (#627)
All checks were successful
Deploy Trade-In / changes (push) Successful in 6s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 51s
Deploy Trade-In / deploy (push) Successful in 36s
2026-05-28 13:57:43 +00:00
ec26e5813f fix(tradein): implement listings_snapshots + offer_price_history writers (#567) (#624)
Some checks are pending
Deploy Trade-In / deploy (push) Successful in 43s
Deploy Trade-In / build-backend (push) Successful in 1m2s
Deploy / changes (push) Waiting to run
Deploy / build-backend (push) Blocked by required conditions
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy / build-worker (push) Blocked by required conditions
Deploy / build-frontend (push) Blocked by required conditions
Deploy / deploy (push) Blocked by required conditions
2026-05-28 13:49:52 +00:00
81bf7e6def fix(tradein-imv): harden Avito IMV anti-bot path + offline contract tests (#565)
Add warm-up GET /evaluation/realty + production browser header set (Sec-Fetch,
X-Requested-With, 25s timeout) mirroring avito.py, чтобы защитить 3-step IMV flow
от server-IP анти-бот 403. Refactor step B/C парсинга в pure helpers
(_parse_geo_position/_parse_price/_parse_placement_history/_parse_suggestions)
+ fixture-driven offline тесты из живых JSON-captures.

Честный диагноз: контракт (geoFieldsHash, price-блок, categoryId=24) НЕ менялся —
проверено живым capture'ом с этой машины (A→B→C, recommended 7.39M). Реальная
причина #565 — скорее анти-бот по PROD-IP, не код → если #565 останется после
deploy, настоящий фикс = ротация egress IP воркера (devops, отдельно).

code-reviewer:  APPROVE no critical — warm-up non-fatal, injected-session path
unchanged, refactor preserves shapes, graceful-None сохранён, fixtures без PII.
Tests: 12 new (27 total). Ruff clean.

Closes #565
2026-05-28 16:29:05 +05:00
a3f45a6722 fix(tradein): decode Avito houses URL-encoded __preloadedState__ (#566)
Avito switched the houses-catalog state blob from JSON.parse("<js-escaped>")
to a URL-encoded string literal, wrapped the 10 widgets in
placeholders[0].widgets, и re-nested developmentData под props.housePage.
JS-unescape path silently failed → houses rows перестали наполняться
(starve'ит #6 same-building + #569 deal centroids).

Extract decode в pure _extract_preloaded_state (urllib.parse.unquote,
JSON.parse fallback для старой формы), add _flatten_widgets, и сделать
_parse_house_page tolerant к обеим developmentData/ratingPreview формам.
Real-HTML fixture (Yumasheva-6 EKB) + 4 regression-теста.

code-reviewer:  APPROVE no critical (regex anchoring verified, decode
safe — no eval/unicode_escape, backward-compat реальный, delisted-house
envelope degrade'ит gracefully, fixture без PII/secrets). Tests: 22 passed.

Closes #566
2026-05-28 15:58:19 +05:00
99a5a0f73b fix(tradein): Yandex listing_date — keyword + absolute-no-year (#602)
All checks were successful
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / deploy (push) Successful in 36s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 47s
2026-05-27 13:11:22 +00:00
f5c87201f1 fix(tradein): Avito listing_date extraction (3 формата) (#601)
All checks were successful
Deploy Trade-In / build-backend (push) Successful in 49s
Deploy Trade-In / deploy (push) Successful in 36s
Deploy Trade-In / changes (push) Successful in 1m28s
Deploy Trade-In / build-frontend (push) Has been skipped
2026-05-27 12:55:27 +00:00
7e24ccbf2c feat(tradein): hook matching в save_listings — fill listing_sources (PR I) (#595)
All checks were successful
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 52s
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / deploy (push) Successful in 40s
2026-05-27 10:02:37 +00:00
aa70e9e155 fix(tradein): yandex_realty captures house number + parse_rub strips NBSP (#593)
All checks were successful
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 55s
Deploy Trade-In / deploy (push) Successful in 42s
2026-05-27 07:23:36 +00:00
6bbb026cb4 fix(yandex-valuation): off-by-one cell index in _parse_row_cells (#552)
Some checks failed
Deploy Trade-In / build-backend (push) Successful in 40s
Deploy Trade-In / deploy (push) Has been cancelled
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
2026-05-24 19:57:17 +00:00
f7a5c5d4f7 fix(yandex-valuation): curl_cffi chrome120 — Yandex gates SSR on Chrome TLS (#545)
All checks were successful
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 39s
Deploy Trade-In / deploy (push) Successful in 45s
2026-05-24 16:42:07 +00:00
8a88ea6508 refactor(yandex-valuation): DOM-based parser via .OffersArchiveSearchOffers__row (#544)
Some checks failed
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 40s
Deploy Trade-In / deploy (push) Failing after 10m3s
2026-05-24 16:25:56 +00:00
3ed58e3e7a fix(yandex-valuation): relax area regex lookbehind (2-комн regression) (#542)
All checks were successful
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 52s
Deploy Trade-In / deploy (push) Successful in 35s
2026-05-24 16:02:06 +00:00
490bc8ca5d fix(yandex-valuation): tighten area regex + chronological date ordering (#541)
All checks were successful
Deploy Trade-In / build-backend (push) Successful in 43s
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / deploy (push) Successful in 35s
2026-05-24 15:37:48 +00:00
9505471129 fix(yandex-valuation): cap area_m2 sanity (drop >10000 or ≤0) (#538)
All checks were successful
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 42s
Deploy Trade-In / deploy (push) Successful in 37s
2026-05-24 15:14:13 +00:00
ee2262d605 fix(tradein-phase-c): house_type 'monolith'→'monolithic' + log 400 body (#537)
All checks were successful
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 46s
Deploy Trade-In / deploy (push) Successful in 38s
2026-05-24 15:05:49 +00:00