Pythonurllib2是否自动解压从网页获取的 gzip 数据?

我在吸毒

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

我想知道:

  1. 如何判断 URL 上的数据是否为 gzip?

  2. 如果数据是 gzip 的,urllib2是否会自动解压缩数据? 数据总是字符串吗?

35416 次浏览
  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. 如果数据是 gzip 的,urllib2是否会自动解压缩数据? 数据总是字符串吗?

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

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

如果您讨论的是使用 Content-Encoding: gzipdeflate的自动 HTTP 级别压缩,那么客户端必须使用 Accept-Encoding头特意请求这种压缩。

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

您的问题已经得到了回答,但是对于更全面的实现,请看一下 马克 · 皮尔格林对此的实现,它涵盖了 gzip、 flate、安全的 URL 解析,以及更多更广泛使用的 RSS 解析器,但仍然是一个有用的参考。

似乎 urllib3现在会自动处理这个问题。

参考标题:

HTTPHeaderDect ({‘ ETag’:’“112d13e-574c64196bcd9-gzip”’,‘ Vary’: ‘ Accept-Encoding’,‘ Content-Encoding’: ‘ gzip’,‘ X-Frame-Options’: ‘接受-编码’,‘内容-编码’: ‘ gzip’,‘ X-Frame-Options’: ‘ samesource’,‘ Server’: ‘ Apache’,‘ Last-Amendment’: ‘ Sat,01 Sep 2018 格林威治时间02:42:16’,‘ X-Content-Type-Options’: ‘ nosniff’,‘ X-Content-Type-Options’,‘ X-Content-Type-Options’, “ X-XSS-Protection”: “1; mode = block”,“ Content-Type”: “ text/plain; Charset = utf-8’,‘ HTTP严格传输安全’: ‘ max-age = 315360000; ‘ X-UA-Compatible’: ‘ IE = edge’,‘ Date’: ‘ Sat,01 Sep 2018年14:20:16格林尼治标准时间’,’接受-范围’:’字节’,’传输-编码’: ‘ 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()