Twitter API v2 特定推文筛选、去重及原创识别问题求解
Twitter 自动回复机器人问题修复
现有代码核心问题根因
- author_id筛选失效:循环遍历单条推文时,错误读取了
stream.data.author_id,stream.data是分页接口返回的整页数据对象,不是当前遍历到的单条推文,判断对象拿错自然筛选不生效。 - 缺少原创推文判定逻辑:没有识别推文的
referenced_tweets字段,无法区分原创、回复、转推、引用内容。 - 缺少已处理记录逻辑:没有存储已经回复过的推文ID,轮询拉取时会重复拿到历史推文,导致重复回复。
- 原代码仅执行一次拉取就结束,没有持续检测新推文的轮询/长连逻辑,无法实现实时监控。
修复逻辑说明
- 单条推文判断直接取循环变量
tweet的属性,不要从stream对象上取分页数据 - 原创推文过滤规则:如果推文存在
referenced_tweets字段,直接判定为非原创(包含回复、纯转推、引用推三类),跳过处理 - 去重逻辑:初始化一个Set集合存储已处理的推文ID,每次拿到新推文先判断ID是否已存在于集合中,存在则跳过;回复发送成功后将推文ID写入集合。如果需要程序重启后也不重复回复,可以定时把Set里的ID写入本地json文件做持久化,保留最近200条ID即可覆盖时间线拉取范围,不会占用过多存储。
- 实时检测优化:如果需要低延迟检测新推文,不要高频轮询
userTimeline接口,改用v2过滤流接口,直接订阅目标用户的新推文事件,比轮询更稳定,也不容易触发接口限流。
修复后参考代码
import { TwitterApi } from 'twitter-api-v2'; // 已处理推文ID集合,做去重用 const repliedTweetIds = new Set(); // 目标用户ID const TARGET_USER_ID = 'censored'; const client = new TwitterApi({ appKey: 'censored', appSecret: 'censored', accessToken: 'censored', accessSecret: 'censored', }); async function loop(){ // 拉取目标用户时间线 const timeline = await client.v2.userTimeline(TARGET_USER_ID,{ 'tweet.fields': ['referenced_tweets', 'author_id', 'id'], expansions: ['referenced_tweets.id'], // 每次只拉最新的10条,减少无效遍历 max_results: 10 }); for await (const tweet of timeline) { // 1. 先判断是不是目标用户发的,直接取当前遍历的tweet对象属性 if(tweet.author_id !== TARGET_USER_ID) continue; // 2. 判断是不是已经处理过的推文 if(repliedTweetIds.has(tweet.id)) continue; // 3. 判断是不是非原创推文:存在referenced_tweets字段就是回复/转推/引用推,直接跳过 if(tweet.referenced_tweets && tweet.referenced_tweets.length > 0) continue; // 走到这里就是符合要求的目标用户原创新推文,执行回复逻辑 console.log('检测到目标用户新原创推文,准备回复:', tweet.id, tweet.text); // 写入实际回复逻辑,示例: // await client.v2.reply('要回复的指定内容', tweet.id); // 回复成功后把ID加入已处理集合 repliedTweetIds.add(tweet.id); } // 轮询间隔设置30-60秒,避免触发接口限流 setTimeout(loop, 60000); } loop();
如果要做毫秒级实时推送,把轮询逻辑替换为v2过滤流即可,规则设置为
from:目标用户ID,有新推文时会直接推送到长连接,不需要定时轮询。
内容的提问来源于stack exchange,提问作者SashimiDude
相关产品推荐
相关产品推荐

