首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 敏感詞過濾實作:關鍵字檔案載入、陣列遍歷與正則匹配兩種方案

     編輯:PHP 綜合知識

內容審核系統的核心需求是敏感詞過濾。本文提供兩種 PHP 實作方案:方案一:逐詞 strpos 遍歷(簡單、適合中小詞庫)、方案二:合併正則單次匹配(高效、適合大詞庫),並解析編碼陷阱、效能優化與擴展建議。

方案一:逐詞遍歷檢測(strpos 版)

關鍵字儲存於 keyWords.txt,每行一詞,UTF-8 編碼。

function keyWordCheck(string $content): string|false {
    $content = trim($content);
    $file = __DIR__ . '/keyWords.txt';
    if (!is_readable($file)) return false;

    $words = file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
    foreach ($words as $word) {
        $word = trim($word);
        if ($word === '') continue;
        // stripos 大小寫不敏感;mb_strpos 支援多位元組
        if (mb_strpos($content, $word) !== false) {
            return $word; // 返回首個命中的敏感詞
        }
    }
    return false;
}

// 使用
$text = '這裡是要發布的文本內容。。。';
if ($bad = keyWordCheck($text)) {
    echo "內容包含敏感詞:$bad";
} else {
    echo "通過檢測,可入庫";
}

方案二:合併正則單次匹配(PCRE 版)

將所有敏感詞以 | 連接成一個巨大正則,**一次掃描**即可檢測所有詞彙,效能遠優於逐詞循環。

function banwordCheck(string $string, string $fileName): bool {
    $pattern = @file_get_contents($fileName);
    if ($pattern === false) die('敏感詞檔案讀取失敗');

    // 檔案內容已為 "詞1|詞2|詞3" 格式,或每行一詞需自行 implode('|', $arr)
    // 加上邊界修飾詞防止部分匹配誤傷(視需求)
    $regex = '/' . $pattern . '/iu'; // i=不分大小寫, u=UTF-8

    return (bool)preg_match($regex, $string);
}

// 敏感詞檔 banwords.txt 內容範例:
// 賭博|色情|暴力|敏感詞4|敏感詞5

// 使用
$content = '測試關鍵字';
if (banwordCheck($content, __DIR__ . '/banwords.txt')) {
    echo "命中敏感詞";
} else {
    echo "未命中";
}

效能對比與選擇建議

指標strpos 遍歷合併正則
詞庫規模< 5,000 詞> 5,000 詞(可達 10 萬+)
單次檢測時間O(N × L) 線性增長O(L) 單次掃描,N 為詞數,L 為文本長度
記憶體佔用低中(正則編譯緩存)
維護難度低(純文字檔)中(需處理正則元字元轉義)
支援邊界/詞性困難可透過 \b, (?<!\w) 等實現

關鍵細節與避坑指南

  1. 正則元字元轉義:敏感詞若含 . * + ? [ ] ( ) { } | ^ $ \ 等,合併正則前**必須** preg_quote($word, '/') 轉義,否則導致正則語法錯誤或匹配異常。
  2. UTF-8 編碼一致性:檔案、PHP 腳本、資料庫、HTTP 輸出**全鏈路 UTF-8**。/u 修飾符強制 PCRE 以 UTF-8 模式運作,避免多位元組字元被拆分匹配。
  3. 短詞誤傷:如敏感詞「幹」,會誤殺「幹部」、「幹勁」。解決:
    ① 詞庫維護最短長度 ≥ 2 字
    ② 正則加詞邊界 /\b(?:詞1|詞2)\b/u(中文詞邊界較複雜,建議引入分詞庫)
    ③ 人工複審機制
  4. 效能陷阱:災難性回溯:避免在正則中使用巢狀量詞(如 (a+)+)。敏感詞正則純交替 A|B|C 安全,但若詞庫極大(>5 萬),PCRE 編譯/匹配可能超時,需分塊或改用 Aho-Corasick 自動機(PHP 擴展 php-aho-corasick 或純 PHP 實現)。
  5. 替換/標記功能擴展:preg_replace_callback 可將命中詞替換為 ***、<mark>$0</mark> 或記錄位置。

進階架構:分層過濾管線

class ContentFilter {
    public function filter(string $text): array {
        $result = ['clean' => $text, 'hits' => [], 'level' => 'pass'];

        // 1. 快速正則檢測(高危詞)
        if ($this->regexHighRisk->match($text)) {
            $result['level'] = 'reject';
            return $result;
        }

        // 2. Aho-Corasick 多模式匹配(通用詞庫)
        $hits = $this->acAutomaton->search($text);
        if ($hits) {
            $result['hits'] = $hits;
            $result['level'] = 'review';
            $result['clean'] = $this->mask($text, $hits);
        }

        return $result;
    }
}

總結

中小專案用 strpos 遍歷足夠;大流量、大詞庫**必須**用合併正則或 Aho-Corasick 自動機。核心鐵律:**UTF-8 全鏈路、元字元轉義、短詞誤傷防範、效能基準測試**。建議引入成熟庫(如 phpsensitive, htmlpurifier 內建過濾)而非重造輪子。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved