我编写了一个简短的Python脚本,以从API中提取一些人群数据并将其存储到CSV中。可以在此处找到API返回的示例。"数据"包含8000多个观测值,因此我正在寻找一种访问它的有效方法。我编写的代码正在工作,但需要几个小时才能运行。因此,我的问题是,是否有任何方法可以更有效地循环浏览此JSON,或者可以提取所需的数据而不循环遍历每个观察?
import requests
api_base = "http://dw.euro.who.int/api/v3/data_sets/HFAMDB/HFAMDB_8"
with open("population.csv", "w") as outfile:
outfile.write("country,year,group,fullname,countn")
for i in range(32,51):
response = requests.get(api_base+str(i))
print(api_base+str(i))
for observation in response.json()['data']:
count = observation["value"]["numeric"]
country = observation["dimensions"]["COUNTRY"]
year = observation["dimensions"]["YEAR"]
group = observation["dimensions"]["AGE_GRP_6"]
fullGroupName = response.json()['full_name']
if observation["dimensions"]["SEX"] == "ALL":
outfile.write("{},{},{},{},{}n".format(country, year, group, fullGroupName, count))
预先感谢您的答案。
好吧,请不要一遍又一遍地不必要地致电response.json()
。
而不是
for observation in response.json()['data']:
fullGroupName = response.json()['full_name']
做
data = response.json()
for observation in data['data']:
fullGroupName = data['full_name']
改变了整个过程,将我的电脑带走了大约33秒。几乎所有这些都是为了要求。也许您可以通过使用并行请求进一步加快该网站的速度。
尽管Stefan Pochmann已经回答了您的问题,但我认为值得一提的是您如何弄清楚自己的问题。
一种方法是使用profiler,例如Python的Cprofile,其中包含在标准库中。
假设您的脚本称为slow_download.py
,您可以将循环中的范围限制为例如range(32, 33)
并以以下方式执行:
python3 -m cProfile -s cumtime slow_download.py
-s cumtime
按累积时间对呼叫进行分类。
结果是:
http://dw.euro.who.int/api/v3/data_sets/HFAMDB/HFAMDB_832
222056 function calls (219492 primitive calls) in 395.444 seconds
Ordered by: cumulative time
ncalls tottime percall cumtime percall filename:lineno(function)
122/1 0.005 0.000 395.444 395.444 {built-in method builtins.exec}
1 49.771 49.771 395.444 395.444 py2.py:1(<module>)
9010 0.111 0.000 343.904 0.038 models.py:782(json)
9010 0.078 0.000 332.900 0.037 __init__.py:271(loads)
9010 0.091 0.000 332.801 0.037 decoder.py:334(decode)
9010 332.607 0.037 332.607 0.037 decoder.py:345(raw_decode)
...
这清楚地表明该问题与json()
和相关方法有关:loads()
和raw_decode()
。
如果数据真的很大,请将数据转储到mongodb中,并有效地查询任何您想要的内容。