Как и зачем я создал свой поисковик Pick: история создания и примеры кода
Рассказ о написании собственного поискового движка, который умеет индексировать сжатый HTML, а также позволяет ранжировать выдачу на основе рейтинга.

Поскольку Яндекс не захотел парсить мои сайты сославшись на то, что они не умеют обрабатывать контент в формате deflate мне захотелось разобраться в чем дело и попробовать написать свой поисковый сервис. Вообще служба техподдержки Яндекс оказалась для меня бесполезной, поскольку два дня Платоны доказывали мне, что сайты на Revolver CMF отдают битую кодировку. В то же время это был просто сжатый в deflate HTML. В итоге я решил написать свой индексатор, который умеет индексировать сжатый HTML и не только.
Создавать было решено антибюрократический Open Source поисковик, ранжирующий результаты в выдаче на основе голосов зарегистрированных пользователей без участия модерации.
Название мы с друзьями выбрали созвучно всем известной Picus Networks из мира компьютерной игры DeusEx. Осталось создать два алгоритма Pick для выполнения запросов и Picker для индексации контента.
Как создавался Pick
Можно было реализовать поисковую систему отдельно, но я использовал framework RevolveR, который предоставляет доступ к API работы с базой данных и ее кэширование, обработку POST и GET запросов с защитой, а также fetch API для динамических запросов.
А после интеграции Pick стал частью ядра. Скачать RevolveR CMF можно со страницы проекта GitHub.
Создаем индекс в базе данных
Очевидно, что нам нужен свой поисковый индекс, который будет храниться в базе данных. Для этого сформируем структуру на SBQ (structure based queries), которая хранится в файле /Kernel/Structures/DataBase.php:
Мы создали структуру будущей таблицы revolver_index, которую будут использовать модели для записи и хранения данных. Полям content
, description
и title
назначаем полнотекстовый индекс для ускорения запросов SELECT, а для поля host
укажем тип индекса simple
(это поможет сделать быстрый поиск по всем индексированным ссылкам определённого ресурса).
Также у нас есть поля date
и hash
. Дата хранит последний момент индексации ресурса, а hash
указывает на актуальность данных (если хэш заново полученной страницы не отличается от хранимого в БД значения, то обновление не выполняется).
Поле uri
будет содержать полную ссылку страницы.
Теперь нам понадобится таблица в БД которая будет хранить рейтинги материалов в формате 5 звезд на основе голосов зарегистрированных пользователей (API для рейтингов есть и о том как оно работает чуть ниже).
Создадим еще одну структуру:
Таблица очень простая. Она хранит ID ресурса, ID пользователя и оценку.
Давайте зарегистрируем структуры в схеме базы данных:
Таблицы сформированы и описаны и нам осталось выполнить SBQ через API RevolveR CMF для создания этих таблиц в базе данных:
После выполнения этого кода в базе данных появится таблицы revolver__index и revolver__index_ratings, а мы сможем использовать API моделей для работы с ними.
Регистрируем сервис индексации и страницу поиска
В RevolveR CMF есть такое понятие как сервисы. Они используются для выполнения каких-то задач при обращении к ним с аргументами, но не имеют кэширования и не обрабатываются шаблоном.
Чтобы зарегистрировать сервис индексации просто пропишем параметры в файл /private/config.php:
Здесь все предельно просто. Type service
указывает на то, что URL /picker/ будет служить обработчиком запросов, которые избегают систему кэширования фреймворка и игнорируют формирование шаблона.
Теперь сразу же зарегистрируем путь, который будет отображать страницу выполнения поисковых запросов к базе данных. Для этого в этом же файле добавим строки:
Параметр menu
указывает на то, что мы отображаем пункт в главном меню, а type
равное node
указывает на то, что регистрируемый путь является узлом, который подвергается кэшированию по умолчанию и может быть подключен к шаблону.
Мы зарегистрировали 2 URI и теперь нужно подключить обработчики сервиса и узла. Поскольку было решено сделать Pick компонентом ядра, мы модернизируем файл /Kernel/Modules/Switch.php:
Этими строками мы создали подключение NodePick и RoutePicker, которые будут содержать основные исходные коды алгоритмов поискового движка. Нам достаточно всего 2 файла.
Индексатор URL Picker
Чтобы проиндексировать какой либо сайт мы должны иметь доступ по сети и уметь парсить сайты. Для этого была использована стандартная библиотека cURL для PHP.
Вот исходный код функции, которая открывает URL и достает содержимое страницы:
Работает алгоритм очень просто. При передаче URL происходит открытие web-страницы и обработчик проверяет корректность SSL соединения. Далее мы смотрим что тип документа характеризует ценные для нас данные HTML или Application xHTML, а также проверяем код ответа сервера. Все, что препятствует получению данных приводит к возврату значения null
.
Дополнительно проверяем, что отдаваемый сервером контент может быть сжатым в gzip, deflate или compress.
Теперь нам нужна функция для работы с самим полученным документом. Мы должны извлечь текстовое содержимое без тегов и получит все ссылки на странице: