Python3调用Telegram API使用MarkdownV2转义后符号异常问题
问题
在Python3中调用Telegram API并使用MarkdownV2解析模式时,对文本中的-、(、)用\转义后,发送到Telegram的消息里仅-对应的转义符\会被显示,括号的转义符则正常隐藏,不符合预期。
代码示例及现象
原始实现代码:
def telegramNotification(message): TOKEN = "xxx:AAGrrzwEJ0Pxxxxs6h5pv0tYo9n-4" chat_id = -629454 message = message.replace("-","\\\\-") url = f"https://api.telegram.org/bot{TOKEN}/sendMessage?chat_id={chat_id}&text={message}&parse_mode=MarkdownV2" http = urllib3.PoolManager(timeout=5.0) resp = http.request('GET', url) respMsg = json.loads(resp.data.decode('utf-8')) print(respMsg) if respMsg["ok"]: print("This is ok") telegramNotification('test\-for\-now and \(pharantesis\)')
尝试过的转义处理:
msg = "test-for-now and (stackoverflow)" newmsg = msg.replace("-","\\-")\ .replace("(","\\(") \ .replace(")","\\)") print(newmsg) # 输出:test\-for\-now and \(stackoverflow\) telegramNotification(newmsg)
两种方式都会导致Telegram消息显示为test\-for\-now and (stackoverflow),-的转义符无法被正确识别隐藏。
原因分析
- URL编码干扰:使用GET请求时,查询参数会被自动URL编码,
\会被编码为%5C。Telegram接收到后还原为\,但普通文本中的-不属于MarkdownV2必须转义的特殊字符,因此这个\会被当作普通字符显示;而(和)是MarkdownV2的特殊语法字符,Telegram会识别\(为转义后的(,所以不会显示转义符。 - 转义层级错误:GET请求的URL参数中,要让Telegram收到有效的转义符
\,需要经过Python字符串转义+URL编码的双重转义,这种多层处理极易出错,且不符合MarkdownV2的实际转义逻辑。
解决方案
方案1:改用POST请求传递参数(推荐)
将消息内容放在请求体中,避免URL编码干扰,同时按MarkdownV2规则统一转义所有特殊字符:
import urllib3 import json def telegramNotification(message): TOKEN = "xxx:AAGrrzwEJ0Pxxxxs6h5pv0tYo9n-4" chat_id = -629454 # MarkdownV2需要转义的特殊字符集合 escape_chars = r'_*[]()~`>#+-=|{}.!' for char in escape_chars: message = message.replace(char, f'\\{char}') url = f"https://api.telegram.org/bot{TOKEN}/sendMessage" http = urllib3.PoolManager(timeout=5.0) # 以JSON格式发送POST请求 resp = http.request( 'POST', url, headers={'Content-Type': 'application/json'}, body=json.dumps({ 'chat_id': chat_id, 'text': message, 'parse_mode': 'MarkdownV2' }) ) respMsg = json.loads(resp.data.decode('utf-8')) print(respMsg) if respMsg["ok"]: print("消息发送成功") telegramNotification('test-for-now and (stackoverflow)')
方案2:GET请求下手动处理URL编码
如果坚持使用GET请求,需对转义后的消息做URL编码,确保转义符被正确传递:
import urllib3 import json from urllib.parse import quote def telegramNotification(message): TOKEN = "xxx:AAGrrzwEJ0Pxxxxs6h5pv0tYo9n-4" chat_id = -629454 escape_chars = r'_*[]()~`>#+-=|{}.!' for char in escape_chars: message = message.replace(char, f'\\{char}') # 对消息进行URL编码 encoded_message = quote(message) url = f"https://api.telegram.org/bot{TOKEN}/sendMessage?chat_id={chat_id}&text={encoded_message}&parse_mode=MarkdownV2" http = urllib3.PoolManager(timeout=5.0) resp = http.request('GET', url) respMsg = json.loads(resp.data.decode('utf-8')) print(respMsg) if respMsg["ok"]: print("消息发送成功") telegramNotification('test-for-now and (stackoverflow)')
关键说明
MarkdownV2仅要求转义具有特殊语法意义的字符,统一转义所有特殊字符是最稳妥的处理方式。使用POST请求传递JSON参数是Telegram API官方推荐的方式,能彻底避免URL编码带来的转义问题。
内容的提问来源于stack exchange,提问作者Faruk Gul
相关产品推荐
相关产品推荐

