discord.py聊天过滤机器人如何实现大写检测与绕开内容拦截
discord.py 抗绕过聊天过滤机器人落地方案
核心实现思路
- 放弃“枚举所有违规变形形式”的传统逻辑,转向消息内容归一化:不管用户用大写混排、插空格、插特殊符号的方式绕开检测,先把收到的消息转成统一的小写、无干扰字符的标准形式,再用精简的标准违规词库做匹配,从根源上减少重复维护工作。
第一层:消息预处理归一化逻辑(解决大写、夹符绕过)
具体实现步骤:
- 统一大小写变体匹配:收到原始消息后先做全小写转换,无论用户发全大写、大小写混排的违规词,转成小写后都能和标准违规词直接匹配,不需要单独在词表里存大写形式的违规词。
- 全角/不可见字符统一清洗:
- 用
unicodedata.normalize('NFKC', 原始内容)把全角字母、全角标点统一转成半角格式,解决用户用全角字符规避检测的问题 - 用正则匹配并删除零宽空格、隐形控制符,避免用户插入不可见字符把违规词拆成无连续字符的状态
- 用
- 插入间隔的内容合并:针对用户在违规词中间插单个空格、单个特殊符号的绕过,用正则匹配两个字母之间长度在0-2的非字母短间隔,循环2-3次把间隔内容剥离,把拆分的词拼回完整形态,不需要枚举所有插符的写法。
注意:这里的清洗范围严格限定在两个字母之间的短间隔,不要全局删除所有非字母字符,否则会把正常聊天的标点、语义全部打坏,增加误判概率。
第二层:轻量化匹配逻辑
- 违规词库只存标准小写形式的违规内容,不需要录入任何大写变体、插符变体的扩展词条,比如词表只需要存
"badword",不需要额外存"BADWORD"、"b a d w o r d"、"b*a*d*w*o*r*d"这些条目。 - 针对高风险违规词,可以适当放宽间隔匹配的阈值(比如允许两个字母之间最多夹3个非字母字符),普通日常违规词用默认阈值(最多夹2个非字母字符),平衡检测率和误判率。
可直接复用的discord.py 示例代码
import re import unicodedata import discord from discord.ext import commands # 标准违规词库,仅存小写核心形式 BANNED_WORDS = {"badword", "示例违规词"} # 匹配零宽隐形字符的正则 INVISIBLE_CHAR_PATTERN = re.compile(r'[\u200b-\u200d\ufeff\u2060]') # 匹配两个字母之间的短间隔(最多夹2个非字母字符) INTERLEAVE_PATTERN = re.compile(r'([a-z])[^a-z]{0,2}([a-z])') def normalize_message(raw_content: str) -> str: # 全角转半角,统一字符格式 content = unicodedata.normalize('NFKC', raw_content) # 转全小写,消除大小写变体 content = content.lower() # 删除不可见零宽字符 content = INVISIBLE_CHAR_PATTERN.sub('', content) # 循环合并字母间的短间隔 for _ in range(3): content = INTERLEAVE_PATTERN.sub(r'\1\2', content) return content intents = discord.Intents.default() intents.message_content = True bot = commands.Bot(command_prefix="!", intents=intents) @bot.event async def on_message(message): # 跳过机器人消息,避免循环触发 if message.author.bot: return # 归一化处理收到的消息 normalized_content = normalize_message(message.content) # 匹配是否命中违规词 hit_banned_word = next( (word for word in BANNED_WORDS if word in normalized_content), None ) if hit_banned_word: # 执行拦截动作:删除违规消息、发送临时提醒 await message.delete() await message.channel.send( f"{message.author.mention} 请遵守频道发言规则,不要发送违规内容", delete_after=5 ) await bot.process_commands(message)
避坑提示
- 不要全局删除消息里的非字母字符:全局删符号会把正常语句里的词拼出意想不到的连续片段,增加误判概率;只在两个字母的短间隔位置做清洗,就能大幅降低这类问题。
- 不要颠倒预处理顺序:必须先做全角转半角、小写转换、不可见字符删除,最后再做间隔合并,顺序颠倒会导致很多变形内容漏检。
- 针对常见的同形字母替换(比如用西里尔字母的а代替拉丁字母的a),可以在归一化阶段加一个简单的字符映射表,把高频同形字符替换成对应的拉丁字母,不需要额外加复杂的检测规则。
内容的提问来源于stack exchange,提问作者TheSuperRobert
相关产品推荐
相关产品推荐

