【问题标题】:urllib2 not retrieving entire HTTP responseurllib2 未检索整个 HTTP 响应
【发布时间】:2009-12-01 04:51:24
【问题描述】:

我很困惑为什么我无法使用 urllib2 从 FriendFeed 下载一些 JSON 响应的全部内容。

>>> 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 检索完整响应?

【问题讨论】:

  • 网站已损坏。在浏览器中尝试。
  • 在 Ubuntu 9.04 上使用 Firefox 3.0 访问该 URL 时,我得到了完整的 165K 响应。检索到的 JSON 文档在我的浏览器中格式正确。
  • 是的,该站点已损坏。但这肯定是urllib 和urllib2 中的一个错误,因为其他工具(curl、wget)报告不完整的响应。很高兴知道 python 库中有什么问题。
  • 啊,好吧,当我使用浏览器或 curl 检索另一个房间配置文件 friendfeed.com/api/room/friendfeed-feedback/profile?format=json 时,我刚刚获得了一个不完整的检索结果,因此来自服务器的响应似乎中断了。我已向 API 开发人员发送了一封电子邮件。对不起,大雁追逐。 :-( 当他发现错误时我会报告。
  • 我遇到了同样的问题。奇怪的是, urllib.urlretrieve() 检索整个内容(并将其放入文件中),因此其中可能有一些代码可以使用

标签: python http urllib2


【解决方案1】:

获取所有数据的最佳方式:

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】:

使用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

该网站一直为我工作,所以我无法给出发现失败的例子:)

【讨论】:

    【解决方案3】:

    继续调用 stream.read() 直到它完成...

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

    【讨论】:

    • read() 是详尽无遗的。重复调用它会返回一个空字符串。
    【解决方案4】:
    readlines() 
    

    也可以

    【讨论】:

    • 它不适合我。 data = ''.join(stream.readlines()); print len(data); print(data[-40:]) 给出相同的结果。
    • stream.readlines() 返回所有行的列表。但我也刚刚意识到您正在使用 urllib2 模块。我的回答是基于我已经使用较长时间的 urllib 模块,我只是仔细检查了 urllib 模块中的 stream.readlines() 并且它工作正常
    猜你喜欢
    • 1970-01-01
    • 2023-04-07
    • 1970-01-01
    • 2015-10-25
    • 2017-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多