python urllib2是否会自动解压缩从网页获取的gzip数据?


71

我正在使用

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

我想知道:

  1. 如何判断URL上的数据是否已压缩?

  2. 如果将urllib2压缩,数据是否会自动解压缩?数据将始终是字符串吗?


3
可能值得注意的是,该requests库会自动处理gzip压缩(请参阅FAQ
dbr

Answers:


149
  1. 如何判断URL上的数据是否已压缩?

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

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压缩,数据是否会自动解压缩?数据将始终是字符串吗?

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


2
bobince有一点,urllib2将不会发送适当的标头,因此不会压缩响应。
daniyalzade 2011年

9
在Py3k中,使用io.BytesIO代替StrinIO.StringIO!
phobie,2012年

2
相关内容:为什么您无法将urllib流式传输到gzip enricozini.org/2011/cazzeggio/python-gzip
山姆

1
@ tommy.carstensen:这是Python 3代码示例
jfs

2
@daniyalzade我正在与一个压缩响应的网站合作,即使请求未指定响应。
2016年

8

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

如果您正在谈论使用Content-Encoding: gzip或进行HTTP级别的自动压缩deflate,那么客户端必须使用Accept-Encoding标头有意地请求该压缩。

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


4
对于所有流行的服务器,似乎并非如此。试试curl -vI http://en.wikipedia.org/wiki/Spanish_language |& grep '^[<>]'
Andres Riofrio

5

您的问题已得到解答,但是对于更全面的实现,请看一下Mark Pilgrim的this的实现,它涵盖了gzip,deflate,安全的URL解析等,并且对于一个广泛使用的RSS解析器而言,还有很多,但仍然是有用的参考。


0

看来urllib3现在自动处理此问题。

参考标题:

HTTPHeaderDict({'ETag':'“ 112d13e-574c64196bcd9-gzip”','Vary':'Accept-Encoding','Content-Encoding':'gzip','X-Frame-Options':'sameorigin','服务器'':'Apache','上次修改时间':'星期六,2018年9月1日02:42:16 GMT','X-Content-Type-Options':'nosniff','X-XSS-Protection':' 1; mode = block','Content-Type':'text / plain; charset = utf-8','Strict-Transport-Security':'max-age = 315360000; includeSubDomains','X-UA-Compatible' :'IE = edge','Date':'Sat,01 Sep 2018 14:20:16 GMT','Accept-Ranges':'bytes','Transfer-Encoding':'chunked'})

参考代码:

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()
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.