使用Tweepy通过Twitter API流存推文至CouchDB失败求助
问题排查与修复方案
核心问题:on_status与on_data的执行冲突
在Tweepy的StreamListener中,同时实现on_status和on_data会导致on_data不会被触发。因为Tweepy的默认逻辑是:on_data方法会解析推文数据并调用on_status,如果重写了on_status但没有在on_data中手动调用它,自定义的on_data代码永远不会执行——这就是你看不到推文打印、也没有数据存入CouchDB的直接原因。
修复方式二选一:
1. 删除on_status方法
直接移除无用的on_status,让on_data正常执行:
class StreamListener(tweepy.StreamListener): def on_error(self, status_code): print(f"Error: {status_code}") # 返回False会停止流,返回True继续(420是限流错误,建议停止) return status_code != 420 def on_data(self, data): if data[0].isdigit(): pass else: try: jdata = json.loads(data) print("Received tweet:", jdata["id_str"]) # 用推文的id_str作为CouchDB的_id,避免重复插入报错 jdata["_id"] = jdata["id_str"] db.save(jdata) print(f"Saved tweet {jdata['id_str']} to DB") except json.JSONDecodeError as e: print(f"Failed to parse JSON: {e}") except Exception as e: print(f"Error saving tweet: {e}")
2. 在on_status中处理保存逻辑
如果需要保留on_status,直接在这个方法里处理推文存储:
class StreamListener(tweepy.StreamListener): def on_status(self, tweet): print('Ran on_status') try: # 将tweet对象转为字典格式 jdata = tweet._json jdata["_id"] = jdata["id_str"] db.save(jdata) print(f"Saved tweet {jdata['id_str']} to DB") except Exception as e: print(f"Error saving tweet: {e}") def on_error(self, status_code): print(f"Error: {status_code}") return status_code != 420
其他需排查的关键点
- Twitter API权限验证:
确认你的开发者账号拥有Elevated Access,免费的Essential Access无法使用Twitter v1.1的流式API。如果使用v2 API,需要改用Tweepy的StreamingClient而非Stream。 - CouchDB操作优化:
手动指定_id为推文的id_str,避免CouchDB自动生成的ID重复导致静默失败(虽然代码有异常捕获,但明确ID更可靠)。 - 过滤词有效性:
可以临时替换filterTerms为更热门的词汇(比如["news"]),测试是否能捕获到推文,排除过滤词匹配度的问题。 - Tweepy版本兼容性:
若使用Tweepy v4.x,StreamListener已被标记为废弃,建议改用StreamingClient(针对v2 API)或Stream配合回调函数。
内容的提问来源于stack exchange,提问作者rahes
相关产品推荐
相关产品推荐

