From 891598a5d788ab0d413bd54e69b9f7cd592d9197 Mon Sep 17 00:00:00 2001 From: bot-backend Date: Mon, 15 Jun 2026 21:12:05 +0300 Subject: [PATCH] =?UTF-8?q?fix(tradein):=20cian=20newbuilding=20MFE/reliab?= =?UTF-8?q?ility=20drift=20=E2=80=94=20initialState=20extraction=20(#972)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cian переименовал MFE ЖК-карточки и переместил reliability-контейнер, из-за чего fetch_newbuilding получал initialState=None → failed_fetch для всех домов (verified live 2026-06-15 на прод-браузере через мобильный egress): - MFE: 'newbuilding-card-desktop-fichering-frontend' → 'newbuilding-card-desktop-frontend' (старое имя на странице отсутствует → extract_state=None → backfill succeeded=0) - reliability: initialState.reliability → initialState.reliabilityState.reliability (inner dict сохранил форму {checkStatus, details[], banner, actions}) Проверено на ЖК «Светлый» (nb 17556): newbuilding.id, realtyValuation chart (27 точек), reliabilityState.reliability.checkStatus + 2 details — всё извлекается. test_fetch_newbuilding_parses_state: fixture обновлён под reliabilityState.reliability. Полный suite зелёный (1779 passed; 2 несвязанных env-only локальных падения — cian_valuation cache / search_api auth — в CI проходят). Refs #972 --- .../app/services/scrapers/cian_newbuilding.py | 13 ++++++++----- tradein-mvp/backend/tests/test_cian_newbuilding.py | 8 +++++--- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/tradein-mvp/backend/app/services/scrapers/cian_newbuilding.py b/tradein-mvp/backend/app/services/scrapers/cian_newbuilding.py index 9ce09f20..20c9b4cf 100644 --- a/tradein-mvp/backend/app/services/scrapers/cian_newbuilding.py +++ b/tradein-mvp/backend/app/services/scrapers/cian_newbuilding.py @@ -1,12 +1,12 @@ """Cian.ru newbuilding (ЖК) catalog page scraper. URL: https://zhk---i.cian.ru/ -MFE: 'newbuilding-card-desktop-fichering-frontend', key: 'initialState' +MFE: 'newbuilding-card-desktop-frontend', key: 'initialState' Sister state containers extracted from same MFE initialState top-level keys: - realtyValuation: 7-month price chart (data.priceDynamics.chart.data.{labels,values}) → houses_price_dynamics -- reliability: наш.дом.рф checkStatus + details[] → house_reliability_checks +- reliabilityState.reliability: наш.дом.рф checkStatus + details[] → house_reliability_checks - offers: grouped by roomType (fromDeveloperRooms[].layouts[]) - reviews: house reviews list - housesByTurn: корпуса по очередям (stored as jsonb on houses) @@ -140,7 +140,9 @@ async def fetch_newbuilding( async with BrowserFetcher() as browser: html = await browser.fetch(zhk_url) - mfe = "newbuilding-card-desktop-fichering-frontend" + # Cian ЖК-карточка: MFE 'newbuilding-card-desktop-frontend', key 'initialState' + # (verified live 2026-06-15). + mfe = "newbuilding-card-desktop-frontend" nb_state = extract_state(html, mfe=mfe, key="initialState") if nb_state is None: @@ -185,8 +187,9 @@ async def fetch_newbuilding( result.realty_valuation_chart = _extract_chart(rv_state) result.raw_sister_states["realtyValuation"] = rv_state - # reliability (наш.дом.рф) — located at initialState.reliability (sec 15.6) - rel_state = top.get("reliability") or mfe_states.get("reliability") + # reliability (наш.дом.рф) — initialState.reliabilityState.reliability + # ({checkStatus, details[], banner, actions}, verified live 2026-06-15). + rel_state = (top.get("reliabilityState") or {}).get("reliability") if rel_state and isinstance(rel_state, dict): result.reliability_checks = _extract_reliability_checks(rel_state) result.raw_sister_states["reliability"] = rel_state diff --git a/tradein-mvp/backend/tests/test_cian_newbuilding.py b/tradein-mvp/backend/tests/test_cian_newbuilding.py index e57fc5b6..015d71c5 100644 --- a/tradein-mvp/backend/tests/test_cian_newbuilding.py +++ b/tradein-mvp/backend/tests/test_cian_newbuilding.py @@ -343,9 +343,11 @@ async def test_fetch_newbuilding_parses_state(monkeypatch): } } }, - "reliability": { - "checkStatus": {"status": "reliable", "title": "Проверено"}, - "details": [{"type": "problemHousesRegistry", "iconType": "success"}], + "reliabilityState": { + "reliability": { + "checkStatus": {"status": "reliable", "title": "Проверено"}, + "details": [{"type": "problemHousesRegistry", "iconType": "success"}], + }, }, }