如何通过Python的python-telegram-bot库实现Telegram机器人追踪用户实时位置?
解决python-telegram-bot实时追踪用户位置的问题
我来帮你搞定这个位置追踪的问题——你用bot.get_updates()的思路其实不太对,咱们换个符合Telegram Bot逻辑的正确方式来实现:
为什么你的代码拿不到updates?
- 如果你的Bot是用webhook模式运行的,
bot.get_updates()会直接返回空,因为webhook模式下消息是通过HTTP请求推送到你的服务器,不会存在本地的updates队列里 - 就算是polling模式,
get_updates也只能拿到还没被updater处理过的旧消息,而Job Queue重复调用时,之前的updates早就被消费完了,所以结果为空 - 更关键的是:Telegram Bot无法主动“抓取”用户位置,只能由用户主动发送,或者通过Bot请求用户共享实时位置
正确的实现步骤
我们可以分三步实现每1分钟追踪用户位置:
- 让用户通过按钮共享实时持续更新的位置
- 接收并保存用户发送的最新位置
- 用Job Queue定时读取保存的位置数据
完整代码示例
from telegram import ReplyKeyboardMarkup, KeyboardButton from telegram.ext import Updater, CommandHandler, MessageHandler, Filters, CallbackContext # 启动命令:发送请求实时位置的按钮 def start(update, context): # 创建请求实时位置的按钮,request_live_period设置为60表示持续60秒自动发送位置 location_button = KeyboardButton( "共享实时位置", request_location=True, request_live_period=60 ) reply_markup = ReplyKeyboardMarkup([[location_button]], one_time_keyboard=True) update.message.reply_text("请点击下方按钮共享你的实时位置:", reply_markup=reply_markup) # 处理用户发送的位置消息,保存到user_data中 def handle_location(update, context): user_location = update.message.location user_id = update.effective_user.id # 将最新位置存入user_data(内置会话存储,临时保存用户数据) context.user_data['latest_location'] = { 'latitude': user_location.latitude, 'longitude': user_location.longitude, 'update_time': update.message.date.strftime("%Y-%m-%d %H:%M:%S") } update.message.reply_text("已获取你的位置,现在开始每1分钟追踪一次!") # 定时任务:每分钟读取并打印用户最新位置 def track_user_location(context: CallbackContext): job_context = context.job user_id = job_context.context # 从任务上下文获取目标用户ID # 从user_data中取出该用户的最新位置 user_data = context.dispatcher.user_data.get(user_id, {}) latest_loc = user_data.get('latest_location') if latest_loc: print(f"用户[{user_id}]的最新位置:") print(f"纬度: {latest_loc['latitude']}, 经度: {latest_loc['longitude']}") print(f"更新时间: {latest_loc['update_time']}\n") else: print(f"用户[{user_id}]尚未共享任何位置\n") # 启动追踪的命令 def start_tracking(update, context): user_id = update.effective_user.id # 检查是否已有追踪任务在运行 if 'tracking_job' in context.user_data: update.message.reply_text("已经在追踪你的位置啦!") return # 每分钟执行一次追踪任务,context传入用户ID tracking_job = context.job_queue.run_repeating( track_user_location, interval=60, # 间隔60秒 first=0, # 立即执行第一次 context=user_id ) context.user_data['tracking_job'] = tracking_job update.message.reply_text("已启动每1分钟一次的位置追踪!") # 停止追踪的命令 def stop_tracking(update, context): tracking_job = context.user_data.get('tracking_job') if tracking_job: tracking_job.schedule_removal() del context.user_data['tracking_job'] update.message.reply_text("已停止位置追踪") else: update.message.reply_text("当前没有在进行位置追踪哦") def main(): # 替换成你的Bot Token BOT_TOKEN = "YOUR_TELEGRAM_BOT_TOKEN" updater = Updater(BOT_TOKEN) dp = updater.dispatcher # 注册命令和消息处理器 dp.add_handler(CommandHandler("start", start)) dp.add_handler(CommandHandler("track", start_tracking)) dp.add_handler(CommandHandler("stop", stop_tracking)) dp.add_handler(MessageHandler(Filters.location, handle_location)) # 启动Polling模式(测试用,生产环境建议用Webhook) updater.start_polling() updater.idle() if __name__ == "__main__": main()
关键细节说明
request_live_period参数:设置这个参数后,用户点击按钮后,Telegram会在指定时长内(比如示例中的60秒)自动持续发送用户的实时位置到Bot,这样我们就能拿到连续的位置数据user_data存储:这是python-telegram-bot提供的内置会话存储,用来临时保存每个用户的位置数据;如果需要持久化存储(比如重启Bot后不丢失数据),可以改用SQLite、MySQL等数据库- Job Queue的上下文传递:我们把用户ID传入Job的context,这样定时任务就能精准对应到每个用户的位置数据
- 避免使用
bot.get_updates():无论是Polling还是Webhook模式,都应该通过官方提供的Handler来处理消息,get_updates只适合非常简单的测试场景,不适合实际开发
内容的提问来源于stack exchange,提问作者Pavlo Zub
相关产品推荐
相关产品推荐

