feat(tradein/avito): per-card ЕКБ гео-фильтр (отсечь padding по России) #1840

Merged
lekss361 merged 1 commit from feat/tradein-avito-ekb-filter-room-split into main 2026-06-20 14:14:03 +00:00
Owner

Проблема (live audit)

avito SERP для редких комбо (4+комн, дорогих) в ЕКБ возвращает мало результатов → Авито добивает выдачу «по всей России» (Москва/Челябинск/Омск/Тюмень...), а парсер глотает их как ЕКБ. Факт по БД: rooms=4 = 11307 листингов, из них ЕКБ только 498 (4%); rooms=3 — 44% ЕКБ. rooms=0/1/2 чисты (98-100%). Это раздувает 4+ бакет (медленный прогон, upd=745 не-ЕКБ за price-бакет) и засоряет БД.

На valuation напрямую почти не влияет (92% не-ЕКБ без координат → radius-фильтр их не берёт), но: бессмысленный «4-комн ЕКБ», bloat, медленный 4+ свип.

Фикс — per-card ЕКБ гео-фильтр

app/services/scrapers/avito.py::_parse_html: каждая SERP-карточка несёт свой source_url (из <a data-marker="item-title" href>). При settings.avito_serp_ekb_only=True карточка без /ekaterinburg/ в URL дропается (Авитошный padding имеет другие city-slug'и). Консервативно: если city-slug не извлёкся (path-сегмент в {kvartiry,item,catalog,user,api}) — карточка остаётся (не дропаем по ошибке). Лог: dropped N non-EKB cards (padding), M without city-slug kept.

  • Флаг avito_serp_ekb_only: bool = True (config.py; ENV AVITO_SERP_EKB_ONLY; False = старое).

4/5+ комнаты — УЖЕ разделены (проверено, не трогал)

ROOM_SLUGS уже содержит отдельные «4-комн.» и «5+комн.»; rooms берётся из заголовка карточки (_extract_rooms_from_title), не из бакета → 4/5/6 различаются по факту. Лумпинга нет — rooms=4=11307 был чисто не-ЕКБ padding (его и режет гео-фильтр).

Тесты

  • Новый tests/.../test_avito_ekb_geo_filter.py: 4 passed (ЕКБ оставляет, Москва/etc дропает, без city-slug — keep).
  • Полный pytest: 2236 passed, 1 skipped, 2 failed (pre-existing на main: cian cache + search auth).
  • ruff green.

Эффект

Будущие свипы: 4+ бакет = ~498 ЕКБ вместо 11307 всероссийских → быстрее + чисто, не засоряет.

⚠️ Деплой — ПОСЛЕ завершения текущего avito full_load (рекрейт scraper убьёт идущий прогон). Связано: аудит скрапперов 2026-06-20, #1796.

## Проблема (live audit) avito SERP для редких комбо (4+комн, дорогих) в ЕКБ возвращает мало результатов → **Авито добивает выдачу «по всей России»** (Москва/Челябинск/Омск/Тюмень...), а парсер глотает их как ЕКБ. Факт по БД: `rooms=4` = 11307 листингов, из них ЕКБ только **498 (4%)**; `rooms=3` — 44% ЕКБ. `rooms=0/1/2` чисты (98-100%). Это раздувает 4+ бакет (медленный прогон, `upd=745` не-ЕКБ за price-бакет) и засоряет БД. На valuation напрямую почти не влияет (92% не-ЕКБ без координат → radius-фильтр их не берёт), но: бессмысленный «4-комн ЕКБ», bloat, медленный 4+ свип. ## Фикс — per-card ЕКБ гео-фильтр `app/services/scrapers/avito.py::_parse_html`: каждая SERP-карточка несёт свой `source_url` (из `<a data-marker="item-title" href>`). При `settings.avito_serp_ekb_only=True` карточка без `/ekaterinburg/` в URL **дропается** (Авитошный padding имеет другие city-slug'и). Консервативно: если city-slug не извлёкся (path-сегмент в `{kvartiry,item,catalog,user,api}`) — карточка остаётся (не дропаем по ошибке). Лог: `dropped N non-EKB cards (padding), M without city-slug kept`. - Флаг `avito_serp_ekb_only: bool = True` (config.py; ENV `AVITO_SERP_EKB_ONLY`; False = старое). ## 4/5+ комнаты — УЖЕ разделены (проверено, не трогал) `ROOM_SLUGS` уже содержит отдельные `«4-комн.»` и `«5+комн.»`; `rooms` берётся из заголовка карточки (`_extract_rooms_from_title`), не из бакета → 4/5/6 различаются по факту. Лумпинга нет — `rooms=4=11307` был чисто не-ЕКБ padding (его и режет гео-фильтр). ## Тесты - Новый `tests/.../test_avito_ekb_geo_filter.py`: 4 passed (ЕКБ оставляет, Москва/etc дропает, без city-slug — keep). - Полный pytest: **2236 passed, 1 skipped, 2 failed** (pre-existing на main: cian cache + search auth). - ruff green. ## Эффект Будущие свипы: 4+ бакет = ~498 ЕКБ вместо 11307 всероссийских → быстрее + чисто, не засоряет. ⚠️ Деплой — ПОСЛЕ завершения текущего avito full_load (рекрейт scraper убьёт идущий прогон). Связано: аудит скрапперов 2026-06-20, #1796.
lekss361 added 1 commit 2026-06-20 14:00:45 +00:00
feat(tradein/avito): per-card ЕКБ гео-фильтр (отсечь padding по России) + сплит комнат 4/5+
All checks were successful
CI / changes (pull_request) Successful in 5s
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
f026423715
FIX 1: в _parse_html добавлен гео-фильтр per-card source_url. При
avito_serp_ekb_only=True (ENV AVITO_SERP_EKB_ONLY, дефолт True) карточки без
/ekaterinburg/ в source_url отбрасываются — Авито добивает выдачу
«по всей России» при малом числе ЕКБ-результатов (rooms=4 давал 96% не-ЕКБ).
Карточки без распознанного city-slug пропускаются консервативно.
Лог: «avito SERP: dropped N non-EKB cards (padding)».

FIX 2 (анализ): ROOM_SLUGS уже содержит отдельные бакеты «4-комн.» и «5+комн.»
(разбиты ранее). rooms-значение берётся из текста заголовка карточки
(_extract_rooms_from_title: regex «(\d)-к. квартира»), а не из бакета —
4/5/6 различаются по факту парсинга. Сплит slug'ов был сделан ранее, регрессий нет.

Тесты: 4 новых unit-теста в test_avito_ekb_geo_filter.py покрывают:
EKB+non-EKB → только EKB; ekb_only=False → все проходят;
без city-slug → консервативно оставляем; все EKB → ничего не дропается.
lekss361 merged commit 97d74e07a7 into main 2026-06-20 14:14:03 +00:00
lekss361 deleted branch feat/tradein-avito-ekb-filter-room-split 2026-06-20 14:14:03 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
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#1840
No description provided.