logg-out.com

Как объединить объявления из разных источников без дублей

Как объединить объявления из разных источников без дублей

Когда вы собираете объявления с нескольких площадок, дубли появляются почти сразу. Один и тот же объект публикуют разные риелторы, собственник и агентство, причём в разных форматах: где-то полный адрес, где-то только район и ориентир, у одной записи свежие фото, у другой — актуальная цена. Чтобы агрегация стала полезной, недостаточно просто загрузить данные в базу. Нужно уметь сводить их в одну карточку объекта без потери качества и без ложных объединений, которые ломают выдачу и подрывают доверие пользователя.

Почему дубли в недвижимости — это не просто «повтор»

В недвижимости дубль — это не идентичная строка, а часто тот же объект, описанный по-разному. Один источник может указать полный адрес, другой — только район и ориентир. У одного объявления будут свежие фото, у другого — актуальная цена. Если склеить такие записи неправильно, пользователь увидит мусор вместо полезной выдачи: пять карточек одной и той же квартиры с разными ценами и наборами фотографий.

Проблема особенно заметна в аренде и вторичке: один объект может несколько раз попадать в выдачу из-за кросс-постинга, обновления объявления, изменения цены или смены посредника. Поэтому задача дедупликации — не «удалить лишнее», а понять, какие записи относятся к одному реальному объекту. И это не разовая операция, а постоянный процесс в пайплайне агрегатора.

Что считать дублем, а что — похожим объявлением

Перед настройкой алгоритма важно разделить три сценария, потому что от этого зависит порог уверенности и дальнейшие действия системы:

  • Точный дубль — записи совпадают почти полностью: один и тот же URL, одинаковые поля, те же фото. Так бывает при повторной публикации с одной площадки или копировании.
  • Вероятный дубль — объявление отличается в деталях, но адрес, площадь, этаж, планировка и фото указывают на один объект. Классический случай: собственник выложил объявление сам, а через неделю его же разместило агентство с новыми фотографиями и другой ценой.
  • Похожий, но не дубль — квартира в том же доме, но другая секция, этаж, корпус или планировка. Иногда отличить можно только по планировке или номеру квартиры, если он есть.

Это критично: если дедупликация слишком агрессивная, система начнёт склеивать разные квартиры и пользователь потеряет реальные варианты. Если слишком слабая — пользователь утонет в повторах и перестанет доверять выдаче.

Из каких признаков обычно собирают сигнал

На практике лучше смотреть не на один признак, а на набор полей. Чем больше независимых совпадений, тем выше уверенность. В реальных проектах я обычно комбинирую несколько источников сигнала, потому что ни одно поле не даёт стопроцентной гарантии.

Признак Что показывает Насколько полезен
Адрес Базовая привязка к объекту Очень высокий
Координаты Точное местоположение Очень высокий
Площадь Хороший идентификатор для квартиры Высокий
Цена Сильный, но изменчивый сигнал Средний
Этаж и этажность Помогают отличать похожие объекты Высокий
Количество комнат Уточняет тип объекта Средний
Фото Часто лучший визуальный маркер Очень высокий
Описание Полезно, но шумное поле Средний
Телефон/контакт Сильный источник связи между объявлениями Очень высокий
Источник и ссылка Помогают отличать повторную публикацию Высокий

Рабочая схема дедупликации

Для реальных проектов лучше использовать не один алгоритм, а несколько этапов. Такой подход устойчивее, чем попытка решить всё одной формулой. Ниже — проверенная на практике последовательность, которую можно подстроить под объёмы и особенности источников.

1. Нормализация данных

Сначала все объявления приводятся к единому виду. Без этого два одинаковых объекта могут выглядеть как совершенно разные записи. В моих парсерах этот этап занимает больше всего времени на старте: нужно продумать словари синонимов, регулярные выражения для извлечения чисел и единый формат для адресов.

  • адреса очищаются от лишних сокращений;
  • единицы измерения приводятся к одному формату;
  • цена переводится в одну валюту и один тип значения;
  • площади и этажи записываются как числа;
  • телефоны и ссылки нормализуются;
  • названия улиц, корпусов и ЖК унифицируются.

Например, «ул. Ленина, д. 5, к. 2» и «Ленина 5/2» после нормализации должны стать одной строкой. Если этого не сделать, сравнение по точному совпадению не сработает.

2. Быстрый поиск кандидатов

Нельзя сравнивать каждое объявление со всеми остальными: при больших объёмах это слишком дорого. Поэтому сначала отбирают кандидатов на совпадение по грубым фильтрам:

  • один город или район;
  • похожий адрес;
  • совпадающая комнатность;
  • близкая площадь;
  • один временной диапазон публикации.

Этот этап нужен, чтобы сократить число пар для проверки. В продакшене я использую индексы по нормализованным полям и блокирующие ключи: например, первые 6 символов от хеша адреса или комбинация «район + комнатность + площадь, округлённая до ближайших 5 м²». Такое «грубое» отсечение снижает вычислительную сложность с O(n²) до чего-то управляемого.

3. Оценка схожести

После отбора кандидатов считается общий score. Обычно он строится из нескольких частичных совпадений:

  • адрес совпал полностью — высокий балл;
  • площадь отличается незначительно — добавляем баллы;
  • фото визуально похожи — ещё один сильный сигнал;
  • описание пересекается по ключевым фразам — дополнительный аргумент;
  • телефон совпал — почти прямое подтверждение.

Важно не полагаться на один критерий. Например, цена может меняться, а в описании могут быть маркетинговые правки. Зато адрес, планировка и фото часто дают более надёжную картину. Для сравнения фото я использую perceptual hash: считаем средний хеш по уменьшенному изображению и сравниваем расстояние Хэмминга. Это быстро и отсекает большинство дублей, хотя и не идеально для разных ракурсов.

4. Группировка в кластеры

Если несколько объявлений относятся к одному объекту, их нужно объединить не попарно, а в кластер. Это значит, что система хранит одну сущность — объект недвижимости — и привязывает к ней все найденные публикации.

Такой подход удобен для пользователя: он видит не десять одинаковых карточек, а одну карточку с источниками. Технически это можно реализовать через union-find или граф, где узлы — объявления, а рёбра — совпадения выше порога. На выходе каждая компонента связности становится канонической карточкой с привязанными записями.

Как понять, что это один и тот же объект

Ниже — практическая логика, которая подходит для большинства real estate-проектов. Она основана на комбинации признаков и уровнях уверенности, которые можно настроить под конкретные источники.

Высокая вероятность дубля

Считайте записи дублем, если совпадает хотя бы один сильный набор признаков:

  • точный адрес + почти одинаковая площадь + совпадающие фото;
  • координаты + этаж + комнатность + похожее описание;
  • одинаковый контакт + адрес + объектные параметры.

Средняя вероятность

Случай требует ручной проверки, если:

  • адрес неполный;
  • фото отличаются, но есть похожая планировка;
  • цена отличается заметно, но остальные параметры совпадают;
  • объект опубликован на разных площадках в разное время.

Низкая вероятность

Скорее всего это разные объекты, если:

  • совпадает только район;
  • площадь и этаж отличаются существенно;
  • фото не пересекаются;
  • адрес указан расплывчато.

Типовые ошибки при объединении объявлений

За годы работы с агрегаторами я наступил на все эти грабли. Лучше знать их заранее, чем отлаживать ложные склейки в проде.

Ошибка 1. Слепая склейка по адресу

Один дом — это ещё не один объект. В большом доме может быть много одинаковых по метражу квартир. Без дополнительных признаков вы получите ложные совпадения. Например, в новостройке на 500 квартир адрес «улица Строителей, дом 10» ничего не говорит о конкретной квартире. Нужны этаж, планировка, номер квартиры или хотя бы фото.

Ошибка 2. Игнорирование изменений цены

Цена часто меняется, и это не повод считать объявление новым объектом. Но если цена сильно отличается вместе с другими полями, это может быть как новый источник, так и другая квартира. Лучше хранить историю цен и использовать цену как дополнительный сигнал, а не как решающий.

Ошибка 3. Доверие только тексту

Описание легко переписать. Риелторы часто меняют формулировки, добавляют маркетинговые слова или скрывают контакты. Текст хорош как вспомогательный сигнал, но не как единственный. Я обычно использую cosine similarity по TF-IDF или embedding’ам, но с низким весом, потому что описания слишком изменчивы.

Ошибка 4. Отсутствие приоритетов источников

Если источники отличаются качеством данных, нужен порядок доверия. Например, один источник может быть богаче по фото, другой — точнее по географии, третий — быстрее обновляться. Без приоритетов вы получите кашу в канонической карточке: устаревшая цена с одного источника, размытое фото с другого, неполный адрес с третьего.

Ошибка 5. Неучёт времени

Объявление могло быть снято и опубликовано заново. Если не учитывать дату и историю, система будет путать новый объект с архивной записью. Особенно это важно в аренде, где квартира может вернуться на рынок через полгода с новым ремонтом и ценой. Нужно вести историю статусов и уметь различать «снова активно» и «новый объект».

Как выбирать «главную» карточку среди дублей

После группировки нужно решить, какая запись станет основной. Обычно выбирают не «самую первую», а самую полезную.

Критерии выбора канонической записи

  • больше заполненных полей;
  • более свежие данные;
  • лучшие фото;
  • точнее адрес;
  • меньше ошибок и пропусков;
  • выше доверие к источнику.

Хорошая практика — хранить не только основную карточку, но и все исходные версии. Тогда можно восстановить историю изменений: цена, описание, наличие мебели, статус публикации. В архитектуре это обычно означает отдельную таблицу для канонических объектов и таблицу связей с исходными записями.

Что делать с конфликтующими данными

Иногда разные источники противоречат друг другу. Например, в одном объявлении 42 м², в другом 44 м². В таких случаях не стоит бездумно перезаписывать одно другим.

Рабочий подход такой:

  • для каждого поля задаётся приоритет источника;
  • конфликтные значения сохраняются в истории;
  • для пользователя показывается одно основное значение и при необходимости — уточнение;
  • если поле критичное, запись уходит на ручную проверку.

Особенно это важно для адреса, площади, комнатности и этажа. Ошибка в таких полях ломает всю дедупликацию дальше по цепочке. Я обычно ввожу систему «доверия» для каждого источника по каждому типу поля: например, источник A даёт точный адрес, но кривую площадь, а источник B — наоборот.

Пошаговый процесс для небольшого проекта

Если система только запускается, не усложняйте архитектуру раньше времени. Можно начать с понятного и надёжного пайплайна, который потом легко масштабировать.

Шаг 1. Приведите поля к единому формату

Соберите единый словарь адресов, форматов цен, площадей и типов объектов. Начните с самых частых источников и выпишите все вариации написания улиц, микрорайонов и ЖК.

Шаг 2. Настройте простые правила

Например:

  • совпадение точного адреса;
  • разница по площади не больше 2 м²;
  • разница по цене не больше 5–10%;
  • совпадение фото или телефона увеличивает уверенность.

Шаг 3. Сгруппируйте кандидатов

Сначала объединяйте только очевидные случаи. Всё спорное — в очередь на проверку. Не пытайтесь сразу автоматизировать все пограничные кейсы, иначе закопаетесь в отладке.

Шаг 4. Введите статус уверенности

У карточки должен быть не только результат, но и уровень доверия: высокий, средний, низкий. Это поможет приоритизировать ручную проверку и отслеживать качество.

Шаг 5. Сохраняйте историю

Храните связь между канонической записью и источниками. Это пригодится для отладки, аналитики и повторной проверки. Как минимум, пишите в лог, какие пары были объединены и по каким правилам.

Чек-лист для настройки дедупликации

  • Все адреса приведены к единому формату
  • Площадь, цена, этаж и комнатность нормализованы
  • Фото сравниваются хотя бы на базовом уровне
  • Есть правила отбора кандидатов
  • Есть пороги для уверенного и спорного совпадения
  • Назначен приоритет источников
  • Сохраняется история изменений
  • Спорные случаи отправляются на ручную проверку
  • Ложные совпадения отслеживаются и используются для улучшения правил

Когда без ручной проверки не обойтись

Автоматизация хорошо работает на больших объёмах, но полностью исключить ручную проверку нельзя. Она нужна, если:

  • адрес неполный или скрыт;
  • объект в новостройке без точной привязки;
  • много похожих квартир в одном доме;
  • фото одинакового качества и почти неразличимы;
  • данные пришли из источника с низкой точностью.

В зрелых системах ручная проверка нужна не для всех записей, а только для пограничных случаев. Это экономит время и повышает качество базы. Обычно такой интерфейс встраивают в админку: оператор видит пару кандидатов, исходные данные и кнопки «объединить» или «разделить».

Практический вывод

Объединение объявлений без дублей — это не одна функция, а цепочка из нормализации, отбора кандидатов, оценки схожести, группировки и контроля конфликтов. Чем больше сигналов система учитывает, тем меньше мусора увидит пользователь и тем полезнее будет агрегатор.

Если делать всё правильно, одна реальная квартира перестаёт превращаться в десять похожих карточек, а пользователь получает чистую, понятную выдачу с историей и источниками. И это, в конечном счёте, главная метрика успеха вашего агрегатора.

FAQ

Какой признак самый надёжный для поиска дублей?

Самые сильные сигналы — точный адрес, координаты, телефон и фото. Но надёжнее всего работает их комбинация, а не один признак. Я бы не стал полагаться только на телефон: его могут скрыть или сменить.

Можно ли объединять объявления только по цене и площади?

Нет. Эти поля полезны, но слишком часто совпадают у разных объектов. Без адреса, фото или дополнительных маркеров будут ложные склейки. Например, в одном доме может быть десяток квартир с одинаковой площадью и ценой.

Что делать, если одно объявление от собственника, а другое от риелтора?

Это частый случай. Если параметры объекта совпадают, такие записи обычно нужно объединять в одну карточку, но с сохранением всех источников. Пользователю не важно, кто разместил объявление, ему нужен сам объект.

Нужно ли хранить удалённые дубликаты?

Да. Лучше хранить не удаление, а связь с канонической записью и историю изменений. Это помогает анализировать рынок и отлаживать дедупликацию. Удалённые записи могут пригодиться, если правила поменяются.

Какой подход лучше: правила или ML-модель?

Для старта — правила и нормализация. Для больших объёмов и сложных кейсов лучше гибридный подход: правила для очевидных совпадений, модель для спорных. ML-модель можно обучить на размеченных вручную парах, когда накопится достаточно данных.