如何实现高效可靠的聊天不良词语过滤器?支持变形违禁词识别
如何构建适用于聊天场景的优质不良词语过滤器?
嘿,这个需求我之前做即时聊天系统的时候正好碰到过,专门研究过怎么对付这类花式规避违禁词的操作,分享下我实践下来的靠谱方案,完美覆盖你说的Poop、pooopppp、P00p这类变形情况。
核心设计思路
首先得明确用户常用的规避手段:大小写混淆、连续重复字符、形近字符替换(比如0替o、1替l),我们的过滤器就要针对性地把这些变形“打回原形”,再做匹配判断。
具体实现步骤
1. 输入文本预处理(关键步骤)
这一步是把各种变形统一成标准格式,方便后续匹配:
- 统一大小写:把输入全转成小写(或大写),直接消除大小写混淆的问题,比如
P00p转成p00p。 - 替换形近字符:提前建一个常见替换映射表,把用户用来规避的字符转成原字符,比如
{'0':'o', '1':'l', '@':'a', '$':'s'},这样P0o0o0op会被转成poooooop。 - 压缩连续重复字符:用正则把连续重复的单个字符只保留一次,比如
pooopppp会被压缩成poop,这里用的正则是re.sub(r'(.)\1+', r'\1', text),原理是匹配任意连续重复的字符,替换成单个该字符。
2. 违禁词匹配策略
预处理完成后,就可以做匹配了:
- 精确匹配:把处理后的文本和违禁词库做比对,只要包含违禁词就触发过滤。如果怕误判正常词汇(比如
poop deck这种专业术语),可以用正则的整词匹配(\bpoop\b),只匹配独立的违禁词。 - 模糊匹配(可选):如果要覆盖更多变形,比如用户打错字的情况,可以用编辑距离(Levenshtein距离),判断处理后的文本和违禁词的差异度是否小于阈值(比如1),但这个要谨慎用,不然容易误拦正常内容。
3. 触发后的处理逻辑
- 直接拦截违规消息,不允许发送到聊天频道;
- 给用户返回清晰的警告提示,比如
"抱歉,你的消息包含违规内容,请修改后重试。"
代码示例(Python)
给你写个可直接用的Demo,包含上面所有逻辑:
import re # 自定义违禁词库,可根据需求扩展 banned_words = {'poop'} # 形近字符映射表,覆盖常见规避替换 char_mapping = { '0': 'o', '1': 'l', '!': 'l', '@': 'a', '$': 's', '3': 'e', '4': 'a', '5': 's', '7': 't', } def preprocess_input(text): # 统一转小写 processed_text = text.lower() # 替换形近字符 for orig_char, target_char in char_mapping.items(): processed_text = processed_text.replace(orig_char, target_char) # 压缩连续重复字符 processed_text = re.sub(r'(.)\1+', r'\1', processed_text) return processed_text def check_banned_content(text): processed_text = preprocess_input(text) # 检查是否包含违禁词(支持整词匹配,避免误判) for word in banned_words: if re.search(rf'\b{word}\b', processed_text): return True return False # 测试各种变形案例 test_messages = ['Poop', 'pooopppp', 'P00p', 'Po0p', 'P0o0o0op', 'poop deck'] for msg in test_messages: if check_banned_content(msg): print(f"拦截消息:{msg} → 提示:抱歉,你的消息包含违规内容,请修改后重试。") else: print(f"消息通过:{msg}")
优化建议
- 动态更新违禁词库:做个后台管理界面,让运营可以随时添加/删除违禁词,不用每次改代码重新部署;
- 性能优化:如果违禁词库很大(上千个词),用Trie树来做匹配会比遍历每个词效率高很多,适合高并发的聊天场景;
- 白名单机制:把一些容易被误判的正常词汇加入白名单,比如专业术语、人名等,减少误拦率。
内容的提问来源于stack exchange,提问作者Arjay




