Спам (и антиспам)

индекс
155,87

Определяем «неправильные» слова при борьбе со спамом

При борьбе со спамом на форуме возникла идея автоматически отлавливать слова, внешне похожие на «нормальные», но фактически отличающиеся от шаблонных, имеющихся в базе стоп-слов. Делается это путём замены кириллических символом на латиницу и наоборот. Например, «Пpoдaeм бeтoн» и «Продаем бетон» только внешне выглядят одинаково, а на самом деле они отличаются друг от друга.
Вот я и написал небольшую функцию для уменьшения энтропии Вселенной, которая определяет (если сможет) язык, на котором написано слово, и заменяет его на нормальное. Затем проверяем это слово по списку стоп-слов и принимаем решение, запрещённое оно или нет :)

(Красным цветом помечается кириллица, синим- латиница или цифры)

В подробности кода на C# вдаваться не буду, думаю, что всё будет понятно.
Конструктивным предложениям и замечаниям буду рад :)

public string CheckWord(string word, out string lang, out bool Changes)
{
  lang = "?";
  string newword = word;
  string OnlyRu = "БбвГгДдЁёЖжЗзИиЙйЛлмнПптУФфЦцЧчШшЩщЪъЫыЬьЭэЮюЯя";
  string OnlyEn = "DdFfGghIiJjLlNQqRrSstUVvWwYZz";
  string Rus = "АаВЕеКкМНОоРрСсТуХхЗО1тиа@пь";
  string Eng = "AaBEeKkMHOoPpCcTyXx30imu@anb";

  bool IsRu100percent = false;
  foreach (char c1 in word)
    foreach (char c2 in OnlyRu)
      IsRu100percent = IsRu100percent || (c1 == c2);
  
  if (IsRu100percent)
  {
    lang = "ru";
    
    //Конвертируем все сомнительные символы в русские
    for (int i = 0; i < word.Length; i++)
      if (Eng.IndexOf(word[i]) >= 0)
      {
        //помечаем word[i] как "фальшивый"
      }
    for (int i = 0; i < Rus.Length; i++)
      newword = newword.Replace(Eng[i], Rus[i]);
  }
  else
  {
    bool IsEn100percent = false;
    foreach (char c1 in word)
      foreach (char c2 in OnlyEn)
        IsEn100percent = IsEn100percent || (c1 == c2);
    if (IsEn100percent)
    {
      lang = "en";
      //Конвертируем все сомнительные символы в английские
      for (int i = 0; i < word.Length; i++)
        if (Rus.IndexOf(word[i]) >= 0)
        {
          //помечаем word[i] как "фальшивый"
        }
      
      for (int i = 0; i < Eng.Length; i++)
        newword = newword.Replace(Rus[i], Eng[i]);
      
    }
  }
  //Были ли замены?
  Changes = newword != word;
  newword = newword.ToLower();
  _SelectionColor = lang == "ru" ? Color.Red : lang == "en" ? Color.Blue : Color.Black;
  return newword;
}

* This source code was highlighted with Source Code Highlighter.



Вызов происходит просто:
string lang;
bool changes;
string re = "[\\w\\@]+";
Regex rx = new Regex(re, RegexOptions.IgnoreCase | RegexOptions.Singleline);
Match m = rx.Match("Пpoдaeм бeтoн");
while (m.Success)
{
  string newWord = CheckWord(m.ToString(), out lang, out changes);
  m = m.NextMatch();
}

* This source code was highlighted with Source Code Highlighter.
+31
4 марта 2010, 09:32
25

комментарии (31)

+1
kaasnake #
Оно конечно хорошо, но как это использовать в реальной жизни?
В голову приходит только написание какого-нибудь плагина для аутглюка, который будет делать предварительное преобразование неправильных слов в правильные во входящих письмах до срабатывания фильтра на ключевые слова…
0
vladon #
можно написать PS-скрипт для Exchange, например.
0
Borro #
А еще в фильтр комментов к разным блогам можно!
На php, как я понял, портировать ее просто.
0
bondbig #
для большей применимости в реальной жизни, программу надо бы сделать консольной. И под *nix порт нужен, т.к. большинство релеев крутится под *nix.
+14
samodum #
Для большей применимости — я дал код функции. Хотите, в консоль делайте, хотите — в dll, хотите — переводите в *nix, на питон, на php… Я просто показал идею.
Оконный вид программы с подсветкой слов — исключительно для наглядности работы функции.
+1
bondbig #
Что ж, спасибо за идею.
+2
amosk #
К сожалению, это только один из многих частных случаев.
В_И_А_Г_Р_А
Виа(гра)
ВИ/\ГР/\
Не говоря уже о том, что много спама валит без прямого указания там ключевых слов.

Пока компы не научатся понимать смысл текста (читай: пока не будет создан ИИ), спамеры всегда смогут придумать как обойти подобные фильтры.

Но все равно спасибо, что занимаетесь этой темой. Надо держать спамеров в тонусе :)
+2
_Felix_ #
Вряд ли кто-то серьезно рассчитывает создать абсолютный фильтр. Спасает так называемый «барьер» — небольшие усилия помогают отстеять огромную массу любителей-спамеров. Дальше повышать барьер сложнее и процент отсеянных спамеров увеличивается намного медленнее. Главное — решить, где остановиться.

На примере: фильтровал я как-то комментарии на сайте развлекательной тематики. Простой список стоп-слов позволили заблокировать процентов 90 нарушителей. После того как я перед проверкой стал удалять все символы кроме букв и цифр (тем самым отсекая варианты типа «В_И_А_Г_Р_А» или «Виа(гра)»), стало отсеиваться 98%. Остальные проверки были совсем специфическими и добавлялись на конкретные случаи, под настроение. В принципе, это — вариант, на котором можно остановится, все остальное пока проще изредка вычищать вручную.
+1
Pechkin1007 #
Капитан компилятор сказал что у переменной string OnlyRu в конце не стоит ";"
+2
samodum #
Спасибо, поправил.
+1
Pechkin1007 #
А его друг другой капитан когда присмотрелся сказал что 6 похоже на русскую «б»
+2
samodum #
Можете сами дополнить словарь по своему усмотрению.
Ещё подскажу: «m» похожа на маленькую русскую «т», но это, как и «6»-«б» бросается в глаза.
+1
Dellirium #
Спамеры вконтакте спокойно используют «k» вместо «к», и не стесняются.
0
Pechkin1007 #
k и к как и З и 3 точно так же бросаются. Однакож отмечены в сабже. Зато тот кто будет машинально копировать из поста будет иметь «большую» защиту только не знаю от чего)
+4
samodum #
Добавил «1тиа@», «imu@a» и убрал k/к из 100%-алфавита.
И обновил скриншот
0
Pechkin1007 #
Добавил тему в избранное чтобы был справочник сопоставления букв)
+2
samodum #
Вообще, надо бы расширить функцию на работу с двусимвольными комбинациями.
Например, «bl» = «Ы», "/\" — «Л»
–1
Pechkin1007 #
Сделай просто массив, а не стринг.
+2
DarkSilence #
Хм, а почему бы не забраковывать письма в которых есть более некоторого количества слов, в которых используется вперемешку латинские и русские буквы?
Собственно сам факт того что в слове из 5 букв русского алфавита есть две буквы из латинского уже определяет то что слово — паразит.
0
leshaogonkov #
Помоему наиболее разумное решение. Как минимум внимания таким письмам должно больше уделяться.
+1
tehnolog #
спасибо. я сам хотел написать такой код, но руки не доходили. На моей работе это нужно не для спама, а для проверки написания товара. У нас блондинки умудряются завести в базе 1С товар вперемежку. Например, есть модель CT-404 (буквы англ.), а заводят русскими. А если CN-102, то первую букву напишут русской, а потом, так как в русской раскладке буквы N нет, то переключаются на английскую раскладку и вводят уже второй символ. Бардак в базе был еще тот.
0
bear11 #
Кстати, отсеять практически весь «нигерийский» спам можно всего лишь по одному (или трем) ключевым словам, практически не встречающимися в нормальных текстах — это «kin» или «next of kin» (наследник).
–2
Pechkin1007 #
Нигерийский спам самый нигерийский спам в спаме)
+1
warpc #
Зря вы так на тему спам-фильтров: наивный байсековский фильтр и фильтр на основе метода Фишера (SmapBayes, подключаемый к Outlook как раз на основе Фишера) могут и используют признак смешение букв из разных алфавитов как признак спама, хотя затем можно нормализовывать текст по описанному выше методу и подвергать другим тестам: ключевые слова и словосочетания, регистр слов (к примеру, все буквы в верхнем регистре и таких «кричащих» слов множество), анализ метаинформации: кто отправил письмо, откуда и т.д… Если же сразу нормализовывать текст, то можно потерять множество признаков, по которым мог бы обнаружен спам.

А за наглядный пример нормализации текста спасибо.
–3
AgentSmith #
Спамеры такие спамеры
–1
ibnteo #
Можно еще считать слова с подменой букв как заведомо спамерские.
0
AgentSmith #
Я ещё проще придумал. Если в слове происходит смена кодировки, то это спам!
0
seriyPS #
Кодировки???
Уж не языка-ли?
0
stas_agarkov #
за этот файл похожих символов юникода два года назад я получил 500 руб. от своего друга
narod.ru/disk/18479522000/!likes.xml.html
0
bashor #
Вам спасибо, а парсер лох (: j.mp/likess )
+2
samodum #
Ещё немного изменил строчки:
string Rus = «АаВЕеКкМНОоРрСсТуХхЗО1тиа@пь930»;
string Eng = «AaBEeKkMHOoPpCcTyXx30imu@anbgEo»;

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.