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

This commit is contained in:
lekss361 2026-05-24 19:57:17 +00:00
parent 5394713bc7
commit 6bbb026cb4
2 changed files with 16 additions and 17 deletions

View file

@ -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

View file

@ -491,16 +491,16 @@ def test_area_regex_still_blocks_subfragment():
_DOM_FIXTURE_ROW_HTML = """
<div class="OffersArchiveSearchOffers__body">
<div class="OffersArchiveSearchOffers__row">
<div class="OffersArchiveSearchOffers__cell">48,5 м², 1-комнатная</div>
<div class="OffersArchiveSearchOffers__cell">19 этаж</div>
<div class="OffersArchiveSearchOffers__cell"></div>
<div class="OffersArchiveSearchOffers__cell">48,5 м², 1-комнатная19 этаж</div>
<div class="OffersArchiveSearchOffers__cell">5,1 млн 105 155 за м²</div>
<div class="OffersArchiveSearchOffers__cell">5,1 млн 105 155 за м²</div>
<div class="OffersArchiveSearchOffers__cell">23.10.2023В экспозиции 945 дней</div>
<div class="OffersArchiveSearchOffers__cell">В продаже</div>
</div>
<div class="OffersArchiveSearchOffers__row">
<div class="OffersArchiveSearchOffers__cell">58,2 м², 2-комнатная</div>
<div class="OffersArchiveSearchOffers__cell">3 этаж</div>
<div class="OffersArchiveSearchOffers__cell"></div>
<div class="OffersArchiveSearchOffers__cell">58,2 м², 2-комнатная3 этаж</div>
<div class="OffersArchiveSearchOffers__cell">9,3 млн 159 932 за м²</div>
<div class="OffersArchiveSearchOffers__cell">8,9 млн 152 062 за м²</div>
<div class="OffersArchiveSearchOffers__cell">12.02.2026В экспозиции 156 дней</div>
@ -552,8 +552,8 @@ def test_dom_parser_studio_row():
html = (
"<html><body>"
'<div class="OffersArchiveSearchOffers__row">'
' <div class="OffersArchiveSearchOffers__cell">Студия 25 м²</div>'
' <div class="OffersArchiveSearchOffers__cell">5 этаж</div>'
' <div class="OffersArchiveSearchOffers__cell"></div>'
' <div class="OffersArchiveSearchOffers__cell">Студия 25 м²5 этаж</div>'
' <div class="OffersArchiveSearchOffers__cell">4 млн ₽160 000 ₽ за м²</div>'
' <div class="OffersArchiveSearchOffers__cell">4 млн ₽160 000 ₽ за м²</div>'
' <div class="OffersArchiveSearchOffers__cell">01.03.2024В экспозиции 30 дней</div>'