Telegram游戏Bot特殊用户名致HTML标记失效问题求助
问题背景
我用python-telegram-bot框架(Python 3.10.12)开发了一款Telegram游戏Bot,核心功能是根据用户的名-姓组合生成按分数排序的聊天用户排行榜,每个用户姓名都对应跳转链接。代码里已经默认对姓名做了HTML转义,但遇到包含特殊字符的用户名(比如$̴̢̛̙͈͚̎̓͆͑.̸̱̖͑͒ ̧̡͉̺̬͎̯.̸̧̢̠̺̮̬͙͛̓̀̐́.̵̦͑̉͌͌̎͘ ̞ ̷̡͈̤̓̀͋͗͊̈́̑̽͝)时,Telegram解析HTML标记出现异常:链接会溢出到无关字符,<b>标签也直接失效。
是不是Telegram的Bug?
这大概率是Telegram HTML解析器对**Unicode组合字符(比如变音符号、修饰符)**处理不当导致的缺陷。这类特殊字符属于非基础Unicode字符,Telegram的解析器在处理时没能正确区分基础字符和附加的修饰符号,导致HTML标签的边界被错误识别,进而引发链接溢出、格式失效的问题。官方短期内未必会修复这类小众场景的问题,所以得自己做规避处理。
规避方案
1. 过滤危险的Unicode组合字符
直接移除所有非基础的Unicode组合标记(Unicode类别为Mn的字符),只保留常规字母、数字和常见符号。虽然会改变用户名的显示,但能彻底避免解析异常:
import unicodedata def sanitize_username(username): # 过滤所有Unicode组合标记类字符 return ''.join(c for c in username if unicodedata.category(c) != 'Mn')
2. 转义后截断内容
如果不想完全移除字符,可以先做HTML转义,再限制显示的用户名长度,减少异常出现的概率:
from telegram.utils.helpers import escape_html def safe_format_username(username): escaped_name = escape_html(username) # 截断过长内容,避免解析逻辑过载 return escaped_name[:30] + '...' if len(escaped_name) > 30 else escaped_name
3. 改用MarkdownV2格式
python-telegram-bot支持MarkdownV2格式,其转义规则和HTML不同,对特殊字符的兼容性更好。可以尝试用这种格式生成链接和加粗效果:
from telegram.utils.helpers import escape_markdown_v2 def format_with_markdown(username, user_id): escaped_name = escape_markdown_v2(username) # 生成MarkdownV2格式的用户跳转链接 return f"[{escaped_name}](tg://user?id={user_id})"
注意MarkdownV2的转义规则更严格,必须使用框架提供的escape_markdown_v2工具函数处理特殊字符。
关于编码问题
这不是UTF-8/UTF-16的编码问题,这些特殊字符本身是合法的Unicode字符,UTF-8/UTF-16都能正确存储。问题根源在Telegram的解析逻辑,而非编码本身。
内容的提问来源于stack exchange,提问作者winwin

