内容正文
PHP实现的敏感词过滤方法,有好的编码和好的实现方法,可以发出来一起互换一下。以下是一份过滤敏感词的编码
一.敏感词过滤方案一
/ @todo 敏感词过滤,返回结果 @param array $list 定义敏感词一维数组 @param string $string 要过滤的内容 @return string $log 处理结果 /function sensitive($list, $string){ $count = 0; //违规词的个数 $sensitiveWord = ''; //违规词 $stringAfter = $string; //更换后的内容 $pattern = \"大众/\公众.implode(\"大众|\公众,$list).\"大众/i\"大众; //定义正则表达式 if(preg_match_all($pattern, $string, $matches)){ //匹配到了却果 $patternList = $matches[0]; //匹配到的数组 $count = count($patternList); $sensitiveWord = implode(',', $patternList); //敏感词数组转字符串 $replaceArray = array_combine($patternList,array_fill(0,count($patternList),'')); //把匹配到的数组进行合并,更换利用 $stringAfter = strtr($string, $replaceArray); //结果更换 } $log = \"大众原句为 [ {$string} ]<br/>\"大众; if($count==0){ $log .= \公众暂未匹配到敏感词!
\公众; }else{ $log .= \"大众匹配到 [ {$count} ]个敏感词:[ {$sensitiveWord} ]<br/>\"大众. \"大众更换后为:[ {$stringAfter} ]\"大众; } return $log;}
调用方法
function testAction(){ $string = 'likeyou小白喜好小黑爱着的大黄'; //要过滤的内容 $list = ['小明', '小红', '大白', '小白', '小黑', 'me', 'you']; //定义敏感词数组 $result = $this->sensitive($list, $string); echo ($result); die; //打印结果: / 原句为 [ likeyou小白喜好小黑爱着的大黄 ] 匹配到 [ 3 ]个敏感词:[ you,小白,小黑 ] 更换后为:[ like喜好爱着的大黄 ] /}
二.敏感词过滤方案二
在网上查了下敏感词过滤方案,找到了一种名为DFA的算法,即Deterministic Finite Automaton算法,翻译成中文便是确定有穷自动机算法。它的基本思想是基于状态转移来检索敏感词,只须要扫描一次待检测文本,就能对所有敏感词进行检测,以是效率比方案一高不少。
假设我们有以下5个敏感词须要检测:傻逼、傻子、傻大个、坏蛋、坏人。那么我们可以先把敏感词中有相同前缀的词组合成一个树形构造,不同前缀的词分属不同树形分支,在Java中,我们可以用HashMap来存储上述的树形构造,还是以上述敏感词为例,我们把每个敏感词字符串拆散成字符,再存储到HashMap中。
三.敏感词过滤方案三
方案二在性能上已经可以知足需求了,但是却很随意马虎被破解,比如说,我在待检测文本中的敏感词中间加个空格,就可以成功绕过了。要办理这个问题也不难,有一个大略的方法是初始化一个无效字符库,比如:空格、、#、@等字符,然后在检测文本前,先将待检测文本中的无效字符去除,这样的话被检测字符就不存在这些无效字符了,因此还是可以连续用方案二进行过滤。只要被检测文本不要太长,那么我们只要在方案二的根本上再多扫描一次被检测文本去除无效字符就行了,这个性能损耗也还是可以接管的。
如果敏感词是英文,则还要考虑大小写的问题。有一个比较大略的办理方案是在初始化敏感词时,将敏感词都以小写形式存储。同时,在检测文本时,也统一将待检测文本转化为小写,这样就能办理大小写的问题了。
比较棘手的是中文跟拼音稠浊的情形,比如“傻逼”这个敏感词,可以通过“sha逼”这种中文跟拼音稠浊的办法轻松绕过,对付这种情形我目前还没想到比较好的办理方案,有想法的读者可以在文末留言。