Домклик: число собственников снова читается, жилая площадь и балконы не стираются переобходом, нули в площадях — не площадь #3569
No reviewers
Labels
No labels
Fable 5 ревью
GG-форсайт
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
feedback/max
generative
needs-discussion
needs-human
observability
pause-bots
performance
priority/p0
priority/p1
priority/p2
priority/p3
scope/backend
scope/db
scope/devops
scope/frontend
scope/qa
scrapers
security
site-finder
stage/1
stage/2
status/blocked
status/done
status/needs-analysis
status/needs-fix
status/qa
status/ready
status/review
status/wip
tech-debt
tradein
ux
week ревью 1
wontfix
ИРД
вторичка
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#3569
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/domclick-card-fields"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
#3252 — что карточка Домклика отдаёт и что мы теряем
Как проверял. 17.09 браузером снял
window.__SSR_STATE__целиком с трёх живых карточек ЕКБ (2078784457, 2078257603, 2074362051) и сравнил с тем, что парсер читает и что лежит на проде у этих же объявлений (listings 10546614, 10546608, 10819282, обогащены 14.09). Прод — только SELECT в read-only транзакции.Дыра 1. Число собственников не читалось никогда с 29.08
egrnData.owners_count = {"status": "success", "value": 2}— обёртка, а не число. Парсер делалint()от словаря и молча получал None.owners_countзаполнен у 5075 из 6296 карточек ручного прогона 18.07 (там обёртку разворачивали,scripts/domclick_local_runner.py::_extract_owners_count) и у 0 из ~2970 карточек, обогащённых с 29.08. Той же обёрткой приходятareaиfloor:raw_payload.egrn_areaу 2156 строк лежит как{"value": 78.1, "status": "success"}._egrn_value()берётvalueпри любом статусе. Статус — это сверка с объявлением (у 2078257603area: {status: error, value: 65.3}при площади объявления 67.4), а значение — сам факт из ЕГРН. КлючegrnData.areaподтверждён, гаданияrosreestrArea/object_areaудалены. Вraw_payload.egrn_areaобёртка остаётся как есть.tests/scrapers/test_domclick_detail.pyфикстура «ground truth» держала egrnData скалярами — вот тест и не замечал. Поправил на живую форму.Дыра 2. Ноль вместо «не указано» в площадях
kitchenArea: 0, livingArea: 0(ремонт пустой, так Домклик пишет «не указано»). Парсер клал 0.00 в колонку, аCOALESCE(:new, old)ещё и затирал нулём ранее известную площадь.kitchen_area_m2 = 0— 303 строки,living_area_m2 = 0— 84, только domklik, все обогащены 26.08–14.09. У avito/cian/yandex/n1 нулей нет. У прогона 18.07 нулей тоже нет: там стоял_pos_float._pos_floatдля обеих площадей. Миграция 320: у domklik нулевые площади → NULL, ожидаемо 303 + 84 строки, при повторном запуске ничего не меняет. Проверил на локальной схеме: domklik 0/0 → NULL/NULL, domklik 12.5/0 → 12.5/NULL, avito 0/0 не тронут, второй прогон —UPDATE 0.Дыра 3. Жилую площадь и балконы стирал переобход выдачи
scraper_kit/base.pyапсерт писалliving_area_m2 = EXCLUDED.living_area_m2иbalconies_count = EXCLUDED.balconies_countс пометкой «Cian-specific». Выдача Домклика и Авито этих полей не отдаёт, поэтому каждый переобход ставил NULL поверх того, что добыла карточка. Та же болезнь, что #3063, соседниеkitchen_area_m2/phonesуже под COALESCE.livingArea: 25.8, balconies: 1, а на проде NULL/NULL приscraped_at16.09 >detail_enriched_at14.09. Разбивка по всему проду:«Жилая площадь у 16 из 3061 активных» из текста issue — это и есть переобход, а не нехватка добора.
SET, в правой части гейта #2992 (иначе строка считалась бы изменившейся на каждом проходе) и в reconcile-UPDATE при дрейфе dedup_hash.bedrooms/loggias/cadastral_*/description_minhashне трогал: карточки Домклика и Авито их не пишут, улик нет.Что по #3252 НЕ сделано (поэтому без Closes)
egrnData.floor {status,value}; вlegalOptions—isOwner,isOccupied,ownerMinors,residenceMinors,encumbranceSberbank,mortgage,neighbors; вobjectInfo—loggias,bathroom,restroom,windowView,redevelopment; вpricePrediction—rentLongPricePredicted/rentShortPricePredictedиsoldOffers(проданные рядом, сsoldDateи ценой); вhouseInfo.info—livingQuartersCount,elevatorsCount,hotWaterType,areaResidential,floors(по реестру, у 2078257603 это 27 против 25 у продавца); вproductCard.house.info—ceilingHeight,security,parking,yard.owners_countу уже обогащённых карточек этим PR не восстанавливаются: detail-добор Домклика берёт толькоdetail_enriched_at IS NULL. Перезапускать ли добор по уже обогащённым — решать владельцу.houseInfo.infoбывает пустым ({}у 2078784457). Запасной путьproductCard.house.wallTypeне существует: настоящий —house.info.wallType, но там словарь продавца («Кирпично-монолитный» против реестрового «Монолитно-кирпичный»). Если его включить, вraw_payload.wall_typeокажутся два словаря.balconies: 0— неясно, «нет балкона» или «не указано».building_cadastral_numberпишетcadastral_geo_match, а апсерт перезаписывает её сырымEXCLUDED— форма та же, что в дыре 3. Цифрами не проверял.#3253 п.3 — годится ли
domclick_building_guidключом дома (замер, кода нет)Пункты 1, 2 и 4 закрыты в #3356. Замер по проду 17.09, только SELECT: 9090 объявлений с guid, из них 9052 с
house_id_fk, 3784 guid.houses(derived против domklik с тем же адресом, это #2690/#1772). 18 пар на 30–150 м, 15 на 150 м–1 км, 2 дальше 1 км: смесь дублей с плохой геокодировкой (Сурикова 24 — 371 м при одном адресе) и ошибок матчера. Под guid один адрес, а объявление приклеено к чужому дому: «Краснолесья 96» → дом «Краснолесья 14к2», «Серова 45» → «Московская 249», «Калинина 59» → «40-летия Октября 33», «Белинского 135» → «Цвиллинга 18», «Азина 31» → «Печерская 4».Тесты
tests/test_3252_domclick_card_fields.py: 3 теста разбора на урезанном живом стейте и 2 поведенческих на живом Postgres (переобход не стирает площадь и балконы; новое значение перезаписывает). Живые — вskip_allowlist.txt, в CI бегут на postgres-сервисе.DATABASE_URL=…localhost:5432/test, после rebase: 6228 passed, 44 skipped, rc=0. До записи живых тестов в allowlist прогон честно дал rc=1 «НЕУЧТЁННЫЙ ПРОПУСК (2)».save_listings(включая #2992 и #3063) плюс domclick: 518 passed, rc=0.ruff check app tests— чисто,ruff format --checkпо изменённым — чисто. Вbase.pyruff format заодно склеил одну уже существовавшую строку лога.packages/scraper-kit: своих тестов нет (pytest rc=5, no tests),ruff check src— чисто.Фальсификация
Копии исходников до правки лежат рядом, после проверки восстановлены,
diff -qпуст.detail.pyдо правки → 3 failed:base.pyдо правки → 1 failed:Приёмка на проде (срок вердикта — 24.09.2026)
<deploy>— время деплоя этого PR.SELECT count(*) FROM _schema_migrations WHERE filename='320_listings_domclick_zero_area_to_null.sql'= 1, иSELECT count(*) FROM listings WHERE source='domklik' AND (kitchen_area_m2=0 OR living_area_m2=0)= 0 (было 303 + 84).SELECT source, count(*), count(living_area_m2) FROM listings WHERE source IN ('avito','domklik') AND detail_enriched_at > '<deploy>' AND scraped_at > detail_enriched_at + interval '1 minute' GROUP BY 1. У avito доля заполненнойliving_area_m2должна быть порядка 60 % (как у непереобойдённых), а не ~0 (было 1 из 8639).SELECT count(*), count(owners_count) FROM listings WHERE source='domklik' AND detail_enriched_at > '<deploy>'—count(owners_count)> 0, ожидаемо порядка 80 %.Пункт 3 и domklik-часть пункта 2 требуют хотя бы одного успешного detail-прогона Домклика. На 17.09 он 3.6 суток не собирает, сторож в логе scraper пишет
domclick_detail_backfill 3.6d/1d. Если к 24.09 успешного прогона не было, вердикт по ним откладывается с этой причиной.Связано: #3063, #2992, #3356, #2690.
🤖 Generated with Claude Code
Сверка парсера с живым __SSR_STATE__ трёх карточек (17.09) нашла три тихие дыры: 1. owners_count. egrnData отдаёт поля ЕГРН обёрткой {status, value}; int() от словаря молча давал None. Прод: 0 из ~2970 карточек, обогащённых с 29.08, против 5075 из 6296 у ручного прогона 18.07, который обёртку разворачивал. Ключ egrnData.area подтверждён — гадания rosreestrArea/object_area удалены, в raw_payload обёртка остаётся как есть (status = сверка с объявлением). 2. livingArea/kitchenArea = 0 у Домклика значит «не указано», а в колонку ложился 0.00 и затирал известное значение. Прод: 303 кухни и 84 жилые площади = 0, только domklik. Разбор: _pos_float; строки: миграция 320 ставит NULL. 3. Жилую площадь и балконы стирал переобход выдачи: апсерт scraper_kit.base писал их сырым EXCLUDED, а SERP Домклика и Авито этих полей не отдаёт. Прод: domklik, переобойдённые после обогащения, living_area_m2 0 из 5217 (без переобхода 2990 из 4058); avito 1 из 8639 (4122 из 6505). COALESCE в SET, в гейте #2992 и на reconcile-пути. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>