Идентичность документа: каноникализация и дубли

Рейтинг: 72.2% · 10 голосов
Полный курс об устройстве веб-поиска: обход, индексирование, факторы ранжирования, нейропоиск, поведенческие сигналы, антиспам, SEO. 23 модуля по главам с разбором и обсуждением.
Ответить
Аватара пользователя
kirill_ir
Сообщения: 25
Зарегистрирован: 11 май 2026, 05:31

Идентичность документа: каноникализация и дубли

Сообщение kirill_ir »

Оглавление курса (23)
  1. Введение
  2. Теоретический фундамент (Information Retrieval)
  3. Краулинг (обход)
  4. Идентичность документа: каноникализация и дубли (вы здесь)
  5. Индексирование и хранение
  6. Обработка и понимание запроса
  7. Текстовая релевантность
  8. Анализ ссылочного графа
  9. Таксономия факторов ранжирования
  10. Машинное обучение ранжированию (Learning-to-Rank)
  11. Нейросетевой поиск (Neural IR)
  12. Поведенческие сигналы и клик-модели
  13. Каскад ранжирования и обслуживание (serving)
  14. Инфраструктура и распределённое обслуживание
  15. Метапоиск и федерация источников
  16. Группировка, схлопывание, разнообразие
  17. Постранжирование, антиспам и качество выдачи
  18. Свежесть и реалтайм
  19. Локализация, гео и персонализация
  20. Измерение качества и эксперименты
  21. SEO: оптимизация под факторы
  22. Этика, приватность и борьба со злоупотреблениями
  23. Capstone: сквозной проект
Часть II · ~6 ч · Сложность: (средний) · Пререквизиты: Модуль 2
Обзор модуля

В Модуле 2 планировщик обхода скачал из веба миллиарды HTTP-ответов. Но «ответ по URL» — это ещё не «документ». Один и тот же материал лежит под десятками адресов (http/https, www/без, со слэшем и без, с UTM-метками, через зеркала и CDN), а множество разных адресов отдают почти одинаковый текст (пагинация, версии для печати, агрегаторы, скопированные новости). Прежде чем индексатор (Модуль 4) построит обратный индекс, кто-то должен ответить на вопрос: что считать одним документом? Этим занимается каноникализатор — компонент офлайн-конвейера между обходом и индексацией.

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

Главная мысль модуля: каноникализация определяет НОСИТЕЛЯ всех факторов. Все сигналы курса — авторитет по ссылкам (Модуль 7), поведенческие клики (Модуль 11), накопленная свежесть, репутация хоста и владельца (Модуль 16) — привязываются не к URL-строке, а к канонической единице. Если каноникализатор ошибся и развёл один документ на три дубля, то ссылки, клики и история тоже расщепляются на три части: каждая копия выглядит слабой, ни одна не набирает критической массы сигналов, и сильный документ проигрывает в ранжировании. Каноникализация — «нулевой фактор»: она не влияет на скоринг напрямую, но задаёт сущность, к которой все остальные факторы относятся.

После модуля вы будете уметь нормализовать URL без потери и без ложного склеивания смысла, проектировать процедуру выбора главного зеркала, реализовывать near-duplicate detection через шинглы, MinHash и SimHash с кластеризацией, а также понимать, как группировка по владельцу подпирает все последующие сигналы.

Как читать по трекам
  • Студент CES — обязательно главы 3.1, 3.3 (вывод MinHash/SimHash — ядро модуля), 3.4. Глава 3.2 — на уровне принципа. Сделайте лабу по SimHash.
  • Инженер — всё обязательно. Особое внимание: каноникализация как офлайн-стадия конвейера, потоковая дедупликация при обходе, выбор представителя кластера, влияние ошибок склейки на индекс и serving (связь с Модулями 4, 12).
  • SEO — обязательно 3.1 (нормализация, rel=canonical), 3.2 (зеркала, склейка www/https), 3.4 (владелец и хостовые сигналы). Все SEO-врезки. Математику MinHash/SimHash в 3.3 — обзорно, но понимать вывод «дубль = размывание сигналов» строго обязательно.
  • Смешанный — обзор модуля, главы 3.1 и 3.4 целиком, идея 3.3 без вывода формул.
Карта модуля
  • 3.1. Нормализация URL и выбор канонической формы — как из множества эквивалентных адресов выбрать один, не потеряв и не склеив смысл.
  • 3.2. Зеркала хостов и выбор главного зеркала — обнаружение хостов с идентичным содержимым и выбор представителя.
  • 3.3. Near-duplicate detection — шинглы, MinHash, SimHash, кластеризация почти-дублей.
  • 3.4. Группировка по владельцу (owner) — «нулевой фактор», на котором держатся все остальные сигналы.
Глава 3.1. Нормализация URL и выбор канонической формы (средний)

Цели обучения

После главы студент сможет:
  • Объяснить, почему один документ имеет множество URL-представлений и чем это вредит поиску.
  • Перечислить безопасные и небезопасные правила нормализации URL и обосновать различие.
  • Реализовать процедуру нормализации URL, дающую стабильный ключ дедупликации.
  • Объяснить роль директивы rel=canonical и её отношение к серверной нормализации.
  • Оценить риски ложного склеивания и ложного разведения адресов.
Конспект

URL — это адрес ответа, а не идентичность содержимого. Проблема в том, что синтаксически разные строки-URL сплошь и рядом указывают на один и тот же ресурс. Цель нормализации — привести эквивалентные URL к единой канонической форме (canonical form), чтобы дедупликация, фронтир обхода и привязка сигналов работали с одним ключом.
Интуиция. Представьте, что у дома есть десяток записей адреса: «ул. Садовая, д. 5», «Садовая 5», «садовая, 5 (вход со двора)». Почтальон должен понимать, что это один дом, иначе разнесёт письма по разным «ящикам», и ни один не окажется полным. URL-нормализация — это приведение всех записей адреса к одной канонической строке.
Источники множественности URL

Один документ порождает множество адресов из-за:
  • Схемы и порта: http:// против https://, явный :80/:443.
  • Хоста: www. против голого домена, разный регистр хоста (хост регистронезависим).
  • Пути: завершающий слэш (/page vs /page/), регистр (на части серверов путь регистрозависим, на части — нет), index.html как индекс каталога, сегменты ./ и ../.
  • Query-string: порядок параметров, дублирующиеся параметры, трекинговые метки (UTM, идентификаторы сессий, рефереры), параметры, не влияющие на контент.
  • Фрагмента (#...): якорь внутри страницы, который сервер вообще не видит.
  • Процентного кодирования: %2D против -, регистр hex-цифр, кодирование незарезервированных символов.
Безопасные правила нормализации

«Безопасные» правила определены так, что не меняют смысл ресурса по стандарту URI — их можно применять почти всегда:

Код: Выделить всё

Правило                                  |  Было                  |  Стало
-----------------------------------------+------------------------+----------------------
Нижний регистр схемы и хоста             |  HTTP://Example.COM/A  |  http://example.com/A
Удалить порт по умолчанию                |  https://h:443/p       |  https://h/p
Декодировать незарезервированные октеты  |  /%7Euser              |  /~user
Привести регистр процент-кодов           |  /a%2fb                |  /a%2Fb
Убрать ./..-сегменты                     |  /a/./b/../c           |  /a/c
Удалить фрагмент                         |  /p#section            |  /p
Пустой путь → /                          |  http://h              |  http://h/
Инженерная заметка. Удаление фрагмента безопасно для серверной идентичности, но осторожно: на SPA-сайтах фрагмент после #! (исторический hashbang) или внутри JS-роутинга мог адресовать разный контент. В современном вебе это редкость, но каноникализатор должен иметь исключения для известных паттернов.
Небезопасные (эвристические) правила

Эти правила меняют ключ дедупликации и могут ошибиться — применяются только при наличии подтверждающих сигналов:
  • Завершающий слэш. /page и /page/ обычно одно и то же, но формально это разные ресурсы. Решение принимают по факту: одинаковый ли ответ, есть ли редирект одного на другой.
  • www vs голый домен — на самом деле задача склейки зеркал (глава 3.2), а не чистой нормализации.
  • Удаление параметров. Трекинговые метки (utm_*, sessionid, fbclid-подобные) почти всегда не влияют на контент — их режут. Но параметр ?id=42 или ?page=2 контент-определяющий, и его резать нельзя.
  • Сортировка параметров. ?a=1&b=2 и ?b=2&a=1 обычно эквивалентны, но не на всех бэкендах.
Внимание. Граница «контент-определяющий vs незначимый параметр» — главный источник ошибок. Слишком агрессивная резка склеит разные товары в один; слишком осторожная — разведёт один документ на тысячи URL по сессиям. На практике классификацию параметров ведут per-host: каноникализатор накапливает статистику «меняет ли этот параметр содержимое» по реально скачанным ответам.
Канонический ключ и редиректы

Результат нормализации — канонический ключ (стабильная строка или её хеш), под которым документ живёт во всём конвейере. Помогают подтверждающие сигналы:
  • HTTP-редиректы (301/308 постоянные, 302/307 временные): если A устойчиво ведёт на B, то B — кандидат в канонические, а сигналы A наследуются B.
  • Идентичность тела ответа: два URL вернули байт-в-байт (или почти, см. 3.3) одинаковое — повод склеить.
  • Декларация rel=canonical в HTML-разметке: сайт сам подсказывает предпочтительный адрес.

Код: Выделить всё

Множество сырых URL                Каноникализатор                Канонический ключ
http://Example.com/p?utm=x#top  ┐
https://example.com/p/          ┼──►  нормализация + редиректы ──►  https://example.com/p
HTTPS://EXAMPLE.COM:443/p       ┘     + rel=canonical + сигналы
SEO-врезка. rel=canonical — это подсказка, а не приказ. Каноникализатор учитывает её как один сигнал наряду с редиректами, картой сайта, внутренней перелинковкой и идентичностью контента. Если вы указали rel=canonical на одну страницу, но ссылаетесь и редиректите на другую, поисковая система выберет ту, в которую «верит» совокупность сигналов. Правила гигиены: канонический URL — абсолютный и самореферентный (страница указывает каноником саму себя), он отдаёт 200, а не редирект/404, и совпадает с тем, что в карте сайта и во внутренних ссылках. Чем меньше противоречий между сигналами, тем предсказуемее склейка.
SEO-врезка. Параметры-метки (utm_*, идентификаторы кампаний) для каноникализатора — шум. Полагаться на то, что они «разведут» страницы, нельзя: их режут. И наоборот — если важные варианты товара различаются только параметром, который похож на трекинговый, их рискуют ошибочно склеить. Делайте контент-определяющие параметры явно «непохожими на метки» (?color=red, а не ?c=1) и при необходимости отдавайте отдельные канонические URL без меток.
Частые заблуждения
Заблуждение. «Достаточно сравнивать URL как строки — одинаковые строки = один документ.» Наоборот: строковое равенство ловит лишь часть случаев. http://h/a и https://h/a/ — разные строки, но один документ; ?page=1 и ?page=2 — почти одинаковые строки, но разные документы. Нужна нормализация по смыслу, а не по символам.
Заблуждение. «rel=canonical гарантированно склеит мои страницы так, как я написал.» Это сигнал-подсказка. При противоречии с редиректами, контентом и перелинковкой система выберет по совокупности, а не по одной директиве.
Лаба / практика

Нормализатор URL и ключ дедупликации. Дан список из ~30 сырых URL (включает регистр хоста, порты по умолчанию, #-фрагменты, utm_*, перестановку параметров, .//../, index.html).

Шаги:
  1. Реализуйте функцию normalize(url) со всеми безопасными правилами из таблицы.
  2. Добавьте резку списка известных трекинговых параметров и сортировку оставшихся.
  3. Сгруппируйте входные URL по полученному ключу; выведите кластеры.
  4. Найдите пару, которую ваша эвристика склеила ошибочно (например, по слишком широкой резке параметра), и опишите, какой подтверждающий сигнал (редирект/идентичность тела) предотвратил бы ошибку.
Псевдокод:

Код: Выделить всё

def normalize(u):
    p = parse(u)
    p.scheme = p.scheme.lower()
    p.host   = p.host.lower()
    p = drop_default_port(p)
    p.path = remove_dot_segments(p.path) or "/"
    p.fragment = ""
    q = [(k, v) for k, v in p.query if k not in TRACKING_PARAMS]
    p.query = sorted(q)
    return rebuild(p)
Время ~40 мин. Критерий «сделано»: эквивалентные URL дают один ключ; найден и объяснён один случай ложного склеивания и сигнал против него.

Контрольные вопросы
  1. Почему регистр хоста можно приводить к нижнему, а регистр пути — нет?
  2. Какие правила нормализации называются «безопасными» и в каком смысле?
  3. Чем отличается резка utm_source от резки ?page? Как каноникализатор различает их на практике?
  4. Почему фрагмент #... обычно удаляют и в каком случае это опасно?
  5. Является ли rel=canonical обязательной для исполнения? Что перевесит её при конфликте сигналов?
  6. Чем грозит слишком агрессивная и слишком осторожная резка query-параметров?
  7. Как редиректы 301 участвуют в выборе канонической формы и наследовании сигналов?
Глава 3.2. Зеркала хостов и выбор главного зеркала (средний)

Цели обучения

После главы студент сможет:
  • Дать определение зеркала (mirror) и отличить его от near-duplicate отдельных страниц.
  • Объяснить, почему зеркала нужно склеивать на уровне хоста, а не каждой страницы по отдельности.
  • Перечислить сигналы обнаружения зеркал и факторы выбора главного зеркала.
  • Описать, как склейка зеркал переносит сигналы (ссылки, авторитет) на представителя.
Конспект

Зеркало (mirror) — хост, отдающий то же содержимое, что и другой хост, с согласованной структурой URL. Классические случаи: www.site и site; http-версия и https-версия; региональные алиасы (site.example ↔ example); CDN-домены; отдельный домен «для печати» или мобильная версия; полностью скопированный сайт под другим доменом.
Интуиция. Если глава 3.1 решала «какая из строк-адресов одного дома правильная», то 3.2 решает «у этих двух разных зданий одинаковая планировка всех квартир — это один жилой комплекс или два?» Когда оказывается, что один — точная копия другого, мы объявляем один из них главным зданием, и вся почта (сигналы) идёт туда.
Почему склейка на уровне хоста

Можно было бы детектить дубли постранично (это глава 3.3), но для зеркал это расточительно и неточно. Если www.site/p ≡ site/p для тысяч страниц, выгоднее установить хостовое отображение www.site → site один раз и применять его ко всем путям. Это:
  • экономит ресурсы обхода (не качаем оба зеркала целиком);
  • даёт стабильную склейку даже для страниц, которые поодиночке выглядят непохоже;
  • позволяет переносить хостовые сигналы (репутация, история, авторитет домена) на одного носителя.
Обнаружение зеркал

Сигналы, что два хоста — зеркала:
  • Совпадение содержимого по выборке путей. Берём набор путей, существующих на обоих хостах, сравниваем тела (через near-duplicate из 3.3). Высокая доля совпадений → зеркала.
  • Структурная согласованность URL. Один и тот же путь /a/b/c есть на обоих и отдаёт одно и то же.
  • Редиректы между хостами. Если http://h устойчиво 301→ https://h, или site → www.site, это прямое объявление главного зеркала самим сайтом.
  • DNS/сетевые признаки (один IP, общий сертификат, охватывающий оба имени) — слабые вспомогательные сигналы.
  • Совпадение карты сайта и внутренней перелинковки.
Инженерная заметка. Зеркала проверяют по выборке путей, а не целиком: качать оба хоста полностью только ради проверки гипотезы — дорого. Берут несколько десятков общих путей, считают долю near-duplicate; при превышении порога склеивают хосты и далее обходят преимущественно главное зеркало, экономя бюджет обхода (политика вежливости и бюджет — Модуль 2).
Выбор главного зеркала

Когда зеркала обнаружены, выбирают представителя (главное зеркало). Критерии, обычно по убыванию веса:
  1. Явная декларация сайта: куда ведут постоянные редиректы; что указано в rel=canonical; что в картах сайта.
  2. Безопасность и современность: https предпочтительнее http.
  3. Накопленный авторитет: на какой хост больше входящих ссылок, какая версия исторически известна (ссылочные сигналы — Модуль 7).
  4. Стабильность и доступность: какой хост надёжнее отвечает.
  5. Канонические соглашения: консистентность с тем, как сайт сам себя адресует (www или без).
После выбора все пути неглавных зеркал отображаются на главное, а сигналы сливаются на представителя.

Код: Выделить всё

www.site/article   ┐
site/article        ┼─► главное зеркало: https://site/article ◄─ сюда сходятся
http://site/article ┘                                              ссылки, клики, история
SEO-врезка. Не давайте поисковой системе угадывать главное зеркало — объявите его сами и согласованно. Практика: выберите один канонический хост (например, https://site без www), поставьте постоянный редирект 301 со всех остальных вариантов (http, www, лишние домены) на него, продублируйте выбор в rel=canonical, картах сайта и внутренних ссылках. Тогда весь ссылочный вес и история склеятся на одном носителе. Если же www и без-www версии независимо набирают ссылки и не склеены, авторитет домена расщепляется надвое — это прямой пример «размывания сигналов по дублям».
Внимание. Ошибочная склейка двух разных сайтов как зеркал (например, шаблонные сайты на одной CMS с почти идентичной обвязкой, но разным основным контентом) — серьёзная авария: контент одного исчезает из выдачи под представителем другого. Поэтому решающий сигнал — совпадение основного содержимого, а не общего каркаса (меню, футер, шаблон). Это мостик к главе 3.3: сравнивать надо значимый текст, отфильтровав бойлерплейт.
Частые заблуждения
Заблуждение. «www.site и site — это очевидно один сайт, система разберётся сама.» Для машины это два разных хоста. Без редиректа или явных сигналов они могут жить как два носителя сигналов, деля между собой ссылки и историю.
Заблуждение. «Чем больше зеркал/доменов с моим контентом, тем шире охват.» Наоборот: несклеенные копии конкурируют друг с другом и дробят сигналы; склеенные — отдают весь вес одному представителю, а лишние просто не показываются.
Лаба / практика

Детектор зеркал по выборке. Даны два хоста A и B и список из 20 общих путей с телами ответов (часть страниц совпадает, часть различается, на части — только общий шаблон).

Шаги:
  1. Для каждого общего пути посчитайте меру схожести тел (используйте Jaccard по шинглам из главы 3.3 — можно опереться на её лабу).
  2. Отфильтруйте бойлерплейт: удалите часто повторяющиеся между страницами блоки (меню/футер) перед сравнением.
  3. Посчитайте долю путей с схожестью выше порога; примите решение «зеркала / не зеркала».
  4. Если зеркала — выберите главное по правилам (есть редиректы? https? больше входящих ссылок — даны в условии).
  5. Покажите, как фильтрация бойлерплейта изменила решение по сравнению с наивным сравнением целых страниц.
Время ~35 мин. Критерий «сделано»: решение о зеркалах обосновано долей совпадений по значимому контенту; выбран представитель; продемонстрировано влияние фильтра шаблона.

Контрольные вопросы
  1. Чем зеркало отличается от near-duplicate отдельной страницы?
  2. Почему зеркала выгоднее склеивать на уровне хоста, а не каждой страницы?
  3. Какие сигналы говорят, что два хоста — зеркала? Какой из них самый надёжный?
  4. По каким критериям выбирают главное зеркало и почему https обычно предпочтительнее?
  5. Почему при сравнении хостов важно отфильтровать бойлерплейт?
  6. Что произойдёт с авторитетом домена, если www- и без-www-версии не склеены?
  7. Чем опасна ошибочная склейка двух разных сайтов как зеркал?
Глава 3.3. Near-duplicate detection: шинглы, MinHash, SimHash, кластеризация (продвинутый)

Цели обучения

После главы студент сможет:
  • Сформулировать near-duplicate как задачу оценки схожести множеств/документов и выбрать меру (Jaccard, косинус, расстояние Хэмминга).
  • Объяснить и реализовать шинглинг документа в множество k-грамм.
  • Вывести, почему MinHash даёт несмещённую оценку Jaccard, и оценить число хешей для нужной точности.
  • Объяснить SimHash как локально-чувствительный хеш и сравнить его с MinHash по применимости.
  • Реализовать кластеризацию почти-дублей через LSH (бандлы MinHash или близость SimHash) и выбрать представителя кластера.
Конспект

Near-duplicate — документы, почти, но не точно совпадающие по содержимому: новость, перепечатанная на сотне сайтов; товар с одинаковым описанием на разных страницах; версия «для печати»; страница, отличающаяся лишь датой и счётчиком. Точные дубли ловятся хешем всего тела (md5/sha). Сложность — именно «почти»: нужно мерить степень схожести и порогом решать, дубли ли это.
Интуиция. Две статьи — это два мешка слов/фраз. Если мешки пересекаются на 95%, это одна и та же статья с косметическими правками. Нам нужен дешёвый способ оценить «процент пересечения мешков», не сравнивая их попарно целиком — иначе на миллиардах документов это N² сравнений, невычислимо.
Шаг 1. Шинглинг (k-граммы)

Представим документ как множество шинглов (shingles) — пересекающихся последовательностей из k подряд идущих токенов (слов). Для k=3 и текста «быстрая бурая лиса прыгнула» шинглы: {«быстрая бурая лиса», «бурая лиса прыгнула»}.

Шинглы из нескольких слов устойчивее к перестановкам и точнее, чем мешок отдельных слов: совпадение длинных фраз — сильный признак копии. Перед шинглингом текст нормализуют (нижний регистр, удаление пунктуации) и отрезают бойлерплейт (меню, футер, реклама), иначе шаблон сайта раздует мнимое сходство.
Инженерная заметка. Чтобы не хранить длинные строки, каждый шингл хешируют в 64-битное число. Документ становится множеством 64-битных хешей. Выбор k: маленькое k (1–2) ловит даже слабо похожие тексты (много ложных склеек); большое k (5+) требует длинных дословных совпадений (пропускает перефразированные копии). На практике k≈3–5.
Мера схожести: Jaccard

Схожесть двух множеств шинглов A и B:

Код: Выделить всё

J(A, B) = |A ∩ B| / |A ∪ B|
J=1 — идентичны, J=0 — не пересекаются. Порог near-duplicate обычно высокий (например, J ≥ 0.8). Прямой расчёт J для всех пар документов невозможен (N² и большие множества). Решение — MinHash.

Шаг 2. MinHash — оценка Jaccard за дёшево

Идея: возьмём случайную хеш-функцию h, применим её ко всем элементам множества A и запомним минимум: minh(A) = min_{a∈A} h(a). Ключевая теорема:

Код: Выделить всё

P[ minh(A) = minh(B) ] = J(A, B)
Интуиция вывода. Минимум хеша достигается на каком-то одном элементе объединения A ∪ B. Хеш «перемешивает» элементы случайно, так что любой элемент объединения равновероятно может оказаться минимальным. Этот элемент-минимум лежит и в A, и в B одновременно тогда и только тогда, когда он принадлежит пересечению A ∩ B. Вероятность этого = |A∩B| / |A∪B| = J. То есть «совпали ли минимумы» — это бросок монеты с вероятностью успеха ровно J.
Одно совпадение — шумная оценка (0 или 1). Берём m независимых хеш-функций, получаем сигнатуру из m минимумов. Доля совпавших позиций сигнатур — несмещённая оценка J:

Код: Выделить всё

Ĵ = (число совпавших позиций) / m
Стандартная ошибка ≈ √(J(1−J)/m) — точность растёт как 1/√m. Для ошибки порядка 0.01 нужно несколько сотен хешей. Так мы сжали документ любого размера до фиксированной сигнатуры из m чисел.
Пример. Документ A → множество хешей шинглов. m=4 функции дают сигнатуру A=[12, 5, 71, 9], B=[12, 5, 71, 40]. Совпали 3 из 4 → Ĵ≈0.75. Истинный Jaccard оценивается в 0.75 без перебора пересечений множеств.
MinHash + LSH: кластеризация без N²

Сигнатуры есть, но сравнивать их попарно — снова N². Спасает Locality-Sensitive Hashing (LSH). Разбиваем сигнатуру из m минимумов на b бандов (bands) по r строк (m = b·r). Для каждого банда хешируем его r чисел в корзину. Кандидаты в дубли — документы, попавшие хотя бы в одну общую корзину хотя бы в одном банде.
Интуиция. Если два документа очень похожи, у них совпадает много минимумов, и шанс, что целый банд совпадёт целиком, велик. Чем больше бандов — тем больше шансов «зацепиться». Параметры b и r задают S-образную кривую вероятности стать кандидатом от J: порог перегиба ≈ (1/b)^(1/r). Подбирая b, r, настраивают, при каком J пара почти наверняка попадёт в кандидаты.
Кандидатов (их немного) уже проверяют точнее и строят граф «дубль–дубль», затем выделяют связные компоненты или кластеризуют — это и есть кластеры near-duplicate.

Альтернатива: SimHash

SimHash — другой локально-чувствительный хеш, дающий документу одну битовую строку (например, 64 бита) так, что у похожих документов хеши различаются в малом числе бит (расстояние Хэмминга мало).

Алгоритм:
  1. Из документа извлекаем взвешенные признаки (шинглы/слова с весами, например по частоте).
  2. Каждый признак хешируем в 64-битный вектор.
  3. Заводим аккумулятор из 64 счётчиков. Для каждого признака: где бит хеша = 1, прибавляем вес; где 0 — вычитаем.
  4. Итог: бит результата = 1, если счётчик положительный, иначе 0.
Похожие документы → близкие SimHash → малое расстояние Хэмминга. Порог: например, «дубли, если различаются ≤ 3 бита из 64».
Сравнение MinHash vs SimHash.
| | MinHash | SimHash |
|---|---|---|
| Хранит | сигнатуру из m чисел | одно слово (напр. 64 бита) |
| Мера | Jaccard множеств | косинус/Хэмминг по взвешенным признакам |
| Память | больше | очень компактно |
| Точность оценки J | настраиваемая m | грубее, но дёшево |
| Поиск кандидатов | LSH-банды | поиск по малому Хэммингу (разбиение на блоки бит) |
MinHash удобен, когда нужна точная оценка Jaccard и гибкий порог; SimHash — когда документов очень много и важна компактность (одно 64-битное число на документ) и быстрый поиск «почти таких же».
Выбор представителя кластера

В кластере near-duplicate в выдачу попадёт один представитель (остальные схлопнутся — Модуль 15). Критерии выбора первоисточника/представителя:
  • Первичность во времени: кто опубликовал раньше (свежесть, Модуль 17).
  • Авторитет носителя: хост/владелец с большим авторитетом (Модули 7, 3.4).
  • Полнота и качество: более полная версия, без «для печати»-усечений.
  • Поведенческие сигналы: на какую копию лучше реагируют пользователи (Модуль 11).
Внимание. Near-duplicate detection — это группировка для выбора представителя, а не удаление. Прочие копии остаются известны системе (например, как кандидаты в других интентах), но в основную выдачу по запросу попадает один представитель, чтобы не засорять топ повторами.
Частые заблуждения
Заблуждение. «Хватит хеша всего тела — одинаковый хеш = дубль.** Это ловит только точные дубли. Изменение одного байта (дата, счётчик, порядок блоков) даёт совсем другой хеш, но документ — тот же. Нужны меры почти-схожести (Jaccard/Хэмминг), а не точное равенство.
Заблуждение. «MinHash и LSH дают точный ответ.» Они дают вероятностную оценку и кандидатов. Возможны ложные совпадения (разные документы в одной корзине) и пропуски (похожие не зацепились) — баланс настраивается параметрами m, b, r и финальной проверкой кандидатов.
Заблуждение. «Сравнивать надо всю страницу целиком.» Общий шаблон сайта (меню, футер) раздувает сходство и склеивает разные документы. Перед шинглингом отделяют значимый контент от бойлерплейта.
Лаба / практика

SimHash-дедупликатор мини-корпуса. Дан корпус из ~12 коротких текстов: несколько точных дублей, несколько near-duplicate (правки/перестановки абзацев), несколько независимых.

Шаги:
  1. Нормализуйте текст, постройте шинглы k=3, взвесьте их частотой.
  2. Реализуйте 64-битный SimHash по алгоритму выше.
  3. Посчитайте попарные расстояния Хэмминга; постройте граф рёбер «≤3 бита».
  4. Выделите связные компоненты — это кластеры дублей.
  5. Для каждого кластера выберите представителя (по заданному в условии «времени публикации» и «авторитету»).
  6. Доп. Повторите оценку схожести через MinHash (m=100) и сравните, какие пары посчитались дублями обоими методами, а какие разошлись.
Псевдокод SimHash:

Код: Выделить всё

def simhash(features):           # features: list[(token, weight)]
    acc = [0]*64
    for tok, w in features:
        h = hash64(tok)
        for i in range(64):
            acc[i] += w if (h >> i) & 1 else -w
    return sum((1 << i) for i in range(64) if acc[i] > 0)

def hamming(a, b):
    return bin(a ^ b).count("1")
Время ~50 мин. Критерий «сделано»: точные и near-duplicate попали в кластеры, независимые — нет; выбран представитель; объяснён хотя бы один случай расхождения MinHash и SimHash и роль порога.

Контрольные вопросы
  1. Чем near-duplicate отличается от точного дубля и почему хеша тела недостаточно?
  2. Что такое шингл и как параметр k влияет на чувствительность к перефразированию?
  3. Сформулируйте и интуитивно обоснуйте равенство P[minh(A)=minh(B)] = J(A,B).
  4. Как число хешей m в MinHash связано с точностью оценки Jaccard?
  5. Зачем нужен LSH и как параметры b, r задают порог попадания в кандидаты?
  6. Чем SimHash отличается от MinHash по тому, что хранится и как ищутся кандидаты?
  7. Почему near-duplicate detection — это группировка с выбором представителя, а не удаление копий?
  8. По каким критериям выбирают представителя кластера дублей?
Глава 3.4. Группировка по владельцу (owner) — «нулевой фактор», от которого зависят все сигналы (средний)

Цели обучения

После главы студент сможет:
  • Дать определение владельца (owner) и отличить его от хоста и URL.
  • Объяснить, почему владелец — «нулевой фактор», подпирающий ссылочные, поведенческие и репутационные сигналы.
  • Перечислить сигналы для группировки хостов/доменов по владельцу.
  • Оценить последствия ошибок группировки (и склейки, и разведения) для ранжирования и антиспама.
Конспект

Иерархия идентичности в конвейере: URL ⊂ документ (после каноникализации) ⊂ хост ⊂ владелец (owner). Владелец — сущность (организация, лицо, проект), которой принадлежит группа хостов/доменов. Каноникализатор поднимает идентичность до этого верхнего уровня, потому что многие сигналы естественно живут именно на нём.
Интуиция. Документ — это квартира, хост — дом, владелец — управляющая компания, которой принадлежат несколько домов. Репутация управляющей компании переносится на все её дома: если одна УК известна махинациями, доверие к её новостройкам падает заранее. Так же поисковая система: накопив репутацию владельца, она применяет её ко всем его хостам.
Почему владелец — «нулевой фактор»

Назовём это нулевым фактором, потому что он сам по себе не скорит документ, но определяет, к какой сущности относить все остальные сигналы. Без правильной группировки:
  • Ссылочный авторитет (Модуль 7) размазывается. Сайт владельца с десятью доменами, ссылающимися друг на друга, без группировки выглядит как «десять независимых сайтов, голосующих друг за друга» — искусственно раздутый авторитет. С группировкой внутренние ссылки владельца обесцениваются (это самореклама), а внешние считаются честно.
  • Поведенческие сигналы (Модуль 11) и репутация привязываются к хосту/владельцу. Если владелец дробит контент по доменам, история кликов и доверие не накапливаются ни на одном.
  • Антиспам и пессимизация (Модуль 16) работают на уровне владельца: спамные сети из сотен доменов одного субъекта нужно видеть как единую сущность, иначе пессимизация одного домена бессмысленна — субъект поднимет новый.
  • Схлопывание выдачи (Модуль 15) — нельзя занять весь топ десятком доменов одного владельца; ограничение применяется на уровне владельца, а не отдельного хоста.
Это центральный тезис всего модуля. Каноникализация и группировка определяют носителя факторов. Сначала near-duplicate и зеркала сводят копии к одному документу/хосту, затем группировка сводит хосты к владельцу. Только после этого ссылки, клики, свежесть и репутация «приземляются» на устойчивую сущность. Ошибка на любом уровне → сигналы размазываются по дублям/доменам, и сильная сущность выглядит как набор слабых.
Сигналы группировки по владельцу
  • Регистрационные данные домена (общий регистрант/контакты, насколько доступны).
  • Сетевые признаки: общий хостинг/IP-диапазон, общие сертификаты (слабые сами по себе — целые хостинги делят IP).
  • Перелинковка и общая инфраструктура: систематические взаимные ссылки, общие счётчики/идентификаторы, шаблоны, единый раздел «о компании»/контакты.
  • Контентные связи: перекрёстные канонические ссылки, единый бренд в разметке.
  • Совпадение зеркал и редиректов (из глав 3.1–3.2): хосты, связанные редиректами, почти наверняка один владелец.
Каждый сигнал по отдельности слаб; владельца устанавливают по совокупности с порогом уверенности.

Код: Выделить всё

URL ──нормализация(3.1)──► документ
документ + зеркала(3.2) ──► хост (главное зеркало)
хост + near-dup(3.3) ───► канонический документ-представитель
хост ──группировка(3.4)─► ВЛАДЕЛЕЦ ◄── носитель: ссылки, клики, репутация, антиспам
SEO-врезка. Группировка по владельцу — причина, по которой «сетки сайтов» для накрутки ссылок не работают и опасны: система видит их как одного владельца, внутренние ссылки обесцениваются, а при срабатывании антиспама пессимизация бьёт по всей сети сразу. И наоборот: если вы дробите свой проект по множеству доменов без склейки, вы дробите и собственные сигналы — авторитет, история и поведенческие данные не накапливаются ни на одном носителе. Консолидируйте: один основной носитель, явные редиректы, согласованные каноникал-ссылки.
Внимание. Ошибка группировки опасна в обе стороны. Ложное объединение независимых сайтов на общем хостинге → невинный сайт наследует пессимизацию соседа. Ложное разведение одной спам-сети на «независимые» домены → антиспам неэффективен. Поэтому решающие сигналы — поведенческие и структурные (систематическая перелинковка, общая инфраструктура управления), а не только общий IP.
Частые заблуждения
Заблуждение. «Владелец, хост и URL — про одно и то же.» Это вложенные уровни идентичности. Сигналы живут на разных уровнях: текстовая релевантность — на документе, авторитет и репутация — на хосте/владельце. Путать уровни — значит привязывать фактор не к тому носителю.
Заблуждение. «Заведу сто доменов и буду ссылаться сам на себя — авторитет вырастет.» Группировка по владельцу обесценивает внутренние ссылки сети и делает её мишенью для антиспама как единое целое.
Заблуждение. «Общий IP/хостинг = один владелец.» Нет: дешёвый шаринг-хостинг держит тысячи независимых сайтов на одном IP. Это лишь слабый вспомогательный сигнал.
Лаба / практика

Группировка хостов по владельцу и эффект на сигналы. Дан мини-граф из 12 хостов: рёбра-ссылки, признаки (общий IP — да/нет, взаимные редиректы, общий идентификатор счётчика), плюс «истинная» разметка владельцев для проверки.

Шаги:
  1. Постройте оценку «один владелец» для пар хостов как взвешенную сумму сигналов (редирект — сильный, систематическая взаимная перелинковка — средний, общий IP — слабый).
  2. Кластеризуйте хосты в владельцев по порогу (связные компоненты по «сильным» рёбрам).
  3. Посчитайте суммарный ссылочный «вес» (упрощённо — число входящих ссылок) до и после обесценивания внутривладельческих ссылок.
  4. Покажите на конкретном кластере, как «сетка самоссылок» теряет искусственный авторитет после группировки.
  5. Найдите один случай, где наивная склейка по общему IP дала бы ложное объединение, и объясните, какой сигнал это предотвращает.
Время ~40 мин. Критерий «сделано»: кластеры владельцев близки к эталону; численно показано падение искусственного авторитета сетки после группировки; найден и объяснён риск ложной склейки по IP.

Контрольные вопросы
  1. Дайте определение владельца и расположите по вложенности: URL, хост, документ, владелец.
  2. Почему владельца называют «нулевым фактором»? Что значит «носитель сигналов»?
  3. Как ошибка группировки влияет на ссылочный авторитет и поведенческие сигналы?
  4. Почему «сетки сайтов» для накрутки не дают преимущества и чем опасны?
  5. Какие сигналы используют для группировки и почему общий IP — слабый?
  6. Опишите последствия ложного объединения и ложного разведения хостов.
  7. Как уровни идентичности (3.1→3.2→3.3→3.4) связаны в единый конвейер каноникализации?
Итоги модуля
  1. URL ≠ документ. Один материал живёт под множеством адресов; нормализация URL приводит эквивалентные адреса к единой канонической форме и даёт стабильный ключ дедупликации.
  2. Безопасные правила нормализации не меняют смысл по стандарту URI; эвристические (резка параметров, слэш) применяют только с подтверждающими сигналами — редиректами, идентичностью тела, rel=canonical.
  3. rel=canonical — подсказка, а не приказ; при конфликте решает совокупность сигналов (редиректы, контент, перелинковка, карта сайта).
  4. Зеркала склеивают на уровне хоста по совпадению значимого (не шаблонного) содержимого; главное зеркало выбирают по декларациям сайта, https, авторитету и стабильности.
  5. Near-duplicate меряют схожестью множеств/векторов: шинглинг → MinHash (несмещённая оценка Jaccard, P[совпадения минимумов]=J) или SimHash (компактный хеш, близость по Хэммингу) → LSH/связные компоненты → выбор представителя.
  6. MinHash vs SimHash: первый — точная настраиваемая оценка Jaccard через сигнатуры и банды; второй — компактное 64-битное представление и быстрый поиск «почти таких же».
  7. Группировка по владельцу — «нулевой фактор»: определяет носителя ссылочных, поведенческих, репутационных и антиспам-сигналов.
  8. Главный тезис: каноникализация определяет НОСИТЕЛЯ всех факторов. Без неё owner, хост, ссылки и поведение размазываются по дублям, и сильная сущность выглядит как набор слабых.
Глоссарий модуля

Код: Выделить всё

Термин                  |  Англ.                       |  Определение
------------------------+------------------------------+----------------------------------------------------------------------------
Каноническая форма URL  |  canonical URL form          |  Единая представительная строка-адрес для множества эквивалентных URL
Нормализация URL        |  URL normalization           |  Приведение URL к канонической форме по безопасным и эвристическим правилам
Канонический ключ       |  canonical key               |  Стабильный идентификатор документа во всём конвейере после каноникализации
Безопасное правило      |  safe rule                   |  Преобразование URL, не меняющее ресурс по стандарту URI
rel=canonical           |  rel canonical               |  HTML-подсказка о предпочтительном URL; сигнал, а не приказ
Трекинговый параметр    |  tracking parameter          |  Метка в query (UTM, sessionid), не влияющая на контент
Главное зеркало         |  preferred mirror            |  Хост-представитель группы зеркал, на который сливаются сигналы
Бойлерплейт             |  boilerplate                 |  Повторяющийся шаблонный контент (меню, футер), исключаемый из сравнения
Шингл                   |  shingle                     |  Пересекающаяся k-грамма токенов документа
Jaccard                 |  Jaccard                     |  Мера схожести множеств: пересечение / объединение
MinHash                 |  MinHash                     |  Сигнатура из минимумов хешей; оценивает Jaccard несмещённо
LSH                     |  locality-sensitive hashing  |  Хеширование, сводящее похожие объекты в общие корзины (банды)
SimHash                 |  SimHash                     |  Локально-чувствительный битовый хеш; близость по расстоянию Хэмминга
Расстояние Хэмминга     |  Hamming distance            |  Число различающихся бит между двумя битовыми строками
Представитель кластера  |  cluster representative      |  Документ-дубль, попадающий в выдачу от имени всего кластера
Связи с другими модулями
  • Опирается на Модуль 2 (Краулинг): редиректы, бюджет обхода и политика вежливости — входные сигналы каноникализатора; склейка зеркал экономит бюджет обхода.
  • Питает Модуль 4 (Индексирование): индексируется канонический документ-представитель, а не каждый дубль; ключ дедупликации — основа документного идентификатора.
  • Подпирает Модуль 7 (Ссылочный граф): владелец и склейка определяют, как считать и обесценивать ссылки; зеркала сливают ссылочный вес.
  • Подпирает Модули 11, 16: хост/владелец как носитель поведенческих сигналов, репутации и антиспам-пессимизации.
  • Связан с Модулем 15 (Группировка, схлопывание): схлопывание выдачи на уровне хоста/владельца — потребитель результатов каноникализации; near-duplicate-кластеры схлопываются в один результат.
  • Связан с Модулем 17 (Свежесть): выбор первоисточника в кластере дублей опирается на время публикации.
Материалы для углубления
  • Классические работы по обнаружению почти-дублей в вебе (шинглинг и оценка ресемблирования множеств).
  • Обзоры по MinHash и locality-sensitive hashing; разделы о similarity search в учебниках по обработке больших данных (mining of massive datasets).
  • Описание SimHash и поиска по малому расстоянию Хэмминга в больших коллекциях.
  • Стандарты и руководства по синтаксису URI и нормализации URL (общая теория, без привязки к продуктам).
  • Обзоры по выявлению зеркал хостов и кластеризации связных компонентов в графах схожести.
  • Материалы по идентификации владельцев/сетей сайтов в контексте веб-спама (обобщённо, по антиспам-литературе).
👍2 ❤️ 🔥2 😄 🤔
✔ Лучший ответ сформирован автоматически — crossroad
у нас near-duplicate ловили через simhash по шинглам, и главная засада была в выборе порога хэмминга. слишком строго - проходят перепечатки с мелкими правками, слишком мягко - склеиваются разные товары у которых отличается только пара строк в описании. пришлось подбирать на размеченной выборке
Перейти к ответу →
Аватара пользователя
love345
Сообщения: 1
Зарегистрирован: 16 май 2026, 02:13

Re: Идентичность документа: каноникализация и дубли

Сообщение love345 »

по канонизации url вопрос про порядок query-параметров. вы сортируете их перед сравнением или a=1&b=2 и b=2&a=1 считаете разными url? и что делаете с параметрами которые реально меняют контент, типа page, чтобы не схлопнуть нужные страницы в один канон
👍1 ❤️ 🔥 😄 🤔
Аватара пользователя
crossroad
Сообщения: 1
Зарегистрирован: 14 май 2026, 00:08

Re: Идентичность документа: каноникализация и дубли

Сообщение crossroad »

✔ Лучший ответ — сформирован автоматически
у нас near-duplicate ловили через simhash по шинглам, и главная засада была в выборе порога хэмминга. слишком строго - проходят перепечатки с мелкими правками, слишком мягко - склеиваются разные товары у которых отличается только пара строк в описании. пришлось подбирать на размеченной выборке
👍 ❤️ 🔥1 😄 🤔
Аватара пользователя
dev_dimon
Сообщения: 1
Зарегистрирован: 13 май 2026, 21:13

Re: Идентичность документа: каноникализация и дубли

Сообщение dev_dimon »

не совсем согласен что rel=canonical можно доверять как источнику правды. на проде половина сайтов проставляет его криво, указывая на пагинацию или вообще на главную. мы его берем только как сигнал в общем голосовании с редиректами и similarity, а не как жесткое правило
👍1 ❤️3 🔥 😄 🤔
Ответить
← Предыдущая глава
Краулинг (обход)
Следующая глава →
Индексирование и хранение

Все главы курса «Поисковые системы: индексирование, факторы ранжирования и формирование выдачи»

Поделиться темой: ✈ Telegram VK

Вернуться в «Поисковые системы: индекс, факторы, выдача»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 0 гостей