【问题标题】:Python3 urlopen read weirdness (gzip)Python3 urlopen 读取怪异(gzip)
【发布时间】:2015-08-25 10:59:52
【问题描述】:

我从 Schema.org 获得一个 URL。它是 content-type="text/html"

有时,read() 会按预期运行 b' ....'

有时,read() 会返回其他内容 b'\x1f\x8b\x08\x00\x00\x00\x00 ...'

try:
    with urlopen("http://schema.org/docs/releases.html") as f:
        txt = f.read()
except URLError:
    return

我尝试使用txt = f.read().decode("utf-8").encode() 解决此问题,但这会导致错误...有时:UnicodeDecodeError: 'utf-8' codec can't decode byte 0x8b in position 1: invalid start byte

显而易见的解决方法是测试第一个字节是否为十六进制并相应地处理。

我的问题是:这是一个错误还是其他什么?

编辑 相关question。显然,有时我会得到一个 gzipped 流。

最后 我通过将以下代码添加为proposed here

解决了这个问题
if 31 == txt[0]:
    txt = decompress(txt, 16+MAX_WBITS)

问题仍然存在;为什么这有时会返回 text/html 而有时会被压缩?

【问题讨论】:

  • 我只能重现您收到 b'.. 在我看来,您收到的其他回复与您的互联网连接以某种方式失败有关。跨度>
  • @SlashV 我可能每 5 次收到一次
  • 我运行代码 200 次...
  • @SlashV 我正在使用 PyCharm,我不知道
  • @SlashV 添加截图

标签: python-3.x urlopen


【解决方案1】:

此类别中还有其他问题,但我找不到解决问题实际原因的答案。

Python 的urllib2.urlopen() 无法透明地处理压缩。它也默认不设置Accept-Encoding 请求头。此外,过去根据 HTTP 标准对这种情况的解释发生了变化。

根据RFC2616

如果请求中没有 Accept-Encoding 字段,服务器可以 假设客户端将接受任何内容编码。在这种情况下, 如果“身份”是可用的内容编码之一,那么 服务器应该使用“身份”内容编码,除非它有 不同内容编码有意义的附加信息 给客户。

不幸的是(至于用例),RFC7231 将其更改为

如果请求中没有 Accept-Encoding 字段,则用户代理认为任何内容编码都可以接受

意思是,当使用urlopen() 执行请求时,您可以获得服务器决定使用的任何编码的响应,并且响应将是一致的。

schema.org 似乎由 google 托管,即它很可能位于分布式前端负载均衡器网络之后。因此,您得到的不同答案可能会从配置略有不同的负载均衡器返回。

Google 工程师过去有 advocated for the use HTTP compression,所以这可能是一个有意识的决定。

所以作为一个教训:使用urlopen()时我们需要设置Accept-Encoding

【讨论】:

  • 我怀疑是这样的。负载均衡器似乎是合理的解释。干杯。
【解决方案2】:

您确实收到了压缩后的响应。您应该能够通过以下方式避免它:

from urllib import request
try:
    req = request.Request("http://schema.org/docs/releases.html")
    req.add_header('Accept-Encoding', 'identity;q=1')
    with request.urlopen(req) as f:
        txt = f.read()
except request.URLError:
    return

【讨论】:

  • 我选择的解决方法是解压缩...更少的代码
  • @GUIJunkie 不,这两行都是两行并且你必须为decompress做一个额外的导入;)
  • :-) 我还必须为请求做一个额外的导入。耸耸肩。
猜你喜欢
  • 2020-10-09
  • 2017-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多