You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Telegram API调用遇Bad Request错误,内嵌链接发送失败求解决

解决Telegram API发送内嵌链接时的Bad Request错误

问题根源分析

你遇到的Bad Request: can't parse inline keyboard Markup Json object错误,主要由以下代码问题导致:

1. 链接变量引用错误

代码中把链接变量link_写成了字符串字面量"link_",这会导致Telegram API收到无效URL,同时破坏JSON结构的合法性。

2. Reply Markup未序列化为JSON字符串

Telegram API要求reply_markup参数必须是JSON格式的字符串,直接传递Python字典会导致API无法正确解析。

3. 循环内键盘结构重复累加

在循环中每次都往inline_keyboard列表添加按钮,导致后续消息的键盘包含之前所有新闻的按钮,不符合单条消息对应单个按钮的预期。

4. 代码缩进错误

try块的缩进不正确,会引发语法错误,导致代码逻辑异常。

5. MarkdownV2特殊字符未转义

使用parse_mode: MarkdownV2时,caption中的特殊字符(如_、*、[等)需要转义,否则会触发格式错误。


修复后的完整代码

import requests
from bs4 import BeautifulSoup
import json

NEWS_URL = "https://www.iflscience.com/latest"
TELEGRAM_API_URL = f"https://api.telegram.org/bot{TELEGRAM_TOKEN}/"
CHAT_ID = "你的聊天ID"  # 替换为实际聊天ID
headers = {}  # 补充你的请求头

def scrape_science_news():
    response = requests.get(url=NEWS_URL, headers=headers)

    if response.status_code == 200:
        soup = BeautifulSoup(response.content, "html.parser")
        news_items = []
        card_list = soup.find_all("div", attrs={"class": "card list-card"})

        for card in card_list[:3]:
            card_tbn = card.find("div", attrs={"class": "card-thumbnail"})
            card_img = card_tbn.picture.source.next_element.attrs["srcset"]

            card_content_h = card.find("div", attrs={"class": "card-content--header"})
            card_header = card_content_h.a.span.string

            card_content_b = card.find("div", attrs={"class": "card-content--body"})
            card_title = card_content_b.a.h3.string

            card_link_h = card_content_b.a.attrs["href"]
  
            news_items.append({
                "card_img": card_img,
                "card_header": card_header,
                "card_title": card_title,
                "card_link": card_link_h
            })

        return news_items

def escape_markdown_v2(text):
    """转义MarkdownV2的特殊字符"""
    special_chars = r'\_*[]()~`>#+-=|{}.!'
    return ''.join(f'\\{c}' if c in special_chars else c for c in text)

def send_news_to_telegram(news_items):
    for item in news_items:
        img_ = item["card_img"]
        header_ = item["card_header"]
        title_ = item["card_title"]
        link_ = item["card_link"]
        
        # 每条消息单独创建键盘,避免累加
        inline_keyboard = [
            [{"text": title_, "url": link_}]
        ]
        inline_keyboard_markup = json.dumps({"inline_keyboard": inline_keyboard})

        # 转义caption中的特殊字符
        message = f"{escape_markdown_v2(header_)}\n\n"
        
        try:
            news = {
                "photo": img_,
                "caption": message,
                "parse_mode": "MarkdownV2",
                "reply_markup": inline_keyboard_markup,
                "disable_web_page_preview": True,
                "chat_id": CHAT_ID
            }

            response = requests.post(TELEGRAM_API_URL + "sendPhoto", data=news)

            if response.status_code == 200:
                with open("islog.txt", 'a') as file:
                    file.write(f"{title_}\n")
            else:
                print(response.text)

        except UnicodeError:
            pass

def main():
    news_items = scrape_science_news()
    send_news_to_telegram(news_items)

if __name__ == "__main__":
    main()

关键修复说明

  1. 修正链接变量:将"url": "link_"改为"url": link_,正确引用实际链接。
  2. 序列化Reply Markup:使用json.dumps()将键盘字典转换为JSON字符串,符合API要求。
  3. 独立构建键盘:在循环内为每条消息单独创建inline_keyboard列表,避免按钮累加。
  4. 修复缩进错误:调整try块的缩进,确保代码语法正确。
  5. 添加MarkdownV2转义:新增escape_markdown_v2函数,转义caption中的特殊字符,避免格式错误。

内容的提问来源于stack exchange,提问作者Bolarin Samuel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 00:06:26