使用Python获取Twitter数据时出现"IncompleteRead"错误
在用 Python 2.7.8 运行这个程序来获取 Twitter 数据的时候:
#imports
from tweepy import Stream
from tweepy import OAuthHandler
from tweepy.streaming import StreamListener
#setting up the keys
consumer_key = '…………...'
consumer_secret = '………...'
access_token = '…………...'
access_secret = '……………..'
class TweetListener(StreamListener):
# A listener handles tweets are the received from the stream.
#This is a basic listener that just prints received tweets to standard output
def on_data(self, data):
print (data)
return True
def on_error(self, status):
print (status)
#printing all the tweets to the standard output
auth = OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_secret)
stream = Stream(auth, TweetListener())
t = u"سوريا"
stream.filter(track=[t])
我运行这个程序已经 5 个小时了,结果出现了这个错误信息:
Traceback (most recent call last):
File "/Users/Mona/Desktop/twitter.py", line 32, in <module>
stream.filter(track=[t])
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/tweepy/streaming.py", line 316, in filter
self._start(async)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/tweepy/streaming.py", line 237, in _start
self._run()
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/tweepy/streaming.py", line 173, in _run
self._read_loop(resp)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/tweepy/streaming.py", line 225, in _read_loop
next_status_obj = resp.read( int(delimited_string) )
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/httplib.py", line 543, in read
return self._read_chunked(amt)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/httplib.py", line 612, in _read_chunked
value.append(self._safe_read(chunk_left))
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/httplib.py", line 660, in _safe_read
raise IncompleteRead(''.join(s), amt)
IncompleteRead: IncompleteRead(0 bytes read, 976 more expected)
>>>
其实我不知道该怎么解决这个问题!!!
5 个回答
对我来说,那个网址指向的后端应用直接返回了一个字符串。
我把它改成了
return Response(response=original_message, status=200, content_type='application/text')
一开始我只是返回了一些文本,比如
return original_message
我觉得这个答案只适合我的情况。
一种解决办法是在捕捉到异常后立即重新启动流。
# imports
from tweepy import Stream
from tweepy import OAuthHandler
from tweepy.streaming import StreamListener
# setting up the keys
consumer_key = "XXXXX"
consumer_secret = "XXXXX"
access_token = "XXXXXX"
access_secret = "XXXXX"
# printing all the tweets to the standard output
auth = OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_secret)
class TweetListener(StreamListener):
# A listener handles tweets are the received from the stream.
# This is a basic listener that just prints received tweets to standard output
def on_data(self, data):
print(data)
return True
def on_exception(self, exception):
print('exception', exception)
start_stream()
def on_error(self, status):
print(status)
def start_stream():
stream = Stream(auth, TweetListener())
t = u"سوريا"
stream.filter(track=[t])
start_stream()
这个对我有效。
l = StdOutListener()
auth = OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)
stream = Stream(auth, l)
while True:
try:
stream.filter(track=['python', 'java'], stall_warnings=True)
except (ProtocolError, AttributeError):
continue
我刚遇到这个问题。之前的回答在事实方面是正确的,基本上可以归结为:
- 你的程序跟不上数据流
- 如果是这样,你会收到一个停滞警告。
在我的情况下,我是把推文读入Postgres数据库,以便后续分析,覆盖了一个相当密集的地理区域,还有一些关键词(实际上是伦敦,大约100个关键词)。即使你只是打印这些推文,你的本地机器可能还在做其他事情,系统进程会优先处理,所以推文会堆积,直到Twitter把你断开连接。(这通常表现为明显的内存泄漏——程序的大小不断增加,直到被杀掉,或者Twitter断开连接——哪个先发生就看运气了。)
在这种情况下,合理的做法是把处理工作推到一个队列里。所以,我使用了Redis和Django-RQ的解决方案——在开发和生产服务器上实现这个大约花了3个小时,包括研究、安装、调整现有代码、在安装过程中犯傻、测试,以及拼写错误。
- 在你的机器上安装Redis
- 启动Redis服务器
- 安装Django-RQ(如果你只用Python工作,可以直接安装RQ)
现在,在你的Django目录下(具体位置视情况而定,对于纯Python应用可能有所不同),运行:
python manage.py rqworker &
你现在有了一个队列!你可以通过修改处理程序来添加任务,像这样: (在文件顶部)
import django_rq
然后在你的处理程序部分:
def on_data(self, data):
django_rq.enqueue(print, data)
return True
顺便说一下,如果你对来自叙利亚的内容感兴趣,而不仅仅是提到叙利亚,你可以像这样添加过滤器:
stream.filter(track=[t], locations=[35.6626, 32.7930, 42.4302, 37.2182]
这是一个非常粗略的地理框,中心在叙利亚,但会在边缘捕捉到一些伊拉克/土耳其的内容。由于这是一个可选的附加功能,值得指出:
边界框不会作为其他过滤参数的过滤器。例如,track=twitter&locations=-122.75,36.8,-121.75,37.8将匹配任何包含“Twitter”这个词的推文(即使是非地理推文)或来自旧金山地区的推文。
这个回答对我有帮助,还有Twitter的文档。
补充:我看到你后来的帖子里,你还是在使用Twitter API的路上,所以希望你已经解决了这个问题,不过希望这对其他人也有用! :)
你应该检查一下,自己处理推文的速度是否够快,可以使用stall_warnings
这个参数来帮助你。
stream.filter(track=[t], stall_warnings=True)
这些信息是由Tweepy处理的(具体实现可以在这里查看),它会告诉你是否跟不上推文的速度。跟不上意味着你处理推文的速度比Twitter API发送给你的速度慢。从Twitter的文档中可以了解到:
如果把这个参数设置为字符串true,当客户端有可能被断开连接时,会定期发送消息。这些消息只会在客户端跟不上时发送,最多每5分钟发送一次。
理论上,在这种情况下,你应该会收到来自API的断开连接消息。不过,这并不总是发生:
流媒体API会尝试发送一条消息,说明流为何被关闭。需要注意的是,如果断开是由于网络问题或客户端读取速度太慢,可能就收不到这条消息。
IncompleteRead
也可能是因为临时的网络问题,可能以后不会再发生。不过,如果在大约5小时后持续出现这种情况,那就很可能是跟不上了。