我正在使用请求库和python 2.7从web api下载gzip压缩文本文件。使用下面的代码,我能够成功发送一个get请求,并从头部判断,接收gzip文件形成的响应。
我知道Requests会自动解压缩这些文件,如果它从头部检测到响应是gzip压缩的话。我希望以文件流的形式进行下载,并将内容写入磁盘以供存储和将来分析。
当我在工作目录中打开生成的文件但是我得到这样的字符: - }}¶-Q@Ï'õ
作为参考,一些响应标题包括'Content-Encoding':'gzip','Content-Type':'application / download','Accept-Encoding,User-Agent'
用二进制文写错了吗?我没有正确编码文本(即可能是ASCII vs 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)
编辑3.30.2016 : 现在我已经改变了我的代码以利用gzipstream库。我尝试使用该流来读取我的响应内容中的整个Gzip文本文件:
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方法?
编辑4.1.2016 我想澄清一点,这不一定是一个流,这只是我遇到的一个解决方案。我只想每天请求这个gzip压缩文件,并以明文本地保存
答案 0 :(得分:3)
因此,stream=True
和iter_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)
请注意,您仍然希望使用字节,因为您尚未确定内容的字符编码,因此您仍然拥有字节,但您不再处理gzip压缩字节。
答案 1 :(得分:3)
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开头的。我知道这个事实,但是我没有清楚地描述它,因为我一直在读取/写入gzip压缩字节。
使用zlib模块,我能够将响应的内容一次性解压缩到数据变量中;然后我将包含解压缩数据的变量写入文件。
我不确定这是否是最佳或最pythonic方式,但它确实有效。如果有人可以告诉我为什么我不能gzip.open
这个内容(也许我需要使用替代方法,我试过gzipstream库无济于事),我会感谢任何解释,但我确实认为这个问题得到了解答。
感谢所有帮助过我的人,即使你没有解决方案,也帮助我鼓励我坚持下去!
答案 2 :(得分:0)
您正在请求剥离块传输编码但保留内容编码完整的原始套接字流。换句话说:你所拥有的内容肯定是gzipped内容。 Content-Encoding: gzip
标头的存在是一个强有力的指标,因为http客户端在删除内容编码时需要将其删除。
消除此问题的一种方法是在请求中发送一个空的Accept-Encoding
标头,表明没有可接受的编码。如果API符合RFC,则应收到未压缩的响应。另一种方法是自己解压缩流。我相信这不能通过gzip和zlib模块本地完成。但是,gzipstream lib应该给你一个开始。