请求Gzip HTTP下载并写入磁盘



我正在使用请求库和python 2.7从web api下载一个gzipped文本文件。使用下面的代码,我能够成功地发送一个get请求,并从头部判断,接收一个以gzip文件形式的响应。

我知道,如果请求从标头中检测到响应是gzip,它会自动为您解压缩这些文件。我想以文件流的形式下载,并将内容写入磁盘,以便存储和将来分析。

当我打开工作目录中的结果文件时,我会得到这样的字符:--}}¶--Q@Í'õ

作为参考,一些响应标头包括"内容编码":"gzip"、"内容类型":"应用程序/下载"、"接受编码,用户代理"

我用二进制写错了吗?我是否没有正确编码文本(即,它可能是ASCII还是utf-8)?响应标头中没有明显的字符编码。

try:
    response = requests.get(url, paramDict, stream=True)
except Exception as e:
    print(e)
with open(outName, 'wb') as out_file:
    for chunk in response.iter_content(chunk_size=1024):
        out_file.write(chunk)

编辑2016年10月3日:现在,我对代码做了一些更改,以利用gzipstream库。我尝试使用流来读取我的响应内容中的Gzipped文本文件的全部内容:

with open(outName, 'wb') as out_file, GzipStreamFile(response.content) as fileStream:
    streamContent = fileStream.read()
    out_file.write(streamContent)

然后我收到了这个错误:out_file.write(streamContent)AttributeError:"_GzipStreamFile"对象没有属性"close"

输出是一个空文本文件,文件名与预期的一样。我是否需要在with块之外初始化streamContent变量,这样它就不会在块末尾自动调用close方法?

EDIT 4.1.2016我只是想澄清一下,这不一定是一个流,这只是我遇到的一个解决方案。我只想每天请求这个gzip文件,并将其保存在本地的明文中

try:
    response = requests.get(url, paramDict)
except Exception as e:
    print(e)
data = zlib.decompress(response.content, zlib.MAX_WBITS|32)
with open('outFileName.txt','w') as outFile:
    outFile.write(data)

这是我写的最终有效的代码。正如sigmavirus所说:该文件从一开始就是用gzip封装的。我知道这个事实,但显然没有足够清楚地描述它,因为我一直在读/写gzipped字节。

使用zlib模块,我能够一次性将响应的内容全部解压缩到数据变量中;然后,我将包含解压缩数据的变量写入一个文件。

我不确定这是最好还是最像蟒蛇的方式,但它起了作用。如果有人能告诉我为什么我不能gzip.open这个内容(也许我需要使用另一种方法,我尝试了gzipstream库,但没有成功),我会感谢任何解释,但我确实认为这个问题已经得到了回答。

感谢所有帮助我的人,即使你没有解决方案,你也帮助鼓励我坚持下去!

所以stream=Trueiter_content的组合是导致问题的原因。你可能想做的是类似于此的事情(以保持流媒体行为):

try:
    response = requests.get(url, params=paramDict, stream=True)
except Exception as e:
    print(e)
raw = response.raw
with open(outName, 'wb') as out_file
    while True:
        chunk = raw.read(1024, decode_content=True)
        if not chunk:
            break
        out_file.write(chunk)

请注意,您仍然希望使用字节,因为您还没有确定内容的字符编码,所以您仍然有字节,但不再处理gzipped字节。

您正在请求原始套接字流,该流剥离了块传输编码,但保留了完整的内容编码。换言之:你所得到的肯定是gzipped的内容。Content-Encoding: gzip标头的存在是一个强有力的指标,因为http客户端在删除内容编码时需要删除它。

消除这种情况的一种方法是在请求中发送一个空的Accept-Encoding报头,以指示不接受任何编码。如果API符合RFC,那么您应该收到一个未压缩的响应。另一种方法是自己解压缩流。我相信gzip和zlib模块不能在本机上完成这一点。不过,gzipstream库应该会给您一个开始。

最新更新