温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

PHP如何实现非法词汇过滤

发布时间:2022-10-11 17:03:07 来源:亿速云 阅读:142 作者:iii 栏目:编程语言

这篇文章主要介绍“PHP如何实现非法词汇过滤”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“PHP如何实现非法词汇过滤”文章能帮助大家解决问题。

算法简介

将关键词构造成一颗树,每个字都是一个节点。

遍历需要过滤的语句,将语句的每个字都去树中查找,看看是否存在。

实现难点

构造一棵树简单,关键点是php中遍历字符串需要自己正确的得到单个字符的长度。
简单遍历字符串的方法如下:

$strLen = mb_strlen($str); for ($i = 0; $i < $strLen; $i++) {     echo mb_substr($str, $i, 1, "utf8"),PHP_EOL; }

该方法是利用mb_*系列函数来正确截取每个字符,处理大量字符串时速度非常慢,我猜测是:mb_substr每截取一个字符,都要计算该字符串之前,有多少个字符。
正确的遍历字符串的方式是按utf8的编码规律来截取字符串,具体请看下文。

算法实现

<?php /**  * 非法关键词检查  */ class SensitiveWords {     protected $tree = null;     protected $callIsNumeric = true;     /**      * 非法词汇列表,一个非法词汇占用一行      */     public function __construct($path = __DIR__ . '/sensitiveWords.txt')     {         $this->tree = new WordNode();         $file = fopen($path, "r");         while (!feof($file)) {             $words = trim(fgets($file));             if ($words == '') {                 continue;             }             //存在纯数字的非法词汇             if (is_numeric($words)) {                 $this->callIsNumeric = false;             }             $this->setTree($words);         }         fclose($file);     }     protected function setTree($words)     {         $array = $this->strToArr($words);         $tree = $this->tree;         $l = count($array) - 1;         foreach ($array as $k => $item) {             $tree = $tree->getChildAlways($item);             if ($l == $k) {                 $tree->end = true;             }         }     }     /**      * 返回包含的非法词汇      * @param string $str      * @return array      */     public function check($str)     {         //先压缩字符串         $str = trim(str_replace([' ', "\n", "\r"], ['', '', ''], $str));         $ret = [];         loop:         $strLen = strlen($str);         if ($strLen === 0) {             return array_unique($ret);         }         //非法词汇中没有纯数字的非法词汇,待检测字符串又是纯数字的,则跳过不再检查         if ($this->callIsNumeric && is_numeric($str)) {             return array_unique($ret);         }         //挨个字符进行判断         $tree = $this->tree;         $words = '';         for ($i = 0; $i < $strLen; $i++) {             //unicode范围 --> ord 范围             //一字节 0-127 --> 0 - 127             //二字节 128-2047 --> 194 - 223             //三字节 2048-65535 --> 224 - 239             //四字节 65536-1114111 --> 240 - 244             //@see http://shouce.jb51.net/gopl-zh/ch4/ch4-05.html             $ord = ord($str[$i]);             if ($ord <= 127) {                 $word = $str[$i];             } elseif ($ord <= 223) {                 $word = $str[$i] . $str[$i + 1];                 $i += 1;             } elseif ($ord <= 239) {                 $word = $str[$i] . $str[$i + 1] . $str[$i + 2];                 $i += 2;             } elseif ($ord <= 244) {                 //四字节                 $word = $str[$i] . $str[$i + 1] . $str[$i + 2] . $str[$i + 3];                 $i += 3;             } else {                 //五字节php都溢出了                 //Parse error: Invalid UTF-8 codepoint escape sequence: Codepoint too large                 continue;             }             //判断当前字符             $tree = $tree->getChild($word);             if (is_null($tree)) {                 //当前字不存在,则截取后再次循环                 $str = substr($str, $i + 1);                 goto loop;             } else {                 $words .= $word;                 if ($tree->end) {                     $ret[] = $words;                 }             }         }         return array_unique($ret);     }     protected function strToArr($str)     {         $array = [];         $strLen = mb_strlen($str);         for ($i = 0; $i < $strLen; $i++) {             $array[] = mb_substr($str, $i, 1, "utf8");         }         return $array;     } } /**  * 单个字符的节点  */ class WordNode {     //是否为非法词汇末级节点     public $end = false;     //子节点     protected $child = [];     /**      * @param string $word      * @return WordNode      */     public function getChildAlways($word)     {         if (!isset($this->child[$word])) {             $this->child[$word] = new self();         }         return $this->child[$word];     }     /**      * @param string $word      * @return WordNode|null      */     public function getChild($word)     {         if ($word === '') {             return null;         }         if (isset($this->child[$word])) {             return $this->child[$word];         }         return null;     } }

关于“PHP如何实现非法词汇过滤”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注亿速云行业资讯频道,小编每天都会为大家更新不同的知识点。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

php
AI