博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java实现敏感词过滤(DFA算法)
阅读量:6179 次
发布时间:2019-06-21

本文共 9541 字,大约阅读时间需要 31 分钟。

小Alan在最近的开发中遇到了敏感词过滤,便去网上查阅了很多敏感词过滤的资料,在这里也和大家分享一下自己的理解。

 

敏感词过滤应该是不用给大家过多的解释吧?讲白了就是你在项目中输入某些字(比如输入xxoo相关的文字时)时要能检

测出来,很多项目中都会有一个敏感词管理模块,在敏感词管理模块中你可以加入敏感词,然后根据加入的敏感词去过滤输

入内容中的敏感词并进行相应的处理,要么提示,要么高亮显示,要么直接替换成其它的文字或者符号代替。 

 

敏感词过滤的做法有很多,我简单描述我现在理解的几种:

①查询数据库当中的敏感词,循环每一个敏感词,然后去输入的文本中从头到尾搜索一遍,看是否存在此敏感词,有则做相

应的处理,这种方式讲白了就是找到一个处理一个。

优点:so easy。用java代码实现基本没什么难度。

缺点:这效率让我心中奔过十万匹草泥马,而且匹配的是不是有些蛋疼,如果是英文时你会发现一个很无语的事情,比如英文

a是敏感词,那我如果是一篇英文文档,那程序它妹的得处理多少次敏感词?谁能告诉我?

②传说中的DFA算法(有穷自动机),也正是我要给大家分享的,毕竟感觉比较通用,算法的原理希望大家能够自己去网上查查

资料,这里就不详细说明了。

优点:至少比上面那sb效率高点。

缺点:对于学过算法的应该不难,对于没学过算法的用起来也不难,就是理解起来有点gg疼,匹配效率也不高,比较耗费内存,

敏感词越多,内存占用的就越大。

③第三种在这里要特别说明一下,那就是你自己去写一个算法吧,或者在现有的算法的基础上去优化,这也是小Alan追求的至

高境界之一,如果哪位淫兄有自己的想法一定别忘了小Alan,可以加小Alan的QQ:810104041教小Alan两招耍耍。

 

那么,传说中的DFA算法是怎么实现的呢?

第一步:敏感词库初始化(将敏感词用DFA算法的原理封装到敏感词库中,敏感词库采用HashMap保存),代码如下:

1 package com.cfwx.rox.web.sysmgr.util;  2   3 import java.util.HashMap;  4 import java.util.HashSet;  5 import java.util.Iterator;  6 import java.util.List;  7 import java.util.Map;  8 import java.util.Set;  9  10 import com.cfwx.rox.web.common.model.entity.SensitiveWord; 11  12 /** 13  * 敏感词库初始化 14  *  15  * @author AlanLee 16  * 17  */ 18 public class SensitiveWordInit 19 { 20     /** 21      * 敏感词库 22      */ 23     public HashMap sensitiveWordMap; 24  25     /** 26      * 初始化敏感词 27      *  28      * @return 29      */ 30     public Map initKeyWord(List
sensitiveWords) 31 { 32 try 33 { 34 // 从敏感词集合对象中取出敏感词并封装到Set集合中 35 Set
keyWordSet = new HashSet
(); 36 for (SensitiveWord s : sensitiveWords) 37 { 38 keyWordSet.add(s.getContent().trim()); 39 } 40 // 将敏感词库加入到HashMap中 41 addSensitiveWordToHashMap(keyWordSet); 42 } 43 catch (Exception e) 44 { 45 e.printStackTrace(); 46 } 47 return sensitiveWordMap; 48 } 49 50 /** 51 * 封装敏感词库 52 * 53 * @param keyWordSet 54 */ 55 @SuppressWarnings("rawtypes") 56 private void addSensitiveWordToHashMap(Set
keyWordSet) 57 { 58 // 初始化HashMap对象并控制容器的大小 59 sensitiveWordMap = new HashMap(keyWordSet.size()); 60 // 敏感词 61 String key = null; 62 // 用来按照相应的格式保存敏感词库数据 63 Map nowMap = null; 64 // 用来辅助构建敏感词库 65 Map
newWorMap = null; 66 // 使用一个迭代器来循环敏感词集合 67 Iterator
iterator = keyWordSet.iterator(); 68 while (iterator.hasNext()) 69 { 70 key = iterator.next(); 71 // 等于敏感词库,HashMap对象在内存中占用的是同一个地址,所以此nowMap对象的变化,sensitiveWordMap对象也会跟着改变 72 nowMap = sensitiveWordMap; 73 for (int i = 0; i < key.length(); i++) 74 { 75 // 截取敏感词当中的字,在敏感词库中字为HashMap对象的Key键值 76 char keyChar = key.charAt(i); 77 78 // 判断这个字是否存在于敏感词库中 79 Object wordMap = nowMap.get(keyChar); 80 if (wordMap != null) 81 { 82 nowMap = (Map) wordMap; 83 } 84 else 85 { 86 newWorMap = new HashMap
(); 87 newWorMap.put("isEnd", "0"); 88 nowMap.put(keyChar, newWorMap); 89 nowMap = newWorMap; 90 } 91 92 // 如果该字是当前敏感词的最后一个字,则标识为结尾字 93 if (i == key.length() - 1) 94 { 95 nowMap.put("isEnd", "1"); 96 } 97 System.out.println("封装敏感词库过程:"+sensitiveWordMap); 98 } 99 System.out.println("查看敏感词库数据:" + sensitiveWordMap);100 }101 }102 }

 

第二步:写一个敏感词过滤工具类,里面可以写上自己需要的方法,代码如下:

1 package com.cfwx.rox.web.sysmgr.util;  2   3 import java.util.HashSet;  4 import java.util.Iterator;  5 import java.util.Map;  6 import java.util.Set;  7   8 /**  9  * 敏感词过滤工具类 10  *  11  * @author AlanLee 12  * 13  */ 14 public class SensitivewordEngine 15 { 16     /** 17      * 敏感词库 18      */ 19     public static Map sensitiveWordMap = null; 20  21     /** 22      * 只过滤最小敏感词 23      */ 24     public static int minMatchTYpe = 1; 25  26     /** 27      * 过滤所有敏感词 28      */ 29     public static int maxMatchType = 2; 30  31     /** 32      * 敏感词库敏感词数量 33      *  34      * @return 35      */ 36     public static int getWordSize() 37     { 38         if (SensitivewordEngine.sensitiveWordMap == null) 39         { 40             return 0; 41         } 42         return SensitivewordEngine.sensitiveWordMap.size(); 43     } 44  45     /** 46      * 是否包含敏感词 47      *  48      * @param txt 49      * @param matchType 50      * @return 51      */ 52     public static boolean isContaintSensitiveWord(String txt, int matchType) 53     { 54         boolean flag = false; 55         for (int i = 0; i < txt.length(); i++) 56         { 57             int matchFlag = checkSensitiveWord(txt, i, matchType); 58             if (matchFlag > 0) 59             { 60                 flag = true; 61             } 62         } 63         return flag; 64     } 65  66     /** 67      * 获取敏感词内容 68      *  69      * @param txt 70      * @param matchType 71      * @return 敏感词内容 72      */ 73     public static Set
getSensitiveWord(String txt, int matchType) 74 { 75 Set
sensitiveWordList = new HashSet
(); 76 77 for (int i = 0; i < txt.length(); i++) 78 { 79 int length = checkSensitiveWord(txt, i, matchType); 80 if (length > 0) 81 { 82 // 将检测出的敏感词保存到集合中 83 sensitiveWordList.add(txt.substring(i, i + length)); 84 i = i + length - 1; 85 } 86 } 87 88 return sensitiveWordList; 89 } 90 91 /** 92 * 替换敏感词 93 * 94 * @param txt 95 * @param matchType 96 * @param replaceChar 97 * @return 98 */ 99 public static String replaceSensitiveWord(String txt, int matchType, String replaceChar)100 {101 String resultTxt = txt;102 Set
set = getSensitiveWord(txt, matchType);103 Iterator
iterator = set.iterator();104 String word = null;105 String replaceString = null;106 while (iterator.hasNext())107 {108 word = iterator.next();109 replaceString = getReplaceChars(replaceChar, word.length());110 resultTxt = resultTxt.replaceAll(word, replaceString);111 }112 113 return resultTxt;114 }115 116 /**117 * 替换敏感词内容118 * 119 * @param replaceChar120 * @param length121 * @return122 */123 private static String getReplaceChars(String replaceChar, int length)124 {125 String resultReplace = replaceChar;126 for (int i = 1; i < length; i++)127 {128 resultReplace += replaceChar;129 }130 131 return resultReplace;132 }133 134 /**135 * 检查敏感词数量136 * 137 * @param txt138 * @param beginIndex139 * @param matchType140 * @return141 */142 public static int checkSensitiveWord(String txt, int beginIndex, int matchType)143 {144 boolean flag = false;145 // 记录敏感词数量146 int matchFlag = 0;147 char word = 0;148 Map nowMap = SensitivewordEngine.sensitiveWordMap;149 for (int i = beginIndex; i < txt.length(); i++)150 {151 word = txt.charAt(i);152 // 判断该字是否存在于敏感词库中153 nowMap = (Map) nowMap.get(word);154 if (nowMap != null)155 {156 matchFlag++;157 // 判断是否是敏感词的结尾字,如果是结尾字则判断是否继续检测158 if ("1".equals(nowMap.get("isEnd")))159 {160 flag = true;161 // 判断过滤类型,如果是小过滤则跳出循环,否则继续循环162 if (SensitivewordEngine.minMatchTYpe == matchType)163 {164 break;165 }166 }167 }168 else169 {170 break;171 }172 }173 if (!flag)174 {175 matchFlag = 0;176 }177 return matchFlag;178 }179 180 }

 

第三步:一切都准备就绪,当然是查询好数据库当中的敏感词,并且开始过滤咯,代码如下:

1  @SuppressWarnings("rawtypes") 2     @Override 3     public Set
sensitiveWordFiltering(String text) 4 { 5 // 初始化敏感词库对象 6 SensitiveWordInit sensitiveWordInit = new SensitiveWordInit(); 7 // 从数据库中获取敏感词对象集合(调用的方法来自Dao层,此方法是service层的实现类) 8 List
sensitiveWords = sensitiveWordDao.getSensitiveWordListAll(); 9 // 构建敏感词库10 Map sensitiveWordMap = sensitiveWordInit.initKeyWord(sensitiveWords);11 // 传入SensitivewordEngine类中的敏感词库12 SensitivewordEngine.sensitiveWordMap = sensitiveWordMap;13 // 得到敏感词有哪些,传入2表示获取所有敏感词14 Set
set = SensitivewordEngine.getSensitiveWord(text, 2);15 return set;16 }

 

最后一步:在Controller层写一个方法给前端请求,前端获取到需要的数据并进行相应的处理,代码如下:

1  /** 2      * 敏感词过滤 3      *  4      * @param text 5      * @return 6      */ 7     @RequestMapping(value = "/word/filter") 8     @ResponseBody 9     public RespVo sensitiveWordFiltering(String text)10     {11         RespVo respVo = new RespVo();12         try13         {14             Set
set = sensitiveWordService.sensitiveWordFiltering(text);15 respVo.setResult(set);16 }17 catch (Exception e)18 {19 throw new RoxException("过滤敏感词出错,请联系维护人员");20 }21 22 return respVo;23 }

 

小Alan在代码中写了不少的注释,希望大家能够动动自己的脑筋好好的理解一下。

 

可爱博主:AlanLee

博客地址:

本文出自博客园,欢迎大家加入博客园。

转载于:https://www.cnblogs.com/AlanLee/p/5329555.html

你可能感兴趣的文章
PHP FPM源代码反刍品味之五:信号signal处理
查看>>
5G网速真的有理论上那么高吗?
查看>>
Set添加自定义方法对象如何保证唯一性
查看>>
站在巨人肩膀上的牛顿:Kubernetes和SAP Kyma
查看>>
技术工坊|浅谈区块链的Layer2扩展(北京)
查看>>
SSM框架——详细整合教程(Spring+SpringMVC+MyBatis)
查看>>
Apache和PHP结合 及 Apache默认虚拟主机
查看>>
添加自定义监控项目配置邮件告警测试告警不发邮件的问题处理
查看>>
solidity智能合约的经典设计模式
查看>>
华为交换网络基础、基本配置、STP/RSTP
查看>>
SpringCloud 微服务 (十七) 容器部署 Docker
查看>>
不定项选择题
查看>>
netty 分析博客
查看>>
Spring Cloud构建微服务架构服务注册与发现
查看>>
BCGControlBar教程:如何将MFC控件的BCGControlBarBCGSuite添加到对话框中
查看>>
深入理解Java8 Lambda表达式
查看>>
Java集合框架面试问题集锦
查看>>
Java每天10道面试题,跟我走,offer有!(六)
查看>>
四种途径提高RabbitMQ传输数据的可靠性(二)
查看>>
c语言实现多态
查看>>