2009-12-01 67 views
12

我很困惑,为什么我无法使用urllib2FriendFeed下载一些JSON响应的全部内容。urllib2不检索整个HTTP响应

>>> import urllib2 
>>> stream = urllib2.urlopen('http://friendfeed.com/api/room/the-life-scientists/profile?format=json') 
>>> stream.headers['content-length'] 
'168928' 
>>> data = stream.read() 
>>> len(data) 
61058 
>>> # We can see here that I did not retrieve the full JSON 
... # given that the stream doesn't end with a closing } 
... 
>>> data[-40:] 
'ce2-003048343a40","name":"Vincent Racani' 

如何使用urllib2检索完整响应?

+1

网站的榜样的网站破碎。尝试在浏览器中。 – 2009-12-01 05:47:18

+0

当使用Ubuntu 9.04上的Firefox 3.0点击该URL时,我得到了全部165K的响应。检索到的JSON文档在我的浏览器中很好地形成。 – gotgenes 2009-12-01 14:23:41

+3

是的,该网站已损坏。但这肯定是'urllib'和'urllib2'中的一个错误,因为其他工具(curl,wget)报告的响应不完整。很高兴知道python库中有什么问题。 – 2009-12-01 14:46:03

回答

18

最好的方式得到的所有数据:

fp = urllib2.urlopen("http://www.example.com/index.cfm") 

response = "" 
while 1: 
    data = fp.read() 
    if not data:   # This might need to be if data == "": -- can't remember 
     break 
    response += data 

print response 

的原因是.read()不能保证返回整个响应,因为套接字的性质。我认为这是在文档中讨论(可能是urllib),但我找不到它。

+2

我无法得到这个例子来处理问题中给出的示例URL,http://friendfeed.com/api/room/the-life-scientists/profile?format=json。答复仍然不完整。正如我对John Weldon所提到的,重复调用read()只返回空字符串,而read()似乎是详尽无遗的。 – gotgenes 2009-12-01 05:39:07

+0

我只在我的浏览器中获得51.21 KB(52441字节)。该网站已损坏。 – 2009-12-01 05:46:34

+0

对于http://www.nylonmag.com/modules/magsection/article/uploaded_images/5463_head_minnie%20big.jpg也不起作用,尽管wget返回完整页面,并且Firefox可以显示jpg。 – dfrankow 2010-11-19 22:30:07

2

保持通话stream.read(),直到它完成...

while data = stream.read() : 
    ... do stuff with data 
+2

'read()'是详尽的。重复调用它返回一个空字符串 – gotgenes 2009-12-01 04:58:48

+0

是的,一个空字符串返回false ... – 2009-12-01 16:09:07

0
readlines() 

也适用

+1

它不适合我。 print(data [-40:])'给出了相同的结果 – gotgenes 2009-12-01 05:17:57

+0

stream.readlines()返回所有行的列表,但我也意识到你正在使用urllib2模块,我的回答是基于他的urllib模块我一直在使用更长的时间,我只是从urllib modu中检查stream.readlines() le,它正常工作 – inspectorG4dget 2009-12-02 00:41:32

4

使用tcpdump(或类似的东西)来监控实际的网络交互 - 然后您可以分析为什么该网站为某些客户端库损坏。确保您通过脚本测试重复多次,所以你可以看到,如果这个问题是一致的:

import urllib2 
url = 'http://friendfeed.com/api/room/friendfeed-feedback/profile?format=json' 
stream = urllib2.urlopen(url) 
expected = int(stream.headers['content-length']) 
data = stream.read() 
datalen = len(data) 
print expected, datalen, expected == datalen 

我一直工作,所以我不能给寻找故障:)