fix(tradein/avito): рейтинг дома перестаёт уезжать в адрес объявления (#2814)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 9s
CI / changes (pull_request) Successful in 8s
CI Trade-In / browser-tests (pull_request) Has been skipped
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
CI Trade-In / backend-tests (pull_request) Successful in 3m50s
CI Trade-In / frontend-checks (pull_request) Has been skipped
All checks were successful
CI Trade-In / changes (pull_request) Successful in 9s
CI / changes (pull_request) Successful in 8s
CI Trade-In / browser-tests (pull_request) Has been skipped
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
CI Trade-In / backend-tests (pull_request) Successful in 3m50s
CI Trade-In / frontend-checks (pull_request) Has been skipped
Авито с 27.07 рендерит рейтинг и число отзывов внутри того же <p> в data-marker="item-location", откуда serp.py берёт адрес: «ул. Ткачей,17·5,0 · 4 отзыва». Прод 2026-08-10: 1 123 активных объявления с таким адресом, и у 1 123 из 1 123 нет координат — доля 100%, 711 из них геокодер уже пробовал. Контроль в тех же данных: у чистых адресов координаты есть у 4 766 из 5 715 (83%). Строка без geom молча выпадает из comp-пула: Tier W отбирает через ST_DWithin, а NULL не проходит предикат и нигде не считается. 2 446 из 3 270 безкоординатных попадают в свежий пул аналогов — 12.7% аналогов невидимы радиусному поиску. Режем по «·», за которой идёт ЦИФРА (рейтинг «·4,9», счётчик «·2 отзыва»). По любой «·» нельзя: разделитель района пишется «, 59 · р-н Академический» — за точкой буква, и этот хвост _deglue_house_marker намеренно сохраняет (#1773). Тест проверяет обе стороны плюс три прежних хвоста (CSS, метро, «от N мин.»). Чинит только новые вставки: base.py пишет address = COALESCE(listings.address, EXCLUDED.address), адрес при конфликте не перезаписывается осознанно (#2777). Бэкфилл 1 123 существующих строк вынесен в #2814 для database-expert.
This commit is contained in:
parent
272abac4d2
commit
ab5c4b86cd
2 changed files with 68 additions and 1 deletions
|
|
@ -0,0 +1,59 @@
|
|||
"""Адрес Авито не должен утаскивать за собой рейтинг дома и число отзывов.
|
||||
|
||||
Прод 2026-08-10: 1 123 активных объявления Авито с адресом вида
|
||||
«ул. Ткачей,17·5,0 · 4 отзыва», и у 1 123 из 1 123 нет координат — доля 100%.
|
||||
У объявлений с чистым адресом координаты есть у 4 766. Хвост появился 27.07.2026,
|
||||
когда Авито начал рендерить рейтинг внутри того же <p> в item-location.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
from scraper_kit.providers.avito.serp import _clean_address
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("raw", "expected"),
|
||||
[
|
||||
# Живые строки с прода — рейтинг + счётчик отзывов.
|
||||
("Авиационная ул.,10·4,9 · 11 отзывов", "Авиационная ул.,10"),
|
||||
("ул. 8 Марта,204Г/2·4,3 · 3 отзыва", "ул. 8 Марта,204Г/2"),
|
||||
("ул. Академика Шварца,18к2·1 отзыв", "ул. Академика Шварца,18к2"),
|
||||
# Только счётчик, без рейтинга.
|
||||
("ул. Фурманова,59·2 отзыва", "ул. Фурманова,59"),
|
||||
# Пробелы вокруг разделителя.
|
||||
("ул. Ткачей, 17 · 5,0 · 4 отзыва", "ул. Ткачей, 17"),
|
||||
],
|
||||
)
|
||||
def test_rating_tail_stripped(raw: str, expected: str) -> None:
|
||||
assert _clean_address(raw) == expected
|
||||
|
||||
|
||||
def test_district_marker_after_dot_survives() -> None:
|
||||
"""Режем «·» только перед цифрой — район за точкой остаётся на месте.
|
||||
|
||||
Иначе фикс рейтинга съел бы разделитель района, который _deglue_house_marker
|
||||
намеренно восстанавливает (#1773).
|
||||
"""
|
||||
assert (
|
||||
_clean_address("улица Вильгельма де Геннина, 59 · р-н Академический")
|
||||
== "улица Вильгельма де Геннина, 59 · р-н Академический"
|
||||
)
|
||||
|
||||
|
||||
def test_clean_address_unchanged() -> None:
|
||||
assert _clean_address("с. Новоалексеевское, ул. 8 Марта,35") == (
|
||||
"с. Новоалексеевское, ул. 8 Марта,35"
|
||||
)
|
||||
|
||||
|
||||
def test_existing_noise_still_stripped() -> None:
|
||||
"""Регрессия: старые хвосты (CSS/метро/«от N мин.») режутся как раньше."""
|
||||
assert _clean_address("ул. Токарей, 56к1Площадь 1905 года.css-39hgr0{fill:red}") == (
|
||||
"ул. Токарей, 56к1"
|
||||
)
|
||||
assert _clean_address("ул. Малышева, 1.css-xxx{color:blue}") == "ул. Малышева, 1"
|
||||
# #1773: слипшийся маркер района по-прежнему расклеивается.
|
||||
assert _clean_address("ул. Евгения Савкова, 29р-н Академический") == (
|
||||
"ул. Евгения Савкова, 29, р-н Академический"
|
||||
)
|
||||
|
|
@ -2097,8 +2097,16 @@ def _avito_room_label(name: str) -> str:
|
|||
|
||||
|
||||
_CSS_NOISE_RE = re.compile(r"\.?css-[a-z0-9_-]+\s*\{[^}]*\}", flags=re.I)
|
||||
# Хвост «·<цифра>» — рейтинг дома и число отзывов, которые Авито с 27.07.2026 рендерит
|
||||
# ВНУТРИ того же <p> в data-marker="item-location": «ул. Ткачей,17·5,0 · 4 отзыва».
|
||||
# Прод 2026-08-10: 1 123 активных объявления с таким адресом, и у 1 123 из 1 123 нет
|
||||
# координат (доля 100%) — ни один геокодер такую строку не берёт. Для сравнения, у
|
||||
# объявлений с чистым адресом координаты есть у 4 766.
|
||||
# Режем по «·», ЗА КОТОРОЙ ИДЁТ ЦИФРА (рейтинг «·4,9» либо счётчик «·2 отзыва»), а не
|
||||
# по любой «·»: разделитель района у площадок пишется как «, 59 · р-н Академический» —
|
||||
# за точкой буква, и такой хвост _deglue_house_marker намеренно сохраняет.
|
||||
_NOT_ADDRESS_TAIL_RE = re.compile(
|
||||
r"\s*(Площадь \d|от \d+\s?мин\.|css-[a-z0-9_-]+)",
|
||||
r"\s*(Площадь \d|от \d+\s?мин\.|css-[a-z0-9_-]+|·\s*\d)",
|
||||
flags=re.I,
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue