← 返回列表

Markdown与HTML富文本机器人消息在解析时的转义与清洗

分类:Telegram机器人发布于:2026-09-07

telegram中文搜索群组

在 Telegram 机器人开发中,消息看似只是几行文字,但一旦加入加粗、斜体、超链接、代码块或用户动态内容,就会涉及 Markdown、HTML、实体解析、字符转义与安全清洗等多个环节。

很多“消息发送失败”“格式错乱”“链接无法点击”甚至“机器人被注入恶意标签”的问题,并不是 Telegram 本身不稳定,而是转义顺序、解析模式和清洗策略没有统一造成的。

🧭 一、先理解 Telegram 的消息解析模式

Telegram Bot API 常见的富文本处理方式主要有三种:MarkdownV2、HTML 和 MessageEntity 实体。开发者通常通过 sendMessage 接口的 parse_mode 参数,告诉 Telegram 应该如何解释 text 字段。

如果设置为 MarkdownV2,Telegram 会把特定符号识别为格式标记;如果设置为 HTML,则会识别允许的 HTML 标签。两种语法不能混用,否则普通字符可能被当成格式控制符,最终导致解析错误。

sendMessage(
  chat_id = 123456789,
  text = "<b>欢迎使用机器人</b>",
  parse_mode = "HTML"
)

上面的示例使用 HTML 模式,因此加粗内容必须使用 Telegram 支持的标签。如果把 MarkdownV2 写法 *欢迎使用机器人* 直接放进去,Telegram 并不会自动把它识别为 HTML 加粗。

1. MarkdownV2 的特点

MarkdownV2 语法简洁,适合格式相对固定的通知、菜单和状态消息,但它对特殊字符非常敏感。下划线、星号、方括号、括号、波浪线、反引号、竖线、加号、减号、等号、句号和感叹号等字符,在特定上下文中都可能需要转义。

对于动态内容,不能只转义用户输入中的星号,因为 URL、文件名、价格、版本号和普通标点也可能触发 MarkdownV2 解析。更稳妥的做法是建立完整的 MarkdownV2 转义函数,并明确哪些部分是模板、哪些部分是外部数据。

需要重点处理的 MarkdownV2 特殊字符:
_ * [ ] ( ) ~ ` > # + - = | { } . !

示例:
原始文本:版本 2.0!价格:+10%
转义后:版本 2\.0!价格:\+10%

2. HTML 模式的特点

HTML 模式更容易阅读,也更适合由模板生成富文本消息,但它并不是完整浏览器 HTML。Telegram 只支持有限的标签和属性,不能直接把网页中的任意 HTML 原样发送。

例如,常见的加粗、斜体、下划线、删除线、代码、预格式文本和链接通常可以使用,但复杂的 div、style、script、事件属性以及自定义 CSS 都不应该进入发送内容。

<b>加粗文本</b>
<i>斜体文本</i>
<u>下划线文本</u>
<code>const id = 1;</code>
<a href="https://example.com">打开链接</a>

🧹 二、转义与清洗不是一回事

转义的目标是让特殊字符失去语法含义,恢复为普通文本。例如,在 HTML 模式中,用户输入的 < 不应被解析成标签,而应该显示为一个小于号。

清洗的目标则是删除或改写不允许的标签、属性和协议。它解决的是输入内容是否安全、是否符合白名单,而不只是“能不能正常显示”。

实际项目中,正确顺序通常是:先判断内容来源,再根据目标 parse_mode 进行清洗和转义,最后拼接模板并发送。不要先拼出一段 HTML,再使用简单的字符串替换进行补救,因为这很容易破坏已有标签。

1. HTML 动态内容的安全处理

假设机器人需要把用户昵称插入 HTML 消息,昵称必须作为纯文本处理,而不是直接拼接到标签中。否则用户输入的尖括号、引号或伪造标签,可能改变消息结构。

原始昵称:
<b>管理员</b>

安全显示:
<b>&lt;b&gt;管理员&lt;/b&gt;</b>

最终效果:
<b>&lt;b&gt;管理员&lt;/b&gt;</b>

这里的关键不是删除用户输入,而是将用户输入转义为文本节点。如果业务确实允许用户提交少量富文本,则应使用 HTML 白名单清洗器,而不是放开全部标签。

2. URL 必须额外检查

链接处理不能只检查是否以 http 开头,还应限制协议范围。一般只允许 https、http,必要时再允许 tg 等业务明确需要的协议,同时拒绝 javascript、data 和 file 等危险协议。

链接文字和 href 属性也应该分开处理:链接文字进行 HTML 文本转义,href 则进行 URL 规范化和协议校验。不要把未经检查的用户输入直接放入 href 引号内部。

⚙️ 三、推荐的消息构建流程

一个稳定的机器人消息管线,应该把“数据、格式和发送”拆开,而不是在业务代码中到处拼接字符串。这样不仅便于测试,也能避免同一段内容在不同场景下重复转义。

第一步:区分可信模板与不可信数据

机器人固定标题、按钮说明和系统提示通常属于可信模板;用户名、群名称、搜索关键词、外部接口返回值和用户投稿则属于不可信数据。后者必须经过统一处理,不能因为“只是展示”就跳过验证。

第二步:统一选择一种解析模式

如果团队偏好可读性,可以统一使用 HTML;如果消息主要由 Markdown 模板生成,则统一使用 MarkdownV2。最忌讳的是同一个函数根据不同调用者随意切换 parse_mode,却没有同步切换转义器。

第三步:在发送前做最小化验证

发送前可以检查标签是否闭合、链接协议是否合规、消息长度是否超出限制,以及 MarkdownV2 的反斜杠数量是否正确。对于复杂消息,建议在测试机器人中覆盖普通文本、空字符串、换行、Emoji、特殊符号和超长输入。

建议的处理顺序:

1. 接收原始数据
2. 判断字段类型与可信等级
3. 清洗 HTML 标签或转义纯文本
4. 拼接固定模板
5. 校验链接、长度和格式
6. 指定 parse_mode
7. 捕获 Telegram API 错误并记录原文

电报精准找群黑科技提示:

由于 Telegram 官方搜索对中文支持极差,很多优质的推广、技术和资源群组隐藏极深。如果你正在寻找相关的活跃社群,强烈推荐使用本站首页的 【TTSO - Telegram 智能搜索 Bot】。作为目前最好用的电报综合搜索导航,只需输入关键词,即可秒级触达数十万个精选 TG 中文群组、资源频道。一键直达,帮你节省 90% 的找群时间!

🔍 四、常见解析错误与排查方法

当 Telegram 返回“can't parse entities”或类似错误时,通常意味着标签未闭合、MarkdownV2 特殊字符未转义、实体范围不正确,或者某个标签嵌套关系不符合规范。

排查时应先记录最终发送给 Telegram 的完整文本,而不是只看业务层的原始数据。很多问题发生在模板拼接之后,只有查看最终字符串,才能确认是哪个字段破坏了消息结构。

1. MarkdownV2 中的反斜杠问题

MarkdownV2 使用反斜杠作为转义符,而在部分编程语言的字符串中,反斜杠本身也需要转义。因此源码里看到的两个反斜杠,运行后可能才会变成一个真正的反斜杠。

建议使用成熟的转义函数,并为“普通文本”“代码内容”“链接地址”分别定义规则。不要对整段已经包含 Markdown 标记的模板再次进行全量转义,否则粗体和链接很可能失效。

2. HTML 标签嵌套问题

HTML 模式中的标签必须正确闭合,动态字段不能意外截断标签。尤其是代码片段、用户昵称和接口返回的富文本,最容易包含尖括号和特殊实体。

如果业务需要更复杂的格式,可以考虑直接构造 MessageEntity。实体方式将文本和格式范围分离,在动态内容较多时更可控,但必须准确计算 offset 和 length。

🧩 五、MessageEntity 适合什么场景

MessageEntity 是 Telegram 对文本格式的结构化描述,例如指定某一段文字是 bold、italic、text_link 或 code。它不依赖 Markdown 标记,也不需要把 HTML 标签混入可见文本。

对于需要频繁组合用户输入、机器翻译结果、数据库字段和多个链接的系统,实体方式可以减少转义层级。但开发者必须注意 Telegram 实体偏移通常按照 UTF-16 code units 计算,中文、Emoji 和部分特殊字符可能让简单的字符串下标计算出现偏差。

实体化消息的核心思路:

text = "欢迎,技术用户"
entities = [
  {
    type: "bold",
    offset: 0,
    length: 2
  }
]

发送时:
text 与 entities 分开提交,不在 text 中嵌入 Markdown 或 HTML 标签。

如果团队没有成熟的 UTF-16 偏移工具,不建议手动拼接复杂实体。对于普通通知,使用 HTML 白名单或 MarkdownV2 转义器通常更容易维护。

🛡️ 六、建立可维护的安全清洗策略

安全清洗不应该只依赖前端,因为机器人可能同时接收来自 Web 表单、群组消息、Webhook 和第三方 API 的内容。所有输入都应在服务端重新验证,前端处理只能改善体验,不能代替安全边界。

推荐采用“默认拒绝、按需开放”的白名单策略:只允许业务需要的标签,只允许必要的属性,只允许安全的 URL 协议,并限制文本长度与嵌套深度。

同时,日志中应记录 Telegram 返回的错误类型、消息来源、解析模式和模板版本,但不要无条件记录用户隐私、机器人令牌或完整敏感内容。良好的日志设计有助于定位问题,也能降低数据泄露风险。

❓ 常见问题解答(FAQ)

Telegram 的 HTML 模式可以使用任意网页标签吗?

不可以。Telegram 只解析官方支持的有限标签,div、style、script、事件属性和复杂 CSS 通常不会按浏览器方式工作。发送前应根据 Bot API 规则建立允许列表。

用户输入为什么不能直接拼接到 Markdown 模板中?

因为用户输入可能包含 MarkdownV2 特殊字符,从而改变原有结构,导致解析失败或生成意外格式。动态内容必须先经过对应模式的转义,再插入模板。

HTML 和 MarkdownV2 应该优先选择哪一种?

固定模板和简单通知可以根据团队习惯选择;如果内容由大量用户输入组成,应优先考虑成熟的 HTML 清洗方案或 MessageEntity。真正重要的不是语法偏好,而是统一解析模式、正确转义并持续测试

出现解析错误时,第一步应该做什么?

首先保存并查看最终发送文本、parse_mode 和实体数据,确认问题发生在模板、动态字段还是转义函数。然后使用最小化文本逐段恢复内容,可以快速定位具体的标签或特殊字符。

总的来说,Telegram 富文本消息的稳定性取决于一套清晰的边界:模板负责格式,转义负责文本,清洗负责安全,实体负责结构化表达。只要避免混用解析模式,并在发送前统一处理动态内容,绝大多数格式错误和注入风险都可以提前消除。

telegram搜
Telegram搜索入口客服ID@TTSO联系