如何通过Python Telegram Bot库获取聊天历史?连接池超时问题及实现可行性咨询
如何通过Python Telegram Bot库获取聊天历史?连接池超时问题及实现可行性咨询
嘿,我来帮你捋清楚这个问题。首先直接给你结论:机器人是可以获取聊天历史的,但你当前的做法有两个核心问题:用错了API,连接池的使用方式也不对,才导致了超时错误。
先说说你遇到的TimedOut错误为什么会发生:
你在handler里直接调用了update._bot.get_updates(),这里有两个明显的坑:
- 首先
update._bot是库的内部对象,不应该直接调用,正确的做法是用context.bot来获取Bot实例; - 其次,你的Application已经在运行
run_polling()了,这个操作本身会占用连接池里的连接,你又在handler里额外发起API请求,直接把20个连接池资源耗尽了,自然就触发了超时。调大连接池尺寸(比如改成30)能临时缓解,但这不是根本解决办法——因为你用错了获取历史的API。
正确获取聊天历史的方式
get_updates()这个方法是用来拉取未被机器人处理过的新更新的,不是用来查询旧历史的。Telegram服务器只会保留最近24小时左右的未处理更新,如果你已经用polling处理过这些消息,get_updates()根本拿不到。要获取真正的历史消息,你应该用get_chat_history()方法(针对python-telegram-bot v20+版本)。
给你改一下你代码里的关键部分:
async def menu_callback(update: Update, context: ContextTypes.DEFAULT_TYPE): client = await get_client(update) logger.error(client.stage) match client.stage: case Stage.some_stage: logger.error(update.message.text) logger.error(update.message) # 替换掉原来的get_updates,用正确的方式拿历史 chat_id = update.effective_chat.id try: # 获取最近10条聊天历史,你可以调整limit的数值(最大支持100) chat_history = await context.bot.get_chat_history(chat_id=chat_id, limit=10) for msg in chat_history: logger.error(f"历史消息ID: {msg.message_id}, 内容: {msg.text}") except Exception as e: logger.error(f"获取历史失败: {str(e)}") last_update_id = update.update_id # 你的其他逻辑...
一些重要的注意点
- 权限要求:机器人必须在目标聊天里(私人聊天要和用户聊过,群组里机器人必须是成员),而且要有读取消息的权限;
- 批量获取更多历史:如果需要超过100条的历史,你可以循环调用
get_chat_history,每次把offset_id设为上一次获取的最后一条消息的ID减1,直到返回的消息为空; - 避免速率限制:不要在短时间内发起大量历史查询请求,Telegram对机器人的API调用频率有限制;
- 连接池优化:如果你确实需要在handler里发起多个API请求,可以在创建Application时适当调大连接池尺寸,同时设置pool_timeout,比如:
self.application = ApplicationBuilder().token(self.token)\ .connection_pool_size(30)\ .pool_timeout(15)\ .build()
最后再明确可行性
完全可以通过Python Telegram Bot库获取聊天历史,但有两个小限制:
- 只能获取机器人参与过的聊天的历史;
- 太古老的消息可能拿不到,因为Telegram服务器不会永久保存所有历史,不过近期的消息(比如几个月内的)一般都能拿到。
内容来源于stack exchange




