Очередной способ борьбы со спамом
В прошлый раз я описал алгоритм шинглов для борьбы со спамом на сайте. Этот метод позволяет определять похожие тексты. С одной стороны - это отличное средство, с другой - существуют ситуации, при которых он бессилен.
Одной из таких ситуаций может стать пример, который я хочу сейчас рассмотреть. Пользователь пишет сообщение "вася васечкин - лох". Его можно добавить в фильтры, но пользователь может изменить сообщение и написать его так: "в.а.с.я.в.а.с.е.ч.к.и.н.л.о.х" - с точки зрения смысловой нагрузки - это одно и то же сообщение. Пытаться его побороть шинглами бесполезно - определить границы слов программно (без использования словарей) - невозможно. Мы можем оставить только буквы в обоих сообщениях - сработает. А если пользователь напишет "в_а_с_я_в_а_с_е_ч_к_и_н_л_о_х_qwerty"?
Решение достаточно элементарно и лежит на поверхности :)
1. Переводим строку в нижний (или верхний - без разницы) регистр
2. Делаем два варианта строки - оставляем только русские и только латинские буквы
3. Выбираем самую длинную из полученных строк (очевидно, количество мусора в строке должно быть меньше, чем смысловой нагрузки)
4. Берём хэши (md5 и sha1 - чтобы снизить вероятность коллизии) и смотрим в базе комментариев
5. Если нашли - запрещаем отправку комментария, если нет - разрешаем.
Небольшой hint - для хранения хэшей в MySQL лучше использовать поле типа BINARY размером в половину строки с хэшем и использовать функцию UNHEX($string) при вставке.
Этот метод имеет несколько недостатков:
1. При небольшом изменении строки хэши будут другими и комментарий пройдёт. Здесь можно каким-то образом объединить этот метод с алгоритмом шинглов.
2. Если добавлять мусор из букв того же языка, что и смысловая часть комментария хэши опять-таки будут другими.
