Парсер карточки Авито недобирает поля: параметры дома теряются молча, метро тянется из описания, собственник не парсится #3047

Closed
opened 2026-08-21 20:39:08 +00:00 by lekss361 · 1 comment
Owner

Найдено 2026-08-21 при подготовке к массовому обогащению. Замер покрытия по listings (54 855 строк с source='avito'):

Поле avito для сравнения
sale_type 2 465 cian 23 441, domklik 5 816
metro_stations 28 cian 21 112, yandex 17 153
is_homeowner 0 cian 7 712
days_on_market 0 yandex 17 983
cadastral_number 0 у всех источников 0

sale_type по месяцам среди обогащённых: май 10, июнь 1 838 (59%), июль 95, август 39 (1,6%) — то есть работало и деградировало.

Корневой дефект: читался только первый блок параметров

Авито отдаёт «О квартире» и «О доме» как два отдельных <div data-marker='item-view/item-params'>, каждый со своим <ul>. Код брал tree.css_first(...) — только первый.

sale_type лежит в первом блоке, поэтому он не задевался. А house_type, total_floors_house и лифты — во втором, и терялись молча на каждой карточке. Ветка, которая должна была это ловить, проверяла len(ul_els) >= 2 внутри первого div — она не срабатывала никогда, потому что там всегда ровно один <ul>.

Это же объясняет houses_enriched: 0 в прогоне 17:33: #3040 пишет параметры дома из карточки в houses, а параметры всегда приходили пустыми.

Остальные поля

  • metro_stations тянулись регуляркой из текста описания. Отсюда 28 записей против 21 112 у ЦИАН: шаблон ловил суффиксы -ская/-инская, а «Уралмаш» и «Машиностроителей» под него не попадали. В разметке метро есть — div#item-view-address, иконка «Пешком до метро».
  • is_homeowner не парсился вовсе. Структурный признак есть: [data-marker='seller-info/label'] со значением «Частное лицо» / «Агентство».
  • days_on_market в явном виде на странице отсутствует, но выводится из даты публикации. Попутно выяснилось, что publish_date тоже никогда не парсился — дата лежит в соседнем [data-marker='item-view/item-date'], а код искал её внутри блока item-view/item-id.
  • cadastral_number на карточке отсутствует. Проверено на двух эталонах: ни текста «кадастр», ни значения. Единственный след — пустое поле domotekaReportTeaser.cadastralNumber в JSON-блоке, схема зарезервирована Авито, но не заполняется. Колонка не заполняется ни одним источником — парсить нечего.

Чего эти поля НЕ делают

Ни одно из них не влияет на цену. Проверено по estimator.py: sale_type, is_homeowner, metro_stations не упоминаются вовсе; cadastral_number там относится к другой колонке (building_cadastral_number, её заполняет геопоиск). Это витрина плюс days_on_market, который питает прогноз срока продажи est_days_on_market, а не стоимость.

Поэтому задача — не про точность оценки, а про полноту данных перед массовым обогащением 11 021 карточки: гонять их, зная, что парсер недобирает поля, значит гонять дважды.

Оговорка

Продакшн-регрессию sale_type (59% → 1,6%) две эталонные карточки не воспроизводят — обе парсятся верно и до, и после правки. Значит падение покрытия вызвано скорее блокировками на части фетчей, чем структурой страницы. Найденный дефект чтения при этом реален и исправлен.

Осталось за рамками

address_full тоже всегда None[itemprop='address'] в разметке не существует, там другой набор. Отдельная задача.

Найдено 2026-08-21 при подготовке к массовому обогащению. Замер покрытия по `listings` (54 855 строк с `source='avito'`): | Поле | avito | для сравнения | |---|---|---| | `sale_type` | 2 465 | cian 23 441, domklik 5 816 | | `metro_stations` | **28** | cian 21 112, yandex 17 153 | | `is_homeowner` | **0** | cian 7 712 | | `days_on_market` | **0** | yandex 17 983 | | `cadastral_number` | **0** | у всех источников 0 | `sale_type` по месяцам среди обогащённых: май 10, **июнь 1 838 (59%)**, июль 95, август 39 (1,6%) — то есть работало и деградировало. ## Корневой дефект: читался только первый блок параметров Авито отдаёт «О квартире» и «О доме» как **два отдельных `<div data-marker='item-view/item-params'>`**, каждый со своим `<ul>`. Код брал `tree.css_first(...)` — только первый. `sale_type` лежит в первом блоке, поэтому он не задевался. А `house_type`, `total_floors_house` и лифты — во втором, и **терялись молча на каждой карточке**. Ветка, которая должна была это ловить, проверяла `len(ul_els) >= 2` внутри первого div — она не срабатывала никогда, потому что там всегда ровно один `<ul>`. **Это же объясняет `houses_enriched: 0`** в прогоне 17:33: #3040 пишет параметры дома из карточки в `houses`, а параметры всегда приходили пустыми. ## Остальные поля - **`metro_stations`** тянулись регуляркой из **текста описания**. Отсюда 28 записей против 21 112 у ЦИАН: шаблон ловил суффиксы `-ская`/`-инская`, а «Уралмаш» и «Машиностроителей» под него не попадали. В разметке метро есть — `div#item-view-address`, иконка «Пешком до метро». - **`is_homeowner`** не парсился вовсе. Структурный признак есть: `[data-marker='seller-info/label']` со значением «Частное лицо» / «Агентство». - **`days_on_market`** в явном виде на странице отсутствует, но выводится из даты публикации. Попутно выяснилось, что **`publish_date` тоже никогда не парсился** — дата лежит в соседнем `[data-marker='item-view/item-date']`, а код искал её внутри блока `item-view/item-id`. - **`cadastral_number` на карточке отсутствует.** Проверено на двух эталонах: ни текста «кадастр», ни значения. Единственный след — пустое поле `domotekaReportTeaser.cadastralNumber` в JSON-блоке, схема зарезервирована Авито, но не заполняется. Колонка не заполняется **ни одним** источником — парсить нечего. ## Чего эти поля НЕ делают Ни одно из них **не влияет на цену**. Проверено по `estimator.py`: `sale_type`, `is_homeowner`, `metro_stations` не упоминаются вовсе; `cadastral_number` там относится к другой колонке (`building_cadastral_number`, её заполняет геопоиск). Это витрина плюс `days_on_market`, который питает прогноз срока продажи `est_days_on_market`, а не стоимость. Поэтому задача — не про точность оценки, а про полноту данных перед массовым обогащением 11 021 карточки: гонять их, зная, что парсер недобирает поля, значит гонять дважды. ## Оговорка Продакшн-регрессию `sale_type` (59% → 1,6%) две эталонные карточки **не воспроизводят** — обе парсятся верно и до, и после правки. Значит падение покрытия вызвано скорее блокировками на части фетчей, чем структурой страницы. Найденный дефект чтения при этом реален и исправлен. ## Осталось за рамками `address_full` тоже всегда `None` — `[itemprop='address']` в разметке не существует, там другой набор. Отдельная задача.
Author
Owner

Проверено в коде на forgejo/main — сделано, закрываю.

PR #3048 (merged 2026-08-21) — парсер карточки читает все блоки; регресс закрыт тестами на реальной разметке (tests/test_avito_detail_fields_3047.py).

Проверено в коде на forgejo/main — сделано, закрываю. PR #3048 (merged 2026-08-21) — парсер карточки читает все блоки; регресс закрыт тестами на реальной разметке (tests/test_avito_detail_fields_3047.py).
Sign in to join this conversation.
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#3047
No description provided.