我想用请求流下载一个。gz文件,同时解压缩流文件。
我要做的代码位是:
import requests
import zlib
url = "https://something"
d = zlib.decompressobj(zlib.MAX_WBITS | 16)
with requests.get(url, stream=True) as r:
r.raise_for_status()
for chunk in r.iter_content(chunk_size=128):
data = d.decompress(chunk)
我还想将未压缩的数据块转换为json/dictionary。但是,由于数据的块部分不能保证是完整的json/字典格式,因此我无法将数据加载到字典或json格式中。然后,我想将数据位发送到将数据插入mongodb数据库的管道。
我想这样做:
import requests
import json
import pandas as pd
import zlib
url = "https://something"
d = zlib.decompressobj(zlib.MAX_WBITS | 16)
with requests.get(url, stream=True) as r:
r.raise_for_status()
for chunk in r.iter_content(chunk_size=128):
data = d.decompress(chunk)
#something like the line down there
yield json.load(data)
#or something like
yield df.to_dict(data)
是否有办法将这些未压缩的块加载到json或将它们转换为字典?或者,以其他方式将此数据加载到mongodb?
仅供参考,我的压缩文件约为90MB,未压缩文件约为1.2 GB。
我的压缩文件约为90MB,未压缩文件约为1.2 GB
如果你被允许使用外部模块,我建议看看json-stream外部模块,作为
与
json.load()
不同,json-stream
可以流JSON数据类文件对象。这有以下好处:
- 它不要求整个json文档预先进入内存
- 它可以在整个文档加载完成之前开始生成数据
- 它只需要足够的内存来保存当前正在解析的数据
由于json_stream.loads
例外于类文件对象,如果您想从内存加载,则需要使用io.StringIO
,请考虑以下示例
import io
import json_stream
data = '["uno","dos","tres"]'
data_io = io.StringIO(data)
for i in json_stream.load(data_io):
print(i)
输出uno
dos
tres
注意io.BytesIO
和io.StringIO
也可能用于其他地方类似文件的预期,不仅在json_stream.load
。io
是内置模块,更多信息请参考io
文档。
我找到了一个解决我的问题,这是为我工作,但不确定它是否会为其他人工作。我想我应该在这里分享一下,以防万一。
import json
import requests
import zlib
url = "helloworld.com"
data = ""
flag = 0
d = zlib.decompressobj(zlib.MAX_WBITS | 16)
with requests.get(url, stream=True) as r:
r.raise_for_status()
for chunk in r.iter_content(chunk_size=128):
datum = d.decompress(chunk)
try:
data+= datum.decode('utf-8')
if flag == 1:
data = data[data.find('"first_key"'):]
data = "[{" + data
flag = 0
if data.count('"first_key"')>=2:
#here -8 to get the last instance of the first_key of an element, might change depending upon the format
location = data.rfind('"first_key"')-8
data1 = data[:location]
if data1[0] == "[":
data1+="]"
data2 = json.loads(data1)
data = "[{" + data[data.rfind('"first_key"'):]
yield data2
except:
data = ""
flag = 1
continue