【问题标题】:Does python urllib2 automatically uncompress gzip data fetched from webpage?python urllib2 会自动解压缩从网页获取的 gzip 数据吗?
【发布时间】:2011-04-26 05:12:00
【问题描述】:

我正在使用

 data=urllib2.urlopen(url).read()

我想知道:

  1. 如何判断 URL 中的数据是否经过 gzip 压缩?

  2. 如果数据被 gzip 压缩,urllib2 会自动解压缩数据吗?数据会一直是字符串吗?

【问题讨论】:

标签: python gzip urllib2


【解决方案1】:
  1. 如何判断 URL 中的数据是否经过 gzip 压缩?

这会检查内容是否被压缩并解压缩:

from StringIO import StringIO
import gzip

request = urllib2.Request('http://example.com/')
request.add_header('Accept-encoding', 'gzip')
response = urllib2.urlopen(request)
if response.info().get('Content-Encoding') == 'gzip':
    buf = StringIO(response.read())
    f = gzip.GzipFile(fileobj=buf)
    data = f.read()
  1. urllib2 是否会自动解压缩 gzip 后的数据?数据是否总是字符串?

没有。 urllib2 不会自动解压缩数据,因为 'Accept-Encoding' 标头不是由 urllib2 设置的,而是由您使用:request.add_header('Accept-Encoding','gzip, deflate')

【讨论】:

  • bobince 有一点,urllib2 不会发送适当的标头,所以响应不会被压缩。
  • 在 Py3k 中使用 io.BytesIO 而不是 StrinIO.StringIO!
  • 相关:为什么不能将 urllib 流式传输到 gzip enricozini.org/2011/cazzeggio/python-gzip
  • @tommy.carstensen:这里是Python 3 code example
  • @daniyalzade 我正在使用一个 gzip 压缩响应的网站,即使请求没有指定它。
【解决方案2】:

如果您谈论的是一个简单的.gz 文件,不,urllib2 不会对其进行解码,您将得到未更改的.gz 文件作为输出。

如果您正在谈论使用Content-Encoding: gzipdeflate 的自动HTTP 级别压缩,那么客户端必须使用Accept-Encoding 标头故意请求。

urllib2 没有设置这个头,所以它返回的响应不会被压缩。您可以安全地获取资源而不必担心压缩(尽管由于不支持压缩,请求可能需要更长时间)。

【讨论】:

  • 这似乎不适用于所有流行的服务器。试试curl -vI http://en.wikipedia.org/wiki/Spanish_language |& grep '^[<>]'
【解决方案3】:

您的问题已得到解答,但要获得更全面的实现,请查看 Mark Pilgrim's implementation of this,它涵盖 gzip、deflate、安全 URL 解析以及更多,对于广泛使用的 RSS 解析器,但仍然是有用的参考。

【讨论】:

    【解决方案4】:

    现在看来 urllib3 会自动处理这个问题。

    参考标题:

    HTTPHeaderDict({'ETag': '"112d13e-574c64196bcd9-gzip"', '变化': '接受编码','内容编码':'gzip','X-Frame-Options': 'sameorigin', 'Server': 'Apache', 'Last-Modified': 'Sat, 01 Sep 2018 02:42:16 GMT', 'X-Content-Type-Options': 'nosniff', 'X-XSS-保护': '1;模式=块','内容类型':'文本/纯文本; charset=utf-8', '严格传输安全': 'max-age=315360000; includeSubDomains', 'X-UA-Compatible': 'IE=edge', 'Date': 'Sat, 01 Sep 2018 14:20:16 GMT”,“接受范围”:“字节”,“传输编码”: '分块'})

    参考代码:

    import gzip
    import io
    import urllib3
    
    class EDDBMultiDataFetcher():
        def __init__(self):
            self.files_dict = {
                'Populated Systems':'http://eddb.io/archive/v5/systems_populated.jsonl',
                'Stations':'http://eddb.io/archive/v5/stations.jsonl',
                'Minor factions':'http://eddb.io/archive/v5/factions.jsonl',
                'Commodities':'http://eddb.io/archive/v5/commodities.json'
                }
            self.http = urllib3.PoolManager()
        def fetch_all(self):
            for item, url in self.files_dict.items():
                self.fetch(item, url)
    
        def fetch(self, item, url, save_file = None):
            print("Fetching: " + item)
            request = self.http.request(
                'GET',
                url,
                headers={
                    'Accept-encoding': 'gzip, deflate, sdch'
                    })
            data = request.data.decode('utf-8')
            print("Fetch complete")
            print(data)
            print(request.headers)
            quit()
    
    
    if __name__ == '__main__':
        print("Fetching files from eddb.io")
        fetcher = EDDBMultiDataFetcher()
        fetcher.fetch_all()
    

    【讨论】:

    • urllib3 是第三方包。这不是 urllib2 的升级。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多