Сайт Романа ПарпалакаБлог20230204

Cистема рекомендаций на сайте

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

Пример 1 — антикоррупционный митинг:

Пример 2 — где учиться, на физтехе или физфаке:

Пример 3 — сворачивание кешбека в Бинбанке:

Систему рекомендаций в таком виде сделал Илья Бирман в Эгее — своем движке блогов. В его случае рекомендации к постам формируются на основе тегов. Тогда у меня появилась идея, как можно подбирать рекомендации на основе анализа текстов, без необходимости расставлять теги. Но одно дело — идея, и совсем другое — работающий продукт.

Подбор рекомендаций

Чтобы воплотить идею в жизнь, мне пришлось сделать много подготовительной работы.

Я подключил к моему движку сайтов S2 поисковый движок Rose. Вообще-то Rose сам по себе — это выделенный из S2 и доработанный поисковый алгоритм. Раньше он назывался просто Search (соответственно, пакет в репозитории композера — s2/search). Но Илья убедил меня, что библиотеке для поиска, как и любому продукту, нужно нормальное имя, и даже предложил несколько вариантов. Название «Ropsen», содержащее первые буквы из Roman Parpalak Search Engine, как-то не прижилось. Когда часть букв выкинули, и осталось Rose, я согласился.

Вместе с именем в Розе многое поменялось внутри. Я привел в порядок код, чтобы он следовал правилам хорошего тона для библиотек на PHP: с интерфейсами, инверсией зависимостей и прочими вещами, скрытыми за аббревиатурой SOLID. Кроме того, я сделал реализацию хранилища поискового индекса в MySQL (предыдущая реализация была просто в файле).

Поиск в S2 продолжал работать на старой кодовой базе. Мне казалось, что потребуется много времени, чтобы удалить из легаси-кода S2 старый алгоритм поиска и подключить Розу. На практике оказалось, что я сделал это меньше чем за день. Такая скорость вдохновила меня, и я решил замахнуться на рекомендации.

Почему я вообще в заметке о рекомендациях пишу уже четвертый абзац не о рекомендациях, а о поиске? Потому что рекомендации к некоторой заметке на основе ее текста — это, грубо говоря, результаты поиска по словам из этой заметки. Мне удалось написать один-единственный SQL-запрос, который возвращает список рекомендуемых заметок напрямую из поискового индекса. В следующий раз я опишу подробнее, как работает такой метод и с каким качеством.

Оформление рекомендаций

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

Мне очень понравилось, как выглядят рекомендации у Ильи, и я решил сделать так же. Кроме того, он в своем докладе об автоматическом дизайне рассказал, каким образом работает автоматическая верстка рекомендаций в Эгее. Он подготовил список хорошо сверстанных вариантов и перевел их в некоторый декларативный конфиг с описанием критериев соответствия для каждого элемента верстки (вроде размера и пропорций картинок, длины заголовка и прочего). Дальше для набора рекомендуемых заметок подбирается наиболее подходящий вариант верстки. Обязательно посмотрите видео по ссылке о том, как это всё придумано и работает.

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

Тем не менее, я сделал свой декларативный язык. Описал несколько очевидных вариантов верстки, например для пяти рекомендаций: одна крупная рекомендация слева и четыре поменьше справа.

Затем стал смотреть, как имеющиеся рекомендации ко всем подряд заметкам раскладываются по этим вариантам верстки. Выбрал критерий успеха: заметки с картинками не должны выводиться без превьюшек картинок. Если этот критерий не выполнялся, значит, для таких рекомендаций не было подходящего варианта верстки. Я смотрел на них и прикидывал, как надо вывести заметки, чтобы использовать все возможные картинки. Причем делал это не в графическом редакторе, а сразу описывал новый вариант на своем декларативном языке, и он применялся к рекомендациям.

В результате таким способом, никуда не подглядывая, я накопипастил 113 вариантов верстки. Ближе к концу я стал понимать, что это какой-то перебор, но отступать было поздно :) Я объясняю такое количество вариантов тем, что у меня в заметках не очень много картинок. Чтобы в рекомендации попадали хоть какие-то картинки, нужно выводить побольше рекомендаций и доставать картинки, скажем, с седьмого или восьмого места.

В процессе мне пришлось изобрести некоторые неочевидные приемы. Например, после определения варианта верстки я сортирую рекомендации по убыванию высоты картинок, а если высота одинакова или картинок вообще нет — по убыванию длины текста. Это нужно, чтобы дыры в верстке появлялись ближе к правому краю, который и так рваный, а не к левому. С дырами получалось забавно: я начал было подбирать длины текста так, чтобы он максимально заполнял дыры. Но рекомендации в некоторых пределах резиновые, а при изменении ширины страницы такие объекты как картинка и текст ведут себя по-разному. Высота картинок уменьшается, а высота текста вместе с количеством строк растет. Пришлось смириться с неплотным заполнением этажа рекомендаций.

Еще одно изобретение — отрицательная максимальная длина текста. Она появилась при попытке собрать из картинки и текста блок примерно одинаковой высоты. Скажем, на какое-то место в верстке идеально подходит картинка с относительной высотой (ratio) 0,6 от ширины. Если картинка меньше, скажем, 0,2 от высоты, то кроме нее нужно вывести короткое описание для заполнения блока.

Чтобы не плодить разные варианты одной и той же верстки с таким отличием, я придумал характеризовать текст не только минимальной и максимальной длиной, но и дополнительным коэффициентом, на который умножается «нехватка» высоты картинки для определения дополнительной длины текста. А если картинка с высотой 1,0 тоже подходит, то у картинки с высотой 0,6 за счет добавки обязательно появится текст.

Сначала я хотел сделать дополнительный параметр для отсчета нехватки высоты от 0,6, а не от 1,0. Но потом понял, что того же можно добиться отрицательной длиной текста.

Ограничения рекомендаций и планы на будущее

У Ильи кроме рекомендаций есть еще и перебивки — оформленные таким же образом ссылки в списках записей. Я не стал их делать. В моем понимании рекомендации решают задачу направить посетителя почитать другие записи. Но в списках и так достаточно записей для чтения. Да и технически подобрать ссылки к нескольким записям на одной странице тяжелее, чем к одной записи. Нужно исключать повторы, чтобы одинаковые блоки не повторялись на этой странице.

Сейчас, если в блоке рекомендаций надо вывести текст, я беру одно-два первых предложения. Я попробую выводить не первые предложения, а те предложения, которые содержат общие слова и которые, по идее, должны полнее отражать суть рекомендации.

4 февраля 2023 года, 01:01     S2 · этот сайт
Поделиться

Зарисовка для объяснения понятия формата Ctrl Запрет висячих заголовков в CSS

Читайте также

SiteX
2007
Как разработать систему рекомендаций
Продолжим разговор о системе рекомендаций в S2. Эта система подбирает к каждой заметке набор других заметок, которые посетитель может почитать дальше.
2023

Офлайн-версия сайта, или PDF и PHP
Недавно я сделал офлайновую версию статей с written.ru. Технически это pdf-файл размером немногим больше мегабайта, который автоматически генерируется на сервере.
2008
vw и %
В css есть специальные единицы длины vw и vh, равные сотой доле ширины и высоты окна. К сожалению, на них не влияют полосы прокрутки.
2017

Комментарии

#1. 4 февраля 2023 года, 09:36. Евгений Степанищев пишет:
Очень круто!

Оставьте свой комментарий


Выделение текста: [i]курсивом[/i] или [b]жирным[/b].
Цитату оформляйте так: [q = имя автора]цитата[/q] или [q]еще цитата[/q].
Других команд или HTML-тегов здесь нет.

Записи