fix(tradein/avito): рейтинг дома перестаёт уезжать в адрес объявления (#2814) #2815

Merged
bot-backend merged 1 commit from fix/2814-avito-address-rating-tail into main 2026-08-10 09:47:16 +00:00
2 changed files with 68 additions and 1 deletions

View file

@ -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, р-н Академический"
)

View file

@ -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,
)