Discord机器人反脏话系统误判含违禁词片段的正常单词,如何在不删黑名单词的前提下解决?
误判根源
当前检测逻辑采用无边界子串匹配,只要消息文本中连续出现黑名单的字符序列就触发拦截,完全不判断该序列是否为独立成词,因此会把whoever、shoe这类正常词汇中嵌入的hoe子串误判为违禁内容。整个方案完全保留黑名单中的"hoe"条目,从匹配规则层面消除误判,不需要调整现有黑名单内容。
落地修改步骤
替换核心匹配规则
用带单词边界的正则匹配替代原生字符串子串判断,利用正则的\b标识匹配词与非词字符(空格、标点、句首/句尾)的交界位置,仅当违禁词作为独立完整单词出现时才触发命中,不会抓取嵌入在其他单词内部的子串。
首先导入正则依赖:
import re
在加载黑名单文件完成遍历后,提前将每个违禁词编译为带边界的匹配对象,避免每次消息触发都重复编译正则拖慢性能:
# 预处理黑名单:每个词转成仅匹配独立成词的正则规则 badword_patterns = [] for badword in file: cleaned_word = badword.strip().lower() # re.escape 用来避免黑名单中含特殊正则符号时触发语法错误 pattern = re.compile(rf'\b{re.escape(cleaned_word)}\b') badword_patterns.append(pattern)
把原来代码中所有的子串判断逻辑:
if badword in message.content.lower()
替换为正则匹配逻辑:
content = message.content.lower() for pattern in badword_patterns: if pattern.search(content): # 原有的删消息、发警告、发日志embed的逻辑完全保留即可
这套规则下,独立出现的hoe会被正常拦截,而whoever、shoe这类把hoe嵌在单词内部的内容不会触发误判。
复用逻辑减少重复代码
可以把违规检测、删消息、发警告、发日志的重复逻辑抽成一个独立的异步函数,
on_message和on_message_edit调用同一个函数,避免两个事件里的代码改了一边漏了另一边。
顺带修复现有代码的运行bug
原实现中存在几处会导致功能异常的问题,改匹配逻辑时可一并修正:
- 违规拦截触发后的
return语句后方的await client.process_commands(message)属于永远不会执行的死代码,可直接移除 on_message_edit事件中,构造日志embed、打印日志时错将after变量写为不存在的全局message变量,运行到拦截分支会直接抛出NameError,需要全部替换为after.author对应的取值- 确保趣味回复逻辑(比如"Jason derulo"触发的"Wiggle wiggle wiggle")、
client.process_commands(message)的调用不会被违规拦截逻辑意外跳过
后续可扩展的适配
如果遇到用户用特殊字符拆分违禁词(比如h o e、h*e)的绕过场景,可以在跑匹配前加一层轻量预处理:把消息文本中的非字母数字字符统一替换为空格,再送入匹配流程,无需一开始就上复杂的敏感词算法。这套方案的性能开销极低,完全能适配普通规模Discord服务器的消息量。
内容的提问来源于stack exchange,提问作者Ender 2K89
相关产品推荐
相关产品推荐

