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

11
在使用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)
>>> 

实际上我不知道如何处理这个问题!!!


1
这个问题最近已经被修复。请确保您正在使用最新的Tweepy。 - Luigi
谢谢,我会尝试并更新状态。 - Hana
实际上,当我在MAC OSX终端中安装“pip install tweepy”时,我收到了这条消息:“Requirement already satisfied (use --upgrade to upgrade): tweepy in /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages Cleaning up…”,请问如何覆盖以前的版本? - Hana
pip install tweepy --upgrade. 不过更新仅在8天前推送到Github,所以pip可能没有最新版本。您可以随时自己编辑源代码/检查以确保,我认为更改只有大约一行。 - Luigi
啊哈,这和 tweepy2.3 是一样的,他只是在 tweepy/streaming.py 中添加了这行代码 "except (Timeout, ssl.SSLError, requests.compat.IncompleteRead) as exc:",而我已经在 tweepy2.3 中有了这行代码 :( - Hana
你能在你的TweetListener中添加一个异常处理器吗? - Luigi
5个回答

8

您应该使用stall_warnings参数来检查是否未能快速处理推文。

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

这些消息由Tweepy处理(在此处查看实现here),并会通知您是否落后。 落后意味着您无法像Twitter API发送推文一样快速处理它们。从Twitter文档中得知:

将此参数设置为字符串true将导致定期发送消息,如果客户端处于断开连接的危险状态,则会发出这些消息。仅在客户端落后时发送这些消息,并且最多每5分钟发生一次。

理论上,您应该从API收到一个断开连接的消息。但是,情况并非总是如此:

流式API将尝试传递指示为何关闭流的消息。请注意,如果断开连接是由于网络问题或客户端读取过慢,则可能无法接收到此消息。

IncompleteRead也可能是由于暂时的网络问题而导致的,可能永远不会再次发生。但是,如果在大约5个小时后可重复发生,则很有可能是落后了。

1
我可能会错过它,但是stall_warning只显示警告以确认错误类型。我相信你没有提供解决方案。我现在遇到了这个问题,并怀疑你可能是正确的,所以如果你知道解决方案,希望你能与我们分享。 - A-nak Wannapaschaiyong

5

我刚刚遇到了这个问题。另一个答案在事实上是正确的,因为很可能是:

  • 你的程序跟不上流
  • 如果是这种情况,你会收到停顿警告。

在我的情况下,我正在将推文读入postgres以供稍后分析,涉及相当密集的地理区域以及关键词(实际上是伦敦和约100个关键词)。很可能,即使你只是打印它,你的本地机器也在做很多其他的事情,系统进程得到优先处理,因此推文将会积压直到Twitter断开连接。(这通常表现为表面上的内存泄漏——程序大小增加直到被杀死或Twitter断开连接——以先发生者为准。)

在这里有意义的事情是将处理推迟到队列中。所以,我使用了redis和django-rq解决方案——在dev和我的生产服务器上实现大约需要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,所以希望您已经解决了这个问题,但希望这对其他人有用! :)


我刚刚收到了一个赞,这让我回来了。如果我的答案或者luigi的答案解决了你的问题,那么请你选择其中一个作为最佳答案,这将非常棒。@hana - Withnail

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

-1

对我来说,URL 指向的后端应用程序直接返回字符串。

我进行了更改:

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

一开始我只是返回文本,例如:

return original_message

我认为这个答案只适用于我的情况


我看不出你的回答和问题之间的联系。 - Ruli

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接