本文目录导读:

在PHP中实现API敏感词过滤,常见的方法包括基于数组的匹配、基于Trie树的匹配等,以下是几种常见的实现方式,从简单到高效:
基于数组的简单匹配(适合少量敏感词)
class SensitiveFilter {
private $sensitiveWords = ['敏感词1', '敏感词2', '敏感词3'];
public function filter($text, $replaceChar = '*') {
foreach ($this->sensitiveWords as $word) {
$text = str_replace($word, str_repeat($replaceChar, mb_strlen($word)), $text);
}
return $text;
}
public function contains($text) {
foreach ($this->sensitiveWords as $word) {
if (mb_strpos($text, $word) !== false) {
return true;
}
}
return false;
}
}
// 使用示例
$filter = new SensitiveFilter();
$text = "这是一个包含敏感词1的文本";
$filtered = $filter->filter($text);
基于Trie树的高效方案(推荐)
class TrieNode {
public $children = [];
public $isEnd = false;
}
class SensitiveFilterTrie {
private $root;
private $sensitiveWords = [];
public function __construct() {
$this->root = new TrieNode();
}
/**
* 加载敏感词列表
*/
public function loadWords(array $words) {
$this->sensitiveWords = $words;
foreach ($words as $word) {
$this->addWord($word);
}
}
/**
* 添加单个敏感词到Trie树
*/
private function addWord($word) {
$node = $this->root;
$len = mb_strlen($word);
for ($i = 0; $i < $len; $i++) {
$char = mb_substr($word, $i, 1);
if (!isset($node->children[$char])) {
$node->children[$char] = new TrieNode();
}
$node = $node->children[$char];
}
$node->isEnd = true;
}
/**
* 检测文本是否包含敏感词
*/
public function contains($text) {
$len = mb_strlen($text);
for ($i = 0; $i < $len; $i++) {
$node = $this->root;
for ($j = $i; $j < $len; $j++) {
$char = mb_substr($text, $j, 1);
if (!isset($node->children[$char])) {
break;
}
$node = $node->children[$char];
if ($node->isEnd) {
return true;
}
}
}
return false;
}
/**
* 过滤敏感词
*/
public function filter($text, $replaceChar = '*') {
$len = mb_strlen($text);
$result = [];
$foundWords = [];
for ($i = 0; $i < $len; $i++) {
$node = $this->root;
$wordStart = $i;
for ($j = $i; $j < $len; $j++) {
$char = mb_substr($text, $j, 1);
if (!isset($node->children[$char])) {
break;
}
$node = $node->children[$char];
if ($node->isEnd) {
$wordLen = $j - $i + 1;
$result[] = str_repeat($replaceChar, $wordLen);
$i = $j;
$foundWords[] = mb_substr($text, $wordStart, $wordLen);
continue 2;
}
}
$result[] = mb_substr($text, $i, 1);
}
return implode('', $result);
}
/**
* 获取所有匹配的敏感词
*/
public function getFoundWords($text) {
$foundWords = [];
$len = mb_strlen($text);
for ($i = 0; $i < $len; $i++) {
$node = $this->root;
for ($j = $i; $j < $len; $j++) {
$char = mb_substr($text, $j, 1);
if (!isset($node->children[$char])) {
break;
}
$node = $node->children[$char];
if ($node->isEnd) {
$foundWords[] = mb_substr($text, $i, $j - $i + 1);
$i = $j;
break;
}
}
}
return array_unique($foundWords);
}
}
// 使用示例
$filter = new SensitiveFilterTrie();
$filter->loadWords(['敏感词1', '敏感词2', '敏感词3', '测试']);
$text = "这是一个包含敏感词1和测试的文本";
echo "是否包含敏感词: " . ($filter->contains($text) ? '是' : '否') . "\n";
echo "过滤后: " . $filter->filter($text) . "\n";
echo "发现的敏感词: " . implode(', ', $filter->getFoundWords($text));
基于正则表达式(适合模式匹配)
class SensitiveFilterRegex {
private $pattern;
public function __construct(array $words) {
// 对敏感词进行转义并构建正则
$escaped = array_map('preg_quote', $words);
$this->pattern = '/(' . implode('|', $escaped) . ')/u';
}
public function filter($text, $replaceChar = '*') {
return preg_replace_callback($this->pattern, function($matches) use ($replaceChar) {
return str_repeat($replaceChar, mb_strlen($matches[0]));
}, $text);
}
public function contains($text) {
return (bool) preg_match($this->pattern, $text);
}
}
// 使用示例
$filter = new SensitiveFilterRegex(['敏感词1', '敏感词2']);
echo $filter->filter("包含敏感词1的文本");
API集成方案
<?php
header('Content-Type: application/json; charset=utf-8');
require_once 'SensitiveFilterTrie.php'; // 包含上面的类
class SensitiveAPI {
private $filter;
public function __construct() {
$this->filter = new SensitiveFilterTrie();
// 从文件或数据库加载敏感词
$this->loadSensitiveWords();
}
private function loadSensitiveWords() {
// 方式1: 从文件加载
$words = file('sensitive_words.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
// 方式2: 从数据库加载
// $words = $this->getFromDatabase();
$this->filter->loadWords($words);
}
public function handleRequest() {
$method = $_SERVER['REQUEST_METHOD'];
$input = json_decode(file_get_contents('php://input'), true);
switch ($method) {
case 'POST':
if (isset($input['text'])) {
$text = $input['text'];
$action = isset($input['action']) ? $input['action'] : 'filter';
switch ($action) {
case 'check':
$result = [
'contains' => $this->filter->contains($text),
'found_words' => $this->filter->getFoundWords($text)
];
break;
case 'filter':
default:
$result = [
'original' => $text,
'filtered' => $this->filter->filter($text,
isset($input['replace_char']) ? $input['replace_char'] : '*'),
'found_words' => $this->filter->getFoundWords($text)
];
break;
}
$this->response(200, $result);
} else {
$this->response(400, ['error' => 'Missing text parameter']);
}
break;
default:
$this->response(405, ['error' => 'Method not allowed']);
}
}
private function response($code, $data) {
http_response_code($code);
echo json_encode($data, JSON_UNESCAPED_UNICODE);
exit;
}
}
// 使用
$api = new SensitiveAPI();
$api->handleRequest();
优化建议
// 1. 缓存敏感词树到文件
class CachedSensitiveFilter extends SensitiveFilterTrie {
private $cacheFile = 'sensitive_tree.cache';
public function loadWords(array $words) {
// 检查缓存
if (file_exists($this->cacheFile) &&
filemtime($this->cacheFile) > $this->getLastModifyTime()) {
$this->root = unserialize(file_get_contents($this->cacheFile));
} else {
parent::loadWords($words);
// 保存缓存
file_put_contents($this->cacheFile, serialize($this->root));
}
}
private function getLastModifyTime() {
// 返回敏感词列表的最后修改时间
}
}
// 2. 使用Redis缓存
class RedisSensitiveFilter extends SensitiveFilterTrie {
private $redis;
private $cacheKey = 'sensitive_filter_tree';
public function loadWords(array $words) {
$cached = $this->redis->get($this->cacheKey);
if ($cached) {
$this->root = unserialize($cached);
} else {
parent::loadWords($words);
$this->redis->set($this->cacheKey, serialize($this->root));
}
}
}
使用建议
- 性能优先:使用Trie树实现,时间复杂度O(n*m),n为文本长度,m为敏感词平均长度
- 更新便利:敏感词从数据库或文件加载,支持热更新
- 批量处理:支持批量API请求
- 错误处理:添加适当的异常处理
- 编码处理:注意UTF-8编码的多字节字符处理
选择哪种方案取决于你的具体需求:简单场景用数组匹配,高性能场景用Trie树,模式匹配复杂用正则。