任务背景:
调用API接口数据以提取所需类型的数据并将其写入指定的mysql数据库。
先宏观地看这个任务,分解任务:
step1:有必要学习用python从url中读取数据的方法
step2)数据分析,也是核心部分,数据形式要从python的角度来理解,辞典? 名单? 还是各种各样的嵌套?
step3:连接到MySQL数据库并写入数据。
在功能上,该数据获取程序可分为: step1对应方法request_data (、step2对应方法parse_data )、step3对应的data_to_db )三种方法。
第一轮不考虑异常,只考虑正常状态下的功能实现。
1、首先看request_data(: )
导入请求
efrequest_data(URL ) :
req=requests.get(URL,timeout=30 ) #请求连接
req_Jason=req.JSON(#获取数据
return req_jason
参照: url地址; return :获取的数据。
2、然后查看parse_data(: )
不同的API接口有不同的数据格式,需要先整理一下。 打开后,排列得密密麻麻的,甚至可能不知道完整的数据间隔在哪里。 此时,可以巧妙使用符号{ [,] }辅助判断。
整理后发现,本界面下的数据格式,最外层为词典,我们需要的数据在最初的key“data”下,data对应的value为列表,列表中的各要素为词典,是词典中键值的一部分
是我们需要的东西。 如上所述,已经发现,我们的数据结构是字典集列表,该列表重新设置字典的格式,并且在最底层的字典中存在一键多值(例如,“weather”)。
当然,也有懒惰的方法。 百度json在线分析格式。
提取数据的一部分如下。 (数据(: (timestamp _ utc ) : ) 2020-08-31t0833600336000 )、(weather ) : ) icon ) 33660
wind_dir':336、' clouds_hi':0、' precip':0.0625} '、{ ' timestamp _ utc ' 3360 ' 2020-08-31t 088-31t 080
wind_dir':336、' clouds_hi':0、' precip':0.0625]、' city _ name ' : '诊断bu '、' lon ' 336666600
efparse_data(req_Jason ) :
data _ trunk=req _ Jason [ ' data ' ] #获取data键值下的列表
time _ now=datetime.datetime.now (.strftime (' % y-% m-% d % h : % m 3360 % s ' ) )获取当前时间
forIinrange(Len ) data_trunk ) :
依次获取作为data_unit=data_trunk[i] #列表下第I个元素的词典
del data_unit['weather'] #从本词典中删除不需要的一键多值key和value。 如果不删除,则会影响后续的dataframe转换,但如果需要键值,则需要进行其他处理
df=PD.dataframe([data_unit] )将删除了键值的词典转换为datafrme
list_need=['timestamp_utc '、' wind_dir '、' precip '、' clouds_hi'] #列出所需的列
df_need=df[list_need] #在保留df所需的列10df_need.insert(0,' update_time ',time_now )表中添加并添加获取数据的当前时间
注意:有两种方法将数据插入数据库:使用insert SQL语句以词典格式插入,或使用pandas to _ SQL方法的dataframe方法。 在本案例中选择了后者,因此在数据分析时将词典数据转换为dataframe格式。
参考:获取的数据; 返回值:无
运行后,我发现这类程序存在一些问题。 这意味着这个for循环太多了,对数据库的写入只能是一个写入,而不是整个块,这会影响程序的效率,所以必须按如下方式修改程序。
efparse_data(req_Jason ) :
data _ trunk=req _ Jason [ ' data ' ] #获取data键值下的列表
time_now=datetime.datetime.now ().strftime('%y-%m-
%d %H:%M:%S") #获取当前时刻for i in range(len(data_trunk)):
data_unit = data_trunk[i] # 依次获取列表下第i个元素即字典
del data_unit["weather"] # 删除该字典中不需要的一键多值的key和value,不删除的话会影响后续的dataframe转换,但是,如果该键值需要的话,需要采取其他处理方式
df = pd.DataFrame(data_trunk) # 将删除键值后的整个列表套字典转为datafrme
list_need = ["timestamp_utc", "wind_dir", "precip","clouds_hi"] # 列出我们需要的列
df_need = df[list_need] # 保留df中需要的列
df_need.insert(0, "update_time", time_now) #表格中还需额外增加获取数据的当前时间,并且需要放在dataframe的第一列
也就是从第7行之后跳出循环;
如果觉得for循环影响整体美观,也可以用map代替,将代码第4/5/6行改为如下代码,不过性能上来说可能还是for循环更好,具体对比可看其他博主的测试,或者自己测试下运行时间。
map(data_trunk.pop, ["weather"])
3. 最后就是data_to_sql():
def data_to_sql(df):
table = "request_data_api"
engine = create_engine("mysql+pymysql://" + "root" + ":" + "123" + "@" + "localhost" + ":" + "3306" + "/" + "test" + "?charset=utf8")
df.to_sql(name=table, con=engine, if_exists="append",
index=False, index_label=False)
入参:dataframe类型数据。
当当当,正常部分已完成,就下来就需要想象各种异常以及处理对策。
第二轮,想象各种异常以及异常的记录与处理对策。
1.读取url后,获取不到数据 → 休息几秒,尝试再次重连获取
2.连接数据库异常 → 数据库可能关闭,尝试重新ping,
3.写入数据库的内容为空 → 记录异常,放弃入库
第三轮,让程序定时跑起来。
fndgz:在代码中采用apscheduler下的cron功能(trigger="cron‘,类似linux下的crontab)实现定时运行(当然,apscheduler还有另一种trigger=‘interval"模式);
xsdjy:在linux下的crontab增加定时任务。
具体可以看别的帖子。
以上就是python 调用API接口 获取和解析 Json数据的详细内容,更多关于python 解析数据的资料请关注云海天教程其它相关文章!
原文链接:https://www.cnblogs.com/xiamibao/p/13589798.html