Twitter API timeline()返回生成器长度获取失败及全量推文拉取问题
问题原因解答
1. 生成器为空的原因
你的判断是正确的,alltweets.extend(new_tweets)操作已经完整迭代了生成器的所有元素,Python生成器是一次性可迭代对象,迭代完成后就会清空,后续任何遍历操作都会返回空值,这也是你后续len(dict(new_tweets))、转列表操作都返回空的核心原因。
2. 判断是否还有未拉取推文的方法
不需要直接统计生成器长度,你可以在每次调用timeline接口后,先将生成器转为列表存储,直接判断列表长度即可:
- 既可以避免生成器被单次消耗后无法校验的问题
- 也可以直接用列表长度判断是否还有返回数据
另外你也可以通过返回结果里的meta字段判断:每次拉取的结果中如果next_token字段存在,说明还有更多推文可以拉取,不需要依赖生成器长度校验。
3. 合并为单行while语句的实现
Python 3.8及以上版本可以用海象运算符:=实现需求,直接在while判断中完成赋值和非空校验:
while someList := list(new_tweets): # 循环内直接处理someList即可
修正后的完整代码参考
def get_all_tweets(user_id, DEBUG): # Your bearer token here t = Twarc2(bearer_token="blah") # Initialize a list to hold all the tweepy Tweets alltweets = [] if DEBUG: # Debug: read from file with open('tweets_debug.txt', 'r') as f: new_tweets = json.load(f) alltweets.extend(new_tweets) else: # 首次拉取直接转列表,避免生成器消耗问题 new_tweets = list(t.timeline(user=user_id)) alltweets.extend(new_tweets) if DEBUG: # Debug: write to file with open("tweets_debug.txt", "w") as f: f.write(json.dumps(alltweets, indent=2, sort_keys=False)) # 首次拉取为空直接返回 if not alltweets: return [] # Save the id of the oldest tweet less one oldest = str(int(alltweets[-1]['meta']['oldest_id']) - 1) # 用海象运算符合并赋值和判断逻辑 while new_tweets := list(t.timeline(user=user_id, until_id=oldest)): print(f"getting tweets before {oldest}") # 直接用已经转成列表的new_tweets,不需要重复迭代生成器 alltweets.extend(new_tweets) # Update the id of the oldest tweet less one oldest = str(int(alltweets[-1]['meta']['oldest_id']) - 1) print(f"...{len(alltweets)} tweets downloaded so far") res = [] for tweetlist in alltweets: res.extend(tweetlist['data']) with open("output.txt", "w") as f: f.write(json.dumps(res, indent=2, sort_keys=False)) return res
内容的提问来源于stack exchange,提问作者TaihouKai
相关产品推荐
相关产品推荐

