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

Python3.9使用Telebot开发Telegram新闻机器人如何实现交互按钮菜单

Python 3.9 + Telebot 交互式新闻菜单完整实现

前置准备

  • 安装兼容Python 3.9的Telebot稳定版本:pip install pyTelegramBotAPI==4.14.0
  • 从@BotFather获取机器人Token,提前关闭群组隐私模式,确保可正常接收按钮回调事件

完整可运行代码

以下代码实现了多层级交互菜单逻辑,包含主菜单、分类列表、新闻详情三级跳转,全程无刷屏,所有交互通过编辑原消息完成:

import telebot
from telebot import types

# 替换为你自己的机器人Token
BOT_TOKEN = "YOUR_BOT_TOKEN_HERE"
bot = telebot.TeleBot(BOT_TOKEN)

# 模拟新闻数据源,实际使用可替换为你的爬虫/API接口返回内容
NEWS_DATA = {
    "tech": [
        {"id": 1, "title": "Python 3.13 性能提升30%", "content": "官方测试数据显示,3.13版本启用JIT编译后,基准测试性能较3.12提升约30%,通用计算场景响应速度明显加快。"},
        {"id": 2, "title": "Telegram Bot API 新增付费媒体接口", "content": "最新版Bot API支持机器人发送付费媒体内容,创作者可直接通过机器人设置付费订阅规则,无需跳转第三方平台。"}
    ],
    "finance": [
        {"id": 3, "title": "A股三大指数集体收涨", "content": "今日沪指涨1.2%,深成指涨1.8%,创业板指涨2.1%,半导体、新能源板块领涨,两市成交额突破1.2万亿。"},
        {"id": 4, "title": "多国央行宣布降息", "content": "本周已有3个新兴市场国家宣布下调基准利率25个基点,市场预期全球降息周期将在三季度全面开启。"}
    ],
    "sport": [
        {"id": 5, "title": "国足世预赛1-1战平泰国", "content": "世预赛亚洲区36强赛最后一轮,国足客场1-1战平泰国,以成绩最好的小组第二身份晋级18强赛。"},
        {"id": 6, "title": "NBA总决赛G3凯尔特人胜独行侠", "content": "总决赛第三场凯尔特人客场106-99击败独行侠,大比分2-1领先,杰伦·布朗砍下30分当选全场最佳。"}
    ]
}
CATEGORY_NAME_MAP = {"tech": "科技新闻", "finance": "财经新闻", "sport": "体育新闻"}

# 生成主菜单内嵌按钮
def build_main_menu_keyboard():
    keyboard = types.InlineKeyboardMarkup(row_width=2)
    btn_tech = types.InlineKeyboardButton("📱 科技新闻", callback_data="cat_tech")
    btn_finance = types.InlineKeyboardButton("💰 财经新闻", callback_data="cat_finance")
    btn_sport = types.InlineKeyboardButton("⚽ 体育新闻", callback_data="cat_sport")
    btn_latest = types.InlineKeyboardButton("🔥 最新推送", callback_data="latest")
    btn_about = types.InlineKeyboardButton("ℹ️ 关于机器人", callback_data="about")
    keyboard.add(btn_tech, btn_finance, btn_sport, btn_latest, btn_about)
    return keyboard

# 生成分类新闻列表按钮
def build_category_keyboard(category_key):
    keyboard = types.InlineKeyboardMarkup(row_width=1)
    for news_item in NEWS_DATA[category_key]:
        keyboard.add(types.InlineKeyboardButton(
            text=news_item["title"],
            callback_data=f"news_{category_key}_{news_item['id']}"
        ))
    keyboard.add(types.InlineKeyboardButton("⬅️ 返回主菜单", callback_data="main_menu"))
    return keyboard

# 生成新闻详情页功能按钮
def build_news_detail_keyboard(category_key):
    keyboard = types.InlineKeyboardMarkup(row_width=2)
    btn_back_cat = types.InlineKeyboardButton("⬅️ 返回分类", callback_data=f"cat_{category_key}")
    btn_back_main = types.InlineKeyboardButton("🏠 返回主菜单", callback_data="main_menu")
    keyboard.add(btn_back_cat, btn_back_main)
    return keyboard

# 处理/start启动指令
@bot.message_handler(commands=['start'])
def send_welcome(message):
    bot.send_message(
        chat_id=message.chat.id,
        text="👋 欢迎使用新闻机器人,请选择你想浏览的内容分类:",
        reply_markup=build_main_menu_keyboard()
    )

# 统一处理所有按钮点击回调
@bot.callback_query_handler(func=lambda call: True)
def handle_button_click(call):
    # 必须调用该方法响应回调,否则客户端会一直显示加载状态
    bot.answer_callback_query(call.id)
    cb_data = call.data

    # 回到主菜单逻辑
    if cb_data == "main_menu":
        bot.edit_message_text(
            chat_id=call.message.chat.id,
            message_id=call.message.message_id,
            text="👋 欢迎使用新闻机器人,请选择你想浏览的内容分类:",
            reply_markup=build_main_menu_keyboard()
        )
        return

    # 进入分类列表逻辑
    if cb_data.startswith("cat_"):
        cat_key = cb_data.split("_")[1]
        cat_name = CATEGORY_NAME_MAP[cat_key]
        bot.edit_message_text(
            chat_id=call.message.chat.id,
            message_id=call.message.message_id,
            text=f"📂 当前分类:{cat_name}\n请选择你要查看的新闻:",
            reply_markup=build_category_keyboard(cat_key)
        )
        return

    # 打开新闻详情逻辑
    if cb_data.startswith("news_"):
        _, cat_key, news_id = cb_data.split("_")
        news_id = int(news_id)
        target_news = next(item for item in NEWS_DATA[cat_key] if item["id"] == news_id)
        content = f"📰 *{target_news['title']}*\n\n{target_news['content']}"
        bot.edit_message_text(
            chat_id=call.message.chat.id,
            message_id=call.message.message_id,
            text=content,
            parse_mode="Markdown",
            reply_markup=build_news_detail_keyboard(cat_key)
        )
        return

    # 最新推送逻辑
    if cb_data == "latest":
        latest_item = NEWS_DATA["tech"][0]
        content = f"🔥 *最新推送*\n\n*{latest_item['title']}*\n{latest_item['content']}"
        bot.edit_message_text(
            chat_id=call.message.chat.id,
            message_id=call.message.message_id,
            text=content,
            parse_mode="Markdown",
            reply_markup=build_main_menu_keyboard()
        )
        return

    # 关于页逻辑
    if cb_data == "about":
        about_content = "ℹ️ *关于本机器人*\n基于Python 3.9 + Telebot开发的新闻交互机器人,支持分类浏览、多级菜单导航。"
        bot.edit_message_text(
            chat_id=call.message.chat.id,
            message_id=call.message.message_id,
            text=about_content,
            parse_mode="Markdown",
            reply_markup=build_main_menu_keyboard()
        )
        return

if __name__ == "__main__":
    print("机器人启动成功")
    bot.infinity_polling()

常见问题排查

  • 按钮消息发送失败:检查是否误用ReplyKeyboardMarkup,消息内嵌的交互按钮必须使用InlineKeyboardMarkup类生成,作为reply_markup参数传入消息发送方法
  • 按钮点击后持续加载:必须在回调处理逻辑第一行调用bot.answer_callback_query(call.id)响应Telegram的回调请求
  • 回调匹配失效:检查callback_data是否重复、长度是否超过64字节限制,不要在callback_data中存储大段文本,仅保留路由标识和数据ID即可
  • 群组内按钮无响应:前往@BotFather找到对应机器人,进入Bot Settings -> Group Privacy选项,设置为Turn off,允许机器人接收群内消息和回调事件

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 01:51:43