使用Python获取Twitter数据时出现"IncompleteRead"错误

11 投票
5 回答
16234 浏览
提问于 2025-04-30 11:04

在用 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 个回答

-1

对我来说,那个网址指向的后端应用直接返回了一个字符串。

我把它改成了

return Response(response=original_message, status=200, content_type='application/text')

一开始我只是返回了一些文本,比如

return original_message

我觉得这个答案只适合我的情况。

0

一种解决办法是在捕捉到异常后立即重新启动流。

# 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()
0

这个对我有效。

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
5

我刚遇到这个问题。之前的回答在事实方面是正确的,基本上可以归结为:

  • 你的程序跟不上数据流
  • 如果是这样,你会收到一个停滞警告。

在我的情况下,我是把推文读入Postgres数据库,以便后续分析,覆盖了一个相当密集的地理区域,还有一些关键词(实际上是伦敦,大约100个关键词)。即使你只是打印这些推文,你的本地机器可能还在做其他事情,系统进程会优先处理,所以推文会堆积,直到Twitter把你断开连接。(这通常表现为明显的内存泄漏——程序的大小不断增加,直到被杀掉,或者Twitter断开连接——哪个先发生就看运气了。)

在这种情况下,合理的做法是把处理工作推到一个队列里。所以,我使用了Redis和Django-RQ的解决方案——在开发和生产服务器上实现这个大约花了3个小时,包括研究、安装、调整现有代码、在安装过程中犯傻、测试,以及拼写错误。

现在,在你的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的路上,所以希望你已经解决了这个问题,不过希望这对其他人也有用! :)

8

你应该检查一下,自己处理推文的速度是否够快,可以使用stall_warnings这个参数来帮助你。

stream.filter(track=[t], stall_warnings=True)

这些信息是由Tweepy处理的(具体实现可以在这里查看),它会告诉你是否跟不上推文的速度。跟不上意味着你处理推文的速度比Twitter API发送给你的速度慢。从Twitter的文档中可以了解到:

如果把这个参数设置为字符串true,当客户端有可能被断开连接时,会定期发送消息。这些消息只会在客户端跟不上时发送,最多每5分钟发送一次。

理论上,在这种情况下,你应该会收到来自API的断开连接消息。不过,这并不总是发生:

流媒体API会尝试发送一条消息,说明流为何被关闭。需要注意的是,如果断开是由于网络问题或客户端读取速度太慢,可能就收不到这条消息。

IncompleteRead也可能是因为临时的网络问题,可能以后不会再发生。不过,如果在大约5小时后持续出现这种情况,那就很可能是跟不上了。

撰写回答