用php实现一个敏感词过滤功能

时间:2022-10-12 11:10:17

周末空余时间撸了一个敏感词过滤功能,下边记录下实现过程。

敏感词,一方面是你懂的,另一方面是我们自己可能也要过滤一些人身攻击或者广告信息等,具体词库可以google下,有很多。

过滤敏感词,使用简单的循环str_replace是性能很低效的,还会随着词库的增加,性能指数下降,而且简单的替换,不能解决一些不是完全匹配的词。这时候就需要先构建一个字典树(trie),单纯的字典树占用空间较大,使用Double-Array Trie或者Ternary Search Tree可以在保证性能的同时节省一部分空间,但是敏感词基本不会很多,几千甚至上万个词基本没压力,所以就实现就选择先构建一个字典树,然后逐字做匹配。

代码不多,就贴到这里。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
<?php

class SensitiveWordFilter
{
private $dict;
private $dictPath;

public function __construct($dictPath)
{
$this->dict = array();
$this->dictPath = $dictPath;
$this->initDict();
}

private function initDict()
{
$handle = fopen($this->dictPath, 'r');
if (!$handle) {
throw new RuntimeException('open dictionary file error.');
}

while (!feof($handle)) {
$word = trim(fgets($handle, 128));

if (empty($word)) {
continue;
}

$uWord = $this->unicodeSplit($word);

$pdict = &$this->dict;

$count = count($uWord);
for ($i = 0; $i < $count; $i++) {
if (!isset($pdict[$uWord[$i]])) {
$pdict[$uWord[$i]] = array();
}
$pdict = &$pdict[$uWord[$i]];
}

$pdict['end'] = true;
}

fclose($handle);
}

public function filter($str, $maxDistance = 5)
{
if ($maxDistance < 1) {
$maxDistance = 1