繁体   English   中英

在 Python 中,如何解码 GZIP 编码?

[英]In Python, how do I decode GZIP encoding?

我在我的 python 脚本中下载了一个网页。 在大多数情况下,这可以正常工作。

但是,这个有一个响应头:GZIP 编码,当我试图打印这个网页的源代码时,它在我的 putty 中有所有符号。

如何将其解码为常规文本?

我使用 zlib 解压缩来自网络的 gzip 压缩内容。

import zlib
import urllib

f=urllib.request.urlopen(url) 
decompressed_data=zlib.decompress(f.read(), 16+zlib.MAX_WBITS)

使用内置的 gzip 模块解压缩字节流。

如果您有任何问题,请显示您使用的确切最小代码、确切的错误消息和回溯,以及print repr(your_byte_stream[:100])的结果

更多信息

1.有关 gzip/zlib/deflate 混淆的解释,请阅读此 Wikipedia 文章的“其他用途”部分。

2.如果你有一个字符串而不是一个文件,那么使用 zlib 模块比使用 gzip 模块更容易。 不幸的是, Python 文档不完整/错误:

zlib.decompress(string[, wbits[, bufsize]])

... wbits 的绝对值是压缩数据时使用的历史缓冲区大小(“窗口大小”)的以 2 为底的对数。 对于最新版本的 zlib 库,它的绝对值应该在 8 到 15 之间,较大的值会导致更好的压缩,但会消耗更多的内存。 默认值为 15。当 wbits 为负数时,标准 gzip 头被抑制; 这是 zlib 库的一个未记录的功能,用于与 unzip 的压缩文件格式兼容。

首先,8 <= log2_window_size <= 15,含义如上。 然后应该是一个单独的 arg 被挤在上面:

arg == log2_window_size 表示假设字符串是 zlib 格式(RFC 1950;HTTP 1.1 RFC 2616 混淆地称为“deflate”)。

arg == -log2_window_size 表示假设字符串为 deflate 格式(RFC 1951;没有仔细阅读 HTTP 1.1 RFC 的人实际实现了什么)

arg == 16 + log_2_window_size 表示假设字符串为 gzip 格式(RFC 1952)。 所以你可以使用 31。

上述信息记录在zlib C 库手册中... Ctrl-F 搜索windowBits

对于 Python 3

试试这个:

import gzip

fetch = opener.open(request) # basically get a response object
data = gzip.decompress(fetch.read())
data = str(data,'utf-8')

我使用类似的东西:

f = urllib2.urlopen(request)
data = f.read()
try:
    from cStringIO import StringIO
    from gzip import GzipFile
    data2 = GzipFile('', 'r', 0, StringIO(data)).read()
    data = data2
except:
    #print "decompress error %s" % err
    pass
return data

如果您使用Requests模块,那么您不需要使用任何其他模块,因为gzipdeflate传输编码会自动为您解码

例子:

>>> import requests
>>> custom_header = {'Accept-Encoding': 'gzip'}
>>> response = requests.get('https://api.github.com/events', headers=custom_header)
>>> response.headers
{'Content-Encoding': 'gzip',...}
>>> response.text
'[{"id":"9134429130","type":"IssuesEvent","actor":{"id":3287933,...

响应.text属性用于读取文本上下文中的内容。

响应.content属性用于读取二进制上下文中的内容。

请参阅docs.python-requests.org上的二进制响应内容部分

类似于 Shatu 对 python3 的回答,但排列方式略有不同:

import gzip

s = Request("https://someplace.com", None, headers)
r = urlopen(s, None, 180).read()
try: r = gzip.decompress(r)
except OSError: pass
result = json_load(r.decode())

此方法允许将 gzip.decompress() 包装在 try/except 中以捕获并传递 OSError,这会导致您可能获得混合的压缩和未压缩数据。 如果对一些小字符串进行编码,它们实际上会变大,因此会发送纯数据。

这个版本很简单,并且通过不调用read()方法来避免首先读取整个文件。 它提供了一个类似对象的文件流,而不是像普通文件流一样行为。

import gzip
from urllib.request import urlopen

my_gzip_url = 'http://my_url.gz'
my_gzip_stream = urlopen(my_gzip_url)
my_stream = gzip.open(my_gzip_stream, 'r')

这些答案都没有使用 Python 3 开箱即用。以下是我获取页面并解码 gzipped 响应的方法:

import requests
import gzip

response = requests.get('your-url-here')
data = str(gzip.decompress(response.content), 'utf-8')
print(data)  # decoded contents of page

您可以使用 urllib3 轻松解码 gzip。

urllib3.response.decode_gzip(response.data)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM