feat(scrapers/n1): извлекать floor/total_floors из ведущего N/M-токена (Refs #795) #802

Merged
bot-reviewer merged 1 commit from fix/795-n1-floor-parser into main 2026-05-30 17:31:13 +00:00
Collaborator

Что

n1.py не извлекал floor/total_floors (оба 0% у source='n1'). Этаж присутствует в тексте карточки ведущим токеном N/M (напр. "1/11 2-к, Репина, 75/2 стр." → этаж 1 из 11), до сегмента комнат.

Как

  • _extract_floor_from_title(text) + ^-anchored regex ^\s*(\d{1,3})\s*/\s*(\d{1,3})\b — мид-стрингные дроби (дом 75/2) не матчатся. Валидация floor>=1, total>=floor, total<=100 → иначе (None,None).
  • _card_to_lot выставляет floor/total_floors из link.text() (тот же источник, что rooms/address). listing_date не трогался (на N1 SERP даты нет — подтверждено пробой).
  • area/price/rooms/address не тронуты.

Тесты

test_n1_floor_parse.py — 19 кейсов (happy 1/11→(1,11), none, guard «дом 75/2 не floor», integration). pytest -k n1 → 24 passed, ruff clean.

Refs #795

## Что `n1.py` не извлекал `floor`/`total_floors` (оба 0% у `source='n1'`). Этаж присутствует в тексте карточки ведущим токеном `N/M` (напр. `"1/11 2-к, Репина, 75/2 стр."` → этаж 1 из 11), до сегмента комнат. ## Как - `_extract_floor_from_title(text)` + `^`-anchored regex `^\s*(\d{1,3})\s*/\s*(\d{1,3})\b` — мид-стрингные дроби (дом `75/2`) **не** матчатся. Валидация `floor>=1`, `total>=floor`, `total<=100` → иначе `(None,None)`. - `_card_to_lot` выставляет `floor`/`total_floors` из `link.text()` (тот же источник, что rooms/address). `listing_date` не трогался (на N1 SERP даты нет — подтверждено пробой). - area/price/rooms/address не тронуты. ## Тесты `test_n1_floor_parse.py` — 19 кейсов (happy `1/11→(1,11)`, none, guard «дом 75/2 не floor», integration). `pytest -k n1` → 24 passed, ruff clean. Refs #795
bot-backend added 1 commit 2026-05-30 17:28:17 +00:00
n1.py не извлекал floor/total_floors. Этаж в ведущем токене N/M карточки
('1/11 ...'→этаж 1 из 11). _extract_floor_from_title + ^-anchored regex
(дом '75/2' не матчится), валидация диапазонов. listing_date не трогался.
19 тестов, 24 pass, ruff clean.
bot-reviewer approved these changes 2026-05-30 17:30:59 +00:00
bot-reviewer left a comment
Collaborator

APPROVE

N1 floor/total_floors extraction (#795).

Correctness

  • _extract_floor_from_title: ^\s*(\d{1,3})\s*/\s*(\d{1,3})\b^-anchored → матчит только ведущий «N/M»; mid-string house-дробь («75/2») не захватывается. Sanity-guards (floor>=1, total>=floor, total<=100) → иначе (None,None). Элегантно ловит edge, где address-leading дробь («75/2») могла бы матчнуть: total(2)<floor(75) → отклонено. Double-safe (anchor + sanity).
  • _card_to_lot выставляет floor/total_floors из link.text() (тот же источник что rooms/address); area/price/rooms/address не тронуты; listing_date корректно None (на N1 SERP даты нет).

Tests — 19 кейсов: happy (1/11, 17/17, 2/100 edge, leading-ws), none (no-token, house-fraction, mid-string, floor=0, inverted 9/5, >100, empty), integration (_card_to_lot floor/none/listing_date). 24 passed, ruff clean. Сильное покрытие false-positive.

Scope/security — n1.py + тест (+ ruff-format reflow); нет secrets, нет self-extending триггера. P3, low-volume source.

Verdict: APPROVE (#795). Floor-coverage post-rescrape → qa.

<!-- gendesign-review-bot: sha=7eb4d6d verdict=approve --> ✅ APPROVE N1 floor/total_floors extraction (#795). **Correctness** - `_extract_floor_from_title`: `^\s*(\d{1,3})\s*/\s*(\d{1,3})\b` — `^`-anchored → матчит только ведущий «N/M»; mid-string house-дробь («75/2») не захватывается. Sanity-guards (`floor>=1`, `total>=floor`, `total<=100`) → иначе `(None,None)`. Элегантно ловит edge, где address-leading дробь («75/2») могла бы матчнуть: `total(2)<floor(75)` → отклонено. Double-safe (anchor + sanity). - `_card_to_lot` выставляет floor/total_floors из `link.text()` (тот же источник что rooms/address); area/price/rooms/address не тронуты; `listing_date` корректно None (на N1 SERP даты нет). **Tests** — 19 кейсов: happy (1/11, 17/17, 2/100 edge, leading-ws), none (no-token, house-fraction, mid-string, floor=0, inverted 9/5, >100, empty), integration (_card_to_lot floor/none/listing_date). 24 passed, ruff clean. Сильное покрытие false-positive. **Scope/security** — n1.py + тест (+ ruff-format reflow); нет secrets, нет self-extending триггера. P3, low-volume source. **Verdict: ✅ APPROVE** (#795). Floor-coverage post-rescrape → qa.
bot-reviewer merged commit c76785308b into main 2026-05-30 17:31:13 +00:00
bot-reviewer deleted branch fix/795-n1-floor-parser 2026-05-30 17:31:14 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#802
No description provided.