敏感词检测
题记
本文主要用于记录如何在go中使用敏感词检测和对底层源码的分析。主要参考的GitHub仓库是:github.com/feiin/sensitivewords。
用法
1 | package main |
这是一个实例,来展示Go如何使用敏感词检测技术。
底层源码剖析
该图片是本文仓库的文件目录。

在这里我们主要是分析trie.go文件。
keywords.txt主要是敏感词测试文件
1 | 卧槽 |
doc.go里面没有代码

example_test.go,sensitive_words_test.go,trie_test.go,这些均为测试代码,我们不做分析处理。
sensitive_words.go文件主要是实例化一个敏感词库,加载敏感词库的文件(keywords.txt)并调用Add方法添加到敏感词库中。对我们了解敏感词检测的实现意义不大。我们不做多的学习。
trie.go是我们接下来主要要探究的部分。
1 | //TrieTree Trie树 |
首先定义了两个结构体:TrieTree和TrieNode。TrieTree表示整个Trie树,其中包含一个指向根节点的指针Root。TrieNode表示树中的节点,其中包含一个布尔值IsEnd用于标识当前节点是否为一个敏感词的结束节点,以及一个Children映射表,用于存储当前节点的子节点。
接下来定义了NewTrieTree函数,用于创建一个新的TrieTree对象。该函数会初始化根节点,并返回TrieTree对象的指针。
1 | //Add 添加敏感词 |
该方法接收一个字符串参数 word,表示要添加的敏感词。首先,通过检查 word 是否为空字符串,如果为空,则直接返回,不执行任何操作。然后,定义一个指针变量 treeNode,指向 Trie 树的根节点 tree.Root,用于表示当前节点。将要添加的敏感词 word 转换为一个 rune 类型的切片 treeWords,方便按字符遍历敏感词。然后,定义一个指针变量 current,指向当前节点 treeNode,用于表示当前遍历的节点。接下来,通过 for 循环遍历敏感词的每个字符。在每次循环中,将当前字符存储在 word 变量中。通过检查当前节点的 Children 字段,判断当前字符是否已经是当前节点的子节点之一。如果是,则更新 current 为当前字符对应的子节点。如果当前字符不是当前节点的子节点,则表示该字符还未在当前节点的子节点中,需要创建一个新的节点。创建一个新的节点 newNode,设置其 IsEnd 字段为 false,并初始化其 Children 字段为一个空的 map[rune]*TrieNode。将新节点 newNode 添加到当前节点 current 的 Children 字段中,键为当前字符 word。然后,将 current 更新为新添加的节点 newNode,以便继续遍历敏感词的下一个字符。循环结束后,表示敏感词的所有字符都已经遍历完毕。将最后一个字符对应的节点 current 的 IsEnd 字段设置为 true,表示该节点是敏感词的结尾节点。
AddWords函数本质上就是调用Add方法。
1 | //Filter 过滤敏感词为* |

1 | //Find 查找敏感词,找到第一个就退出 |
该方法接收一个字符串参数 input,表示要进行敏感词查找的输入文本。首先,将输入文本 input 转换为一个 rune 类型的切片 words,方便按字符遍历文本。然后,定义变量 current(指向当前节点)、found(表示是否找到字符)、treeNode(指向 Trie 树的根节点)、offset(表示当前遍历的字符偏移量)。通过一个 for 循环遍历输入文本的每个字符。在每次循环中,将当前字符存储在变量 w 中。通过检查当前节点的 Children 字段,判断当前字符是否是当前节点的子节点之一。如果是,则更新 current 为当前字符对应的子节点,并将 found 设置为 true。如果当前字符不是当前节点的子节点,则表示该字符不在当前节点的子节点中,需要进行回溯。将循环索引 i 减去偏移量 offset,以回退到上一个已匹配的位置。将偏移量 offset 重置为 0,表示回退后的位置。将当前节点 treeNode 更新为 Trie 树的根节点,以重新开始匹配过程。循环结束后,表示整个文本已经遍历完毕。如果最后一个字符对应的节点 current 是敏感词的结尾节点(current.IsEnd 为 true),则表示找到了敏感词。此时,返回结果为 true 和找到的敏感词,即 string(words[i-offset : i+1])。如果循环结束时没有找到敏感词,则返回结果为 false 和一个空字符串。通过上述操作,方法可以在输入文本中查找敏感词,并返回是否找到敏感词以及找到的第一个敏感词。请注意,此方法只会找到第一个敏感词并立即退出,而不会继续查找其他可能存在的敏感词。
FindAll函数本质上就是定义了一个[]string类型的results,每次找到敏感词就append进results。
FindAny函数本质上就是定义了一个[]string类型的results,每次找到敏感词就append进results,只不过他会判断len(result)==count。
- 标题: 敏感词检测
- 作者: 纸鸢
- 创建于 : 2023-06-19 19:39:10
- 更新于 : 2023-06-20 00:57:28
- 链接: https://www.youandgentleness.cn/2023/06/19/敏感词检测/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。