Pull to refresh

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

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

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

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

public string CheckWord(string word, out string lang, out bool Changes)
{
  lang = "?";
  string newword = word;
  string OnlyRu = "БбвГгДдЁёЖжЗзИиЙйЛлмнПптУФфЦцЧчШшЩщЪъЫыЬьЭэЮюЯя";<br>
  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.
Tags:
Hubs:
+31
Comments 32
Comments Comments 32

Articles