背景
在做一些跟内容相关的项目的时候,经常需要对内容文本中的内容进行检测,检测文本中是否包含某个敏感、违法等词汇,例如“贷款”、“发票”之类的。有些狡猾的用户可能知道“贷款”在你的系统中是敏感词,不能审核通过,便使用“贷 款”、“贷$款”、"贷;款"等这种方式故意欺骗你的系统,从而系统无法简单找出这些敏感词。敏感词一般都是中文分词后的单个词,不排除想要不分词处理的敏感词,这种情况可能影响到最终校验结果。
解决方案
方案一:使用List的contains方法检测文本中是否有敏感词,简单粗暴
最容易想到的,将所有敏感词存放在List中,每次需要检测文本中是否有敏感词的时候,for循环list列表,使用contains方法判断文本中是否包含关键词,如果有则返回true,如果循环结束还没有找到的话则不包含敏感词。代码大概如下:
String text="贷款测试";
for(String str: blackList){if(text.contains(str)){return true;}
}
return false;
使用这种方式的优点就是简单,但是每次检测的时候,如果文本中没有敏感词,都需要把每个敏感词循环一遍,如果系统对性能要求比较高,可能速度满足不了性能需求。
方案二:使用开源项目https://github.com/toolgood/ToolGood.Words,目前版本有升级,一些方法可能过时,使用最新得实现方法就可以了。
1、将所有敏感词加载到List
public static List<String> loadKeywords(File file){List<String> keyArray=new ArrayList<String>();try{BufferedReader br = new BufferedReader(new FileReader(file));//构造一个BufferedReader类来读取文件String s = null;while((s = br.readLine())!=null){//使用readLine方法,一次读一行keyArray.add(s);}br.close();}catch(Exception e){e.printStackTrace();}return keyArray;}
示例代码是从txt文本文件中加载黑词,在我们实际项目中可以改为从数据库中读取
2、定义IllegalWordsSearch对象
IllegalWordsSearch iwords = new IllegalWordsSearch();
iwords.SetKeywords(list);
3、使用IllegalWordsSearch敏感词过滤方法,常用的有如下:
(1)ContainsAny 判断文本是否包含关键字
(2)FindFirst 找出文本中第一个关键字
(3)FindAll 在文本中查找所有的关键字
eg:
maven依赖:
<dependency> <groupId>io.github.toolgood</groupId> <artifactId>toolgood-words</artifactId> <version>3.0.3.1</version> </dependency> <dependency><groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.7.15</version> </dependency>
String test = "我有一颗大土豆,刚出锅的夜场.票d女模特"; // 可以对test先格式化,去除标点符号、空格等 List<String> list=new ArrayList<String>(); list.add("夜场女模特"); list.add("发票"); // list.add("模特"); StringSearch iwords = new StringSearch(); iwords.SetKeywords(list); boolean b = iwords.ContainsAny(test); System.out.println("b="+b);
值得一提的是它支持过滤跳词,即如果你的关键词为“贷款”,如果文本是“贷 款”、“贷;款”之类的也是可以识别的。
作者在项目中也给出了速度测试结果,速度也很不错。
另外项目中也包含一些繁体简体互转,汉字转拼音,中文数字互转的功能,值得推荐!!!
解决方案三:使用hutool中的dfa
<dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.4.1</version>
</dependency>
public static void main(String[] args) {WordTree tree = new WordTree();tree.addWord("彩票");tree.addWord("发票");Filter<Character> charFilter = StopChar::isNotStopChar;tree.setCharFilter(charFilter);//正文String text = "我有一颗大土豆,刚出锅的彩.票发票";System.out.println(tree.isMatch(text));List<String> matchAll = tree.matchAll(text, -1, false, false);System.out.println(matchAll);
}