From 6bbb026cb4d4569f66b299d6d08a4d44c3171116 Mon Sep 17 00:00:00 2001 From: lekss361 Date: Sun, 24 May 2026 19:57:17 +0000 Subject: [PATCH] fix(yandex-valuation): off-by-one cell index in _parse_row_cells (#552) --- .../app/services/scrapers/yandex_valuation.py | 21 +++++++++---------- .../backend/tests/test_yandex_valuation.py | 12 +++++------ 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/tradein-mvp/backend/app/services/scrapers/yandex_valuation.py b/tradein-mvp/backend/app/services/scrapers/yandex_valuation.py index c4e38ff6..5760382c 100644 --- a/tradein-mvp/backend/app/services/scrapers/yandex_valuation.py +++ b/tradein-mvp/backend/app/services/scrapers/yandex_valuation.py @@ -322,28 +322,27 @@ class YandexValuationScraper(BaseScraper): return None cell_texts = [(c.text(strip=True) or "").replace("\xa0", " ") for c in cells] - # [0] area + rooms - area_text = cell_texts[0] - area_m = RE_ITEM_AREA.search(area_text) + # [0] photo (skipped — empty cell) + # [1] title — single cell contains area + rooms + floor jammed together, + # e.g. "48,5 м², 1-комнатная19 этаж" (real Yandex layout, 2026-05-24) + title_text = cell_texts[1] if len(cell_texts) > 1 else "" + + area_m = RE_ITEM_AREA.search(title_text) area_m2: float | None = float(area_m.group(1).replace(",", ".")) if area_m else None # Sanity drop (belt-and-suspenders from PR #538) if area_m2 is not None and (area_m2 > 10_000 or area_m2 <= 0): area_m2 = None rooms: int | None = None - if RE_ITEM_STUDIO.search(area_text): + if RE_ITEM_STUDIO.search(title_text): rooms = 0 else: - rooms_m = RE_ITEM_ROOMS.search(area_text) + rooms_m = RE_ITEM_ROOMS.search(title_text) if rooms_m: rooms = int(rooms_m.group(1)) - # [1] floor - floor: int | None = None - if len(cell_texts) > 1: - floor_m = RE_ITEM_FLOOR.search(cell_texts[1]) - if floor_m: - floor = int(floor_m.group(1)) + floor_m = RE_ITEM_FLOOR.search(title_text) + floor: int | None = int(floor_m.group(1)) if floor_m else None # [2] start price + ppm2 — "5,1 млн ₽105 155 ₽ за м²" (no separator) start_price: int | None = None diff --git a/tradein-mvp/backend/tests/test_yandex_valuation.py b/tradein-mvp/backend/tests/test_yandex_valuation.py index 4b1988ff..c32e4aec 100644 --- a/tradein-mvp/backend/tests/test_yandex_valuation.py +++ b/tradein-mvp/backend/tests/test_yandex_valuation.py @@ -491,16 +491,16 @@ def test_area_regex_still_blocks_subfragment(): _DOM_FIXTURE_ROW_HTML = """
-
48,5 м², 1-комнатная
-
19 этаж
+
+
48,5 м², 1-комнатная19 этаж
5,1 млн ₽105 155 ₽ за м²
5,1 млн ₽105 155 ₽ за м²
23.10.2023В экспозиции 945 дней
В продаже
-
58,2 м², 2-комнатная
-
3 этаж
+
+
58,2 м², 2-комнатная3 этаж
9,3 млн ₽159 932 ₽ за м²
8,9 млн ₽152 062 ₽ за м²
12.02.2026В экспозиции 156 дней
@@ -552,8 +552,8 @@ def test_dom_parser_studio_row(): html = ( "" '
' - '
Студия 25 м²
' - '
5 этаж
' + '
' + '
Студия 25 м²5 этаж
' '
4 млн ₽160 000 ₽ за м²
' '
4 млн ₽160 000 ₽ за м²
' '
01.03.2024В экспозиции 30 дней
'