站長(zhǎng)資訊網(wǎng)
        最全最豐富的資訊網(wǎng)站

        PHP實(shí)現(xiàn)非法詞匯過(guò)濾(算法分析)

        算法簡(jiǎn)介

        將關(guān)鍵詞構(gòu)造成一顆樹(shù),每個(gè)字都是一個(gè)節(jié)點(diǎn)。

        遍歷需要過(guò)濾的語(yǔ)句,將語(yǔ)句的每個(gè)字都去樹(shù)中查找,看看是否存在。

        實(shí)現(xiàn)難點(diǎn)

        構(gòu)造一棵樹(shù)簡(jiǎn)單,關(guān)鍵點(diǎn)是php中遍歷字符串需要自己正確的得到單個(gè)字符的長(zhǎng)度。
        簡(jiǎn)單遍歷字符串的方法如下:

        $strLen = mb_strlen($str); for ($i = 0; $i < $strLen; $i++) {     echo mb_substr($str, $i, 1, "utf8"),PHP_EOL; }
        登錄后復(fù)制

        該方法是利用mb_*系列函數(shù)來(lái)正確截取每個(gè)字符,處理大量字符串時(shí)速度非常慢,我猜測(cè)是:mb_substr每截取一個(gè)字符,都要計(jì)算該字符串之前,有多少個(gè)字符。
        正確的遍歷字符串的方式是按utf8的編碼規(guī)律來(lái)截取字符串,具體請(qǐng)看下文。

        算法實(shí)現(xiàn)

        <?php /**  * 非法關(guān)鍵詞檢查  */ class SensitiveWords {     protected $tree = null;     protected $callIsNumeric = true;     /**      * 非法詞匯列表,一個(gè)非法詞匯占用一行      */     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;             }             //存在純數(shù)字的非法詞匯             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);         }         //非法詞匯中沒(méi)有純數(shù)字的非法詞匯,待檢測(cè)字符串又是純數(shù)字的,則跳過(guò)不再檢查         if ($this->callIsNumeric && is_numeric($str)) {             return array_unique($ret);         }         //挨個(gè)字符進(jìn)行判斷         $tree = $this->tree;         $words = '';         for ($i = 0; $i < $strLen; $i++) {             //unicode范圍 --> ord 范圍             //一字節(jié) 0-127 --> 0 - 127             //二字節(jié) 128-2047 --> 194 - 223             //三字節(jié) 2048-65535 --> 224 - 239             //四字節(jié) 65536-1114111 --> 240 - 244             //@see http://shouce.jb51.net/gopl-zh/ch3/ch3-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) {                 //四字節(jié)                 $word = $str[$i] . $str[$i + 1] . $str[$i + 2] . $str[$i + 3];                 $i += 3;             } else {                 //五字節(jié)php都溢出了                 //Parse error: Invalid UTF-8 codepoint escape sequence: Codepoint too large                 continue;             }             //判斷當(dāng)前字符             $tree = $tree->getChild($word);             if (is_null($tree)) {                 //當(dāng)前字不存在,則截取后再次循環(huán)                 $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;     } } /**  * 單個(gè)字符的節(jié)點(diǎn)  */ class WordNode {     //是否為非法詞匯末級(jí)節(jié)點(diǎn)     public $end = false;     //子節(jié)點(diǎn)     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;     } }
        登錄后復(fù)制

        推薦學(xué)習(xí):《PHP視頻教程》

        php入門(mén)到就業(yè)線上直播課:立即學(xué)習(xí)
        全程直播 + 實(shí)戰(zhàn)授課 + 邊學(xué) + 邊練 + 邊輔導(dǎo)

        贊(0)
        分享到: 更多 (0)
        網(wǎng)站地圖   滬ICP備18035694號(hào)-2    滬公網(wǎng)安備31011702889846號(hào)
        主站蜘蛛池模板: 亚洲国产精品不卡毛片a在线| 欧洲成人午夜精品无码区久久 | 99RE8这里有精品热视频| 亚洲欧美日韩国产精品| 成人精品一区二区三区电影黑人| 欧美久久亚洲精品| 2021久久国自产拍精品| 亚洲精品一级无码中文字幕| 国产精品玖玖美女张开腿让男人桶爽免费看 | 国产精品 综合 第五页| 凹凸69堂国产成人精品视频| 人妻熟妇乱又伦精品视频 | 精品久久一区二区| 亚洲AV永久精品爱情岛论坛| 欧美日韩精品一区二区三区不卡 | 精品不卡一区二区| 亚洲AV成人精品网站在线播放 | 久久精品无码一区二区三区日韩| 在线精品国产一区二区| 国产91精品一区二区麻豆网站| 精品性影院一区二区三区内射| 亚洲国产一二三精品无码| 日韩精品无码人妻一区二区三区| 精品91自产拍在线观看二区| 国产AⅤ精品一区二区三区久久| 91久久精品电影| 国产精品成人久久久久三级午夜电影 | 国产成人精品免高潮在线观看| 国内精品久久国产大陆| 国产精品国产三级国产专播| 第一福利永久视频精品| 精品国产精品国产偷麻豆 | 国产精品久久久久aaaa| 99精品视频免费| 成人精品综合免费视频| 国产成人精品免费视频大全麻豆| 国产精品无码无片在线观看| .精品久久久麻豆国产精品 | 蜜臀AV无码国产精品色午夜麻豆| 无码欧精品亚洲日韩一区夜夜嗨| 日韩专区亚洲精品欧美专区|