一、小谈过滤算法

       敏感词过滤功能在很多地方都会用到,理论上在Web应用中,只要涉及用户输入的地方,都需要进行文本校验,如:XSS校验、SQL注入检验、敏感词过滤等。

       每一种过滤算法会都它的适用的地方。简单的循环遍历也有它的使用场景,如在SQL注入检验,使用List<string>集合,遍历所有敏感词,逐个检测输入的文本中是否含有指定的敏感SQL关键词。

       在我知晓的过滤算法,检验速度越快,它的初始构造成本越大,如:

    循环遍历 < Tried Tree < AC自动机 < ToolGood.Words < ToolGood.TextFilter

      

       防止初始构造过长,一般有两种方案解决:1)单例模式,2)将构造后结构序列化后保存本地,第二次加载时直接读取文件。

二、使用List<string>遍历所有敏感词

 1         public static bool Find(string test)
 2         {
 3             var txts = File.ReadAllLines("sensitiveWords.txt");
 4             foreach (var txt in txts) {
 5                 if (test.Contains(txt)) {
 6                     return true;
 7                 }
 8             }
 9             return false;
10         }

三、使用正则方式查寻敏感词

 1         public static bool Find2(string test)
 2         {
 3             var txts = File.ReadAllLines("sensitiveWords.txt");
 4             StringBuilder stringBuilder = new StringBuilder();
 5             for (int i = 0; i < txts.Length; i++) {
 6                 if (stringBuilder.Length > 0) {
 7                     stringBuilder.Append("|");
 8                 }
 9                 var txt = txts[i].Replace(@"", @"").Replace(@"?", @"?").Replace(@".", @".")
10                       .Replace(@"^", @"^").Replace(@"$", @"$")
11                       .Replace(@"*", @"*").Replace(@"+", @"+")
12                       .Replace(@"[", @"[").Replace(@"]", @"]")
13                       .Replace(@"(", @"(").Replace(@")", @")")
14                       .Replace(@"{", @"{").Replace(@"}", @"}");
15                 stringBuilder.Append(txt);
16             }
17             txts = File.ReadAllLines("sensitiveWords_regex.txt");
18             for (int i = 0; i < txts.Length; i++) {
19                 if (stringBuilder.Length > 0) {
20                     stringBuilder.Append("|");
21                 }
22                 stringBuilder.Append(txts[i]);
23             }
24             return Regex.IsMatch(test, stringBuilder.ToString());
25         }

四、敏感词过滤算法比较

       1)循环遍历过滤算法,代码十分简单,能够满足要求小量敏感词检测。这个方案有一个很大的问题是,随着敏感词数量的增多,敏感词检测的时间会呈线性增长。如果项目中有成千上万个敏感词,使用这种方案就会很耗CPU了。

       2)正则表达式过滤算法,一个非常取巧的方法。熟练掌握正则,能在各种场景玩出花来,变体、重复词、跳词统统不在话下。但综合速度比Tried Tree低很多。

       3)Tried Tree 网上最常见的算法。在敏感词检测方面效率很高。缺点不支持跳词、不支持重复词、不支持变种,想支持变种就得增加敏感词汇。

       4)AC自动机是Tried Tree算法在文本匹配方面的优化算法。敏感词检测比Tried Tree算法更快,缺点继承了Tried Tree,不支持跳词、不支持重复词、不支持变种。

       5)ToolGood.Words是一个算法合集,核心算法是在AC自动机基础上优化。

    其中IllegalWordsSearch类更符合敏感词过滤这种场景,支持全角转半角,忽略大小写,跳词,重复词。

    而WordsMatch类更像是AC自动机向正则表达式方面试探。

后记:

       下次介绍 Tried Tree 及 AC自动机。

ToolGood.Words 为开源项目,地址:https://github.com/toolgood/ToolGood.Words

ToolGood.TextFilter 为商业项目《ToolGood 内容审核系统》的核心算法,是一个综合算法,由敏感词检测、NLP分词排错、多组敏感词检测,Html解析、Json解析等多个算法组成。