如何处理urllib2的泄密响应?

时间:2009-12-08 02:16:48

标签: python gzip urllib2 deflate

我目前使用以下代码通过urllib2解压缩gzipped响应:

opener = urllib2.build_opener()
response = opener.open(req)
data = response.read()
if response.headers.get('content-encoding', '') == 'gzip':
    data = StringIO.StringIO(data)
    gzipper = gzip.GzipFile(fileobj=data)
    html = gzipper.read()

它是否也能处理泄密的响应,还是需要编写单独的代码来处理泄密的响应?

4 个答案:

答案 0 :(得分:4)

有一个更好的方法概述:

作者解释了如何通过块解压缩块,而不是在内存中一次解压缩块。当涉及较大的文件时,这是首选方法。

还找到了这个有用的测试网站:

答案 1 :(得分:4)

你可以尝试

if response.headers.get('content-encoding', '') == 'deflate':
    html = zlib.decompress(response.read())

如果失败,这是另一种方式,我在requests source code

中找到了它
if response.headers.get('content-encoding', '') == 'deflate':
    html = zlib.decompressobj(-zlib.MAX_WBITS).decompress(response.read())

答案 2 :(得分:1)

要回答上述评论,HTTP规范(http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3)说:

  

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

我认为这意味着它应该使用身份。我从来没有见过没有的服务器。

答案 3 :(得分:1)

您可以在urllib3

中看到代码
class DeflateDecoder(object):

    def __init__(self):
        self._first_try = True
        self._data = binary_type()
        self._obj = zlib.decompressobj()

    def __getattr__(self, name):
        return getattr(self._obj, name)

    def decompress(self, data):
        if not data:
            return data

        if not self._first_try:
            return self._obj.decompress(data)

        self._data += data
        try:
            return self._obj.decompress(data)
        except zlib.error:
            self._first_try = False
            self._obj = zlib.decompressobj(-zlib.MAX_WBITS)
            try:
                return self.decompress(self._data)
            finally:
                self._data = None


class GzipDecoder(object):

    def __init__(self):
        self._obj = zlib.decompressobj(16 + zlib.MAX_WBITS)

    def __getattr__(self, name):
        return getattr(self._obj, name)

    def decompress(self, data):
        if not data:
            return data
        return self._obj.decompress(data)