在Telegram Bot开发中,接收用户消息和交互请求是构建一切功能的基础。Telegram Bot API提供了两种获取更新的方式:短轮询(Short Polling)和长轮询(Long Polling)。尽管长轮询在现代开发中更常见,但理解短轮询的原理与实现,能让你更深刻地把握Bot的工作机制,并成为构建高效、稳定Bot的基石。本文将从零开始,手把手教你使用短轮询方式接收Telegram Bot的更新。
什么是短轮询?与长轮询的区别
短轮询是指客户端(你的Bot服务器)反复向Telegram服务器发送HTTP请求,询问是否有新的更新。每次请求都会立即得到响应——如果有更新,返回数据;如果没有,则返回空列表。长轮询则是在请求中设置timeout参数,Telegram服务器会保持连接直到有更新或超时才返回,从而减少无效请求。
短轮询的特点:
- 实现简单:无需考虑长连接和超时机制。
- 延迟相对较高:取决于轮询间隔。
- 消耗更多资源:频繁请求可能触发速率限制。
尽管如此,短轮询在开发调试、低流量场景或需要完全控制请求节奏时依然有实用价值。学习它也能帮助你更好地理解偏移量(offset)和更新确认机制。
开发环境准备
在编写代码前,你需要完成以下准备工作:
- 创建Bot并获取Token:在Telegram中与@BotFather对话,使用
/newbot命令创建一个新机器人,获得形如123456789:ABCdefGHI...的API Token。 - 选择开发语言和库:你可以使用任何支持HTTP请求的语言。作为示例,我们使用Python(requests库)和Node.js(axios)展示两种常见实现。
- 了解getUpdates方法:这是轮询的核心API,文档位于
https://api.telegram.org/bot<token>/getUpdates。
getUpdates方法参数详解
getUpdates接受以下可选参数:
| 参数 | 类型 | 说明 |
|---|---|---|
| offset | Integer | 第一个待确认更新的标识符。用于避免重复处理。 |
| limit | Integer | 每次最多返回的更新数量,1-100,默认100。 |
| timeout | Integer | 长轮询超时秒数。短轮询通常设为0或不设置。 |
| allowed_updates | Array | 指定要接收的更新类型,如["message","callback_query"]。 |
在短轮询模式下,我们不设置timeout(或设为0),请求立即返回。
使用短轮询获取更新的代码示例
Python实现(requests)
import requests
TOKEN = "你的BOT_TOKEN"
URL = f"https://api.telegram.org/bot/getUpdates"
def get_updates(offset=0):
params = {"offset": offset, "timeout": 0}
response = requests.get(URL, params=params)
return response.json()
# 简单轮询循环
offset = 0
while True:
data = get_updates(offset)
for update in data.get("result", []):
print(update)
offset = update["update_id"] + 1
Node.js实现(axios)
const axios = require('axios');
const TOKEN = '你的BOT_TOKEN';
const URL = `https://api.telegram.org/bot$/getUpdates`;
async function getUpdates(offset = 0) {
const { data } = await axios.get(URL, { params: { offset, timeout: 0 } });
return data;
}
let offset = 0;
(async function startPolling() {
while (true) {
const data = await getUpdates(offset);
for (const update of data.result || []) {
console.log(update);
offset = update.update_id + 1;
}
}
})();
上述代码中,每轮请求后我们更新offset为最新update_id + 1,确保Telegram服务器确认这些更新已被处理,下次不再返回。
处理更新数据
返回的result是一个更新对象数组。每个Update包含固定的update_id,以及根据更新类型不同的其他字段,常见的包括:
message:新的普通消息,包含message_id、from(发送者)、chat(会话)、text(文本)等。edited_message:消息被编辑。channel_post:频道新帖子。callback_query:按钮回调请求。
开发时可以根据实际业务需要,对不同类型的更新进行分派处理。例如:
if "message" in update:
chat_id = update["message"]["chat"]["id"]
text = update["message"].get("text", "")
# 回复“收到”
requests.post(f"https://api.telegram.org/bot/sendMessage", json={"chat_id": chat_id, "text": "收到:" + text})
轮询循环与错误处理
实际部署时,直接无限循环存在风险——网络异常、Telegram API限制等都会导致崩溃。因此需要加入错误处理:
import time
while True:
try:
data = get_updates(offset)
if data.get("ok"):
for update in data["result"]:
process_update(update)
offset = update["update_id"] + 1
except Exception as e:
print(f"请求出错: ")
time.sleep(1)
特别要注意409 Conflict错误:当多个实例同时使用同一个Bot的getUpdates时会出现。确保同一时间只有一个轮询进程在运行。
另外,若请求过于频繁,可能收到429 Too Many Requests或retry_after字段。此时应等待指定时间再继续。
最佳实践与实用建议
- 始终使用offset:每次处理完更新后,立即更新offset并保存,以防崩溃导致重复或丢失。
- 设置合理的polling间隔:短轮询典型间隔为1-2秒。过短会骚扰服务器,过长则延迟高。若需要实时响应,建议升级为长轮询(设置
timeout为30-50秒)。 - 使用allowed_updates过滤:只接收你关心的更新,减少带宽和处理压力。
- 代码结构模块化:将轮询逻辑与业务处理分离,方便后续维护和扩展。
- 使用Webhook替代:对于生产环境,更推荐Webhook模式——Telegram主动推送更新到你的HTTPS端点,效率更高。但短轮询和长轮询依然是本地开发和测试的好选择。
总结
通过本文的学习,你已经掌握了Telegram Bot短轮询接收更新的完整流程。虽然短轮询并非最高效的方案,但它清晰展示了getUpdates的核心机制——offset确认、更新对象解析和循环处理。理解这些概念后,你再转向长轮询或Webhook,将发现它们只是参数和网络模型上的变体。现在,启动你的第一个Bot,用短轮询亲手接收一条消息吧!