Avito leaks addresses with house number glued to district marker without separator («…Савкова, 29р-н Академический»), breaking house-number extraction and same-house matching (41 unmatched avito listings on one street). _clean_address now inserts ", " between a house-number token (digits + optional Cyrillic letter + optional /N|сN|кN|корпус|стр) and a following marker (р-н, мкр, район, г., пос, снт, …). - avito.py: idempotent _deglue_house_marker step (CSS/tail-strip kept) - tests: de-glue positive/negative/idempotency (24 passed) - data/sql/124_deglue_avito_addresses.sql: idempotent backfill for stored rows normalize.py НЕ тронут (общий fingerprint матчинга, #1534). Закрывает avito-часть #1773 (cian-без-номера + дедуп — отдельно, зона cian).
44 lines
3.4 KiB
PL/PgSQL
44 lines
3.4 KiB
PL/PgSQL
-- 124_deglue_avito_addresses.sql
|
||
-- #1773 — де-слип номера дома и маркера района/нас.пункта в listings.address (Avito).
|
||
--
|
||
-- ПРОБЛЕМА (прод). Avito-адреса хранят номер дома СЛИПШИМСЯ с маркером района без
|
||
-- разделителя: «…ул. Евгения Савкова, 29р-н Академический» (номер «29» приклеен к
|
||
-- «р-н Академический»). Паттерны из данных: «29р-н», «17Ар-н», «35/2р-н», «33с1р-н»,
|
||
-- «44Бр-н». Из-за склейки ломается извлечение номера дома и матчинг «того же дома»
|
||
-- (41 несматченный avito-листинг по одной улице).
|
||
--
|
||
-- ЧТО ДЕЛАЕТ. Вставляет «, » между токеном номера дома и следующим за ним маркером
|
||
-- района/нас.пункта без пробела. На ingest то же чинит avito.py::_clean_address;
|
||
-- этот backfill чистит УЖЕ сохранённые строки на деплое.
|
||
--
|
||
-- ПОЧЕМУ POSIX-ERE без lookahead. Postgres regexp_replace не поддерживает (?=…),
|
||
-- поэтому маркер фиксируется хвостовой группой \3 = «не кириллица/не цифра или конец»
|
||
-- (гарантирует, что маркер — целый токен, а не начало слова). Литера дома [А-Яа-яЁё]?
|
||
-- жадная, но движок обязан затем сматчить целый маркер вплотную — иначе совпадения нет.
|
||
-- Корпус «сN/кN» требует цифру, поэтому не путается с маркерами «с.» (село) / «к».
|
||
--
|
||
-- Idempotent: regexp_replace на уже-расклеенной строке («29, р-н») — no-op
|
||
-- (между номером и маркером уже стоит «, »); WHERE отбирает только ещё-слипшиеся
|
||
-- строки. Под gate _schema_migrations (ровно один раз).
|
||
-- Apply after: 123_avito_newbuilding_sweep_schedule.sql
|
||
|
||
BEGIN;
|
||
|
||
UPDATE listings
|
||
SET address = regexp_replace(
|
||
address,
|
||
-- \1 = токен номера дома (цифры + опц. литера + опц. корпус/строение)
|
||
-- \2 = маркер района/нас.пункта
|
||
-- \3 = хвостовая граница (не буква/цифра или конец строки)
|
||
'([0-9]+[А-Яа-яЁё]?(/[0-9]+|с[0-9]+|к[0-9]+|корп\.? ?[0-9]+|стр\.? ?[0-9]+)?)'
|
||
|| '(р-?н|мкр\.?|микрорайон|район|г\.|пос\.?|посёлок|поселок|снт|кв-л|квартал|д\.|с\.|пгт)'
|
||
|| '([^А-Яа-яЁё0-9]|$)',
|
||
'\1, \3\4',
|
||
'g'
|
||
)
|
||
WHERE source = 'avito'
|
||
AND address ~ ('([0-9]+[А-Яа-яЁё]?(/[0-9]+|с[0-9]+|к[0-9]+|корп\.? ?[0-9]+|стр\.? ?[0-9]+)?)'
|
||
|| '(р-?н|мкр\.?|микрорайон|район|г\.|пос\.?|посёлок|поселок|снт|кв-л|квартал|д\.|с\.|пгт)'
|
||
|| '([^А-Яа-яЁё0-9]|$)');
|
||
|
||
COMMIT;
|