Discord.py搭建的Tweepy推特自动推送机器人启动推送旧推文如何解决
问题根源
- 未记录已推送的推文标识:Twitter每条推文都有唯一的数值ID,ID值随发布时间递增,你当前未存储已经推送过的最新推文ID,每次拉取全量时间线都会把历史内容全部推送一遍
- 触发逻辑错误:你将推文推送逻辑绑定在了
on_message事件上,只要服务器内有新消息发送,就会触发全量时间线的遍历推送,完全不符合定时拉取新增内容的需求
实现方案
你可以通过记录最新已推送的推文ID+定时轮询拉取新内容的方式实现需求,使用discord.py内置的tasks扩展做定时任务即可,修改后的参考代码如下:
import discord from discord.ext import tasks import tweepy import json # 此处保留你原有的推特API初始化、Discord客户端初始化、CHANNELID配置等内容 # 加载已记录的最新推文ID,持久化存储避免机器人重启后重复推送 def load_latest_id(): try: with open('latest_tweet_id.json', 'r') as f: return json.load(f)['latest_id'] except (FileNotFoundError, KeyError): # 首次运行无历史记录时,取最新一条推文的ID作为基线,不推送历史内容 timeline = api.home_timeline(count=1) if timeline: latest_id = timeline[0].id save_latest_id(latest_id) return latest_id return 0 # 保存最新已推送的推文ID def save_latest_id(latest_id): with open('latest_tweet_id.json', 'w') as f: json.dump({'latest_id': latest_id}, f) latest_tweet_id = load_latest_id() # 定时拉取新推文任务,此处设置为每5分钟拉取一次,可自行调整 @tasks.loop(minutes=5) async def push_new_tweets(): global latest_tweet_id channel = client.get_channel(CHANNELID) # 调用Tweepy接口仅拉取比已记录ID更新的推文 timeline = api.home_timeline(since_id=latest_tweet_id, tweet_mode="extended") # 推文默认按时间倒序返回,反转后从旧到新推送更符合阅读逻辑 for tweet in reversed(timeline): em1 = discord.Embed(title = f'New Tweet From {tweet.user.name}', description = tweet.full_text) await channel.send(embed = em1) # 更新最新已推送ID if tweet.id > latest_tweet_id: latest_tweet_id = tweet.id # 每轮拉取结束后保存最新ID save_latest_id(latest_tweet_id) # 机器人启动完成后自动启动定时任务 @client.event async def on_ready(): push_new_tweets.start() print("机器人已启动,推文推送任务运行中") # 如果你原本的on_message事件没有其他逻辑,可以直接删除,有其他逻辑的话记得补充await client.process_commands(message)避免命令被拦截
注意事项
- 轮询间隔不要设置过短,避免触发Twitter API的速率限制,免费开发者账号15分钟内最多允许调用15次home_timeline接口,设置5分钟以上的间隔比较稳妥
- 如果不需要持久化存储(允许机器人重启后推送重启期间的新内容,或接受重启后首次运行只推送之后的新内容),可以去掉读写JSON文件的逻辑,仅维护全局变量
latest_tweet_id即可
内容的提问来源于stack exchange,提问作者Good Grief
相关产品推荐
相关产品推荐

