思路:使用Python爬虫对腾讯疫情网站世界疫情数据进行爬取,封装成一个函数返回一个
字典数据格式的对象,写另一个方法调用该函数接收返回值,和数据库取得连接后把
数据存储到mysql数据库。
一、mysql数据库建表
CREATE TABLE world( id INT(11) NOT NULL AUTO_INCREMENT, dt DATETIME NOT NULL COMMENT '日期', c_name VARCHAR(35) DEFAULT NULL COMMENT '国家', continent VARCHAR(35) DEFAULT NULL COMMENT '所属大洲', nowConfirm INT(11) DEFAULT NULL COMMENT '累计确诊', confirm INT(11) DEFAULT NULL COMMENT '当日现存确诊', confirmAdd INT(11) DEFAULT NULL COMMENT '当日新增确诊', suspect INT(11) DEFAULT NULL COMMENT '剩余疑似', heal INT(11) DEFAULT NULL COMMENT '累计治愈', dead INT(11) DEFAULT NULL COMMENT '累计死亡', confirmAddCut INT(11) DEFAULT NULL COMMENT 'confirmAddCut', confirmCompare INT(11) DEFAULT NULL COMMENT 'confirmCompare', nowConfirmCompare INT(11) DEFAULT NULL COMMENT 'nowConfirmCompare', healCompare INT(11) DEFAULT NULL COMMENT 'healCompare', deadCompare INT(11) DEFAULT NULL COMMENT 'deadCompare', PRIMARY KEY(id))ENGINE=INNODB DEFAULT CHARSET=utf8mb4;
注意建立的表,数据的名字,数据的长度,数据的类型,主键的定义一定要小心仔细。
这里博主出现了几个小错误:
①数据表的主键不可以设置为日期,因为在之后爬取数据之后可以看到,网站给的数据是同一天的,
因为主键不可以有重复,所以相同的日期是不可以作为主键定义的。
②设置int类型的id作为数据表的主键,那么存在一个问题,在往表里插入数据的时候,id位置的数据值需要考虑,
这个方法可以解决:可以在传值的时候把id的值设定为 0,前提是id是自增的,
这样数据库是可以自己处理id的,依然是从0开始自增,这样避免了不给id传值导致Null的异常。
③博主使用的mysql可视化工具默认在一个页面显示30条记录,在右上角可以改变显示的记录数,因为本次插入的
是185条数据,所以在插入完之后如果发现数据不对,可以看看可视化工具是不是有什么设置导致的。
二、下面直接上代码(爬虫方法)
"""获取全球疫情数据"""def get_world_data(): url='https://api.inews.qq.com/newsqa/v1/automation/foreign/country/ranklist' headers={'user-agent': 'WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36'} # 创建会话对象 # session = requests.session() # 请求接口 # result = session.get('https://api.inews.qq.com/newsqa/v1/automation/foreign/country/ranklist') # 打印结果 # print(result.text) res = requests.get(url, headers=headers) # print(res.text) response_data_0 = json.loads(res.text.replace('jQuery34102848205531413024_1584924641755(', '')[:-1]) #转化json对象 # print(response_data_0.keys()) # print(response_data_0) response_data_1=response_data_0['data'] # print(response_data_1) # print(response_data_1[0].keys()) # data = jsonpath.jsonpath(resJson_1, '$.data.*') # print(resJson_1.keys()) # for d in data: # res = '日期:' + d['date'] + '--' + d['continent'] + '--' + d['name'] + '--' + '新增确诊:' + str( # d['confirmAdd']) + '累计确诊:' + str(d['confirm']) + '治愈:' + str(d['heal']) + '死亡:' + str(d['dead']) # file = r'C:/Users/Administrator/Desktop/world_data.txt' # with open(file, 'w+', encoding='utf-8') as f: # f.write(res + '\n') # 加\n换行显示 # f.close() world={} for i in response_data_1: temp=i['y']+'.'+i['date'] tup = time.strptime(temp, '%Y.%m.%d') dt = time.strftime('%Y-%m-%d', tup) # 改变时间格式,插入数据库 日期 # print(ds) c_name=i['name'] #国家 continent=i['continent'] #所属大洲 nowConfirm=i['nowConfirm'] #现有确诊 confirm=i['confirm'] #累计确诊 confirmAdd=i['confirmAdd'] #新增确诊 suspect=i['suspect'] #现有疑似 heal=i['heal'] #累计治愈 dead=i['dead'] #累计死亡 confirmAddCut=i['confirmAddCut'] confirmCompare=i['confirmCompare'] nowConfirmCompare=i['nowConfirmCompare'] healCompare=i['healCompare'] deadCompare=i['deadCompare'] world[c_name] = {'dt':dt , 'continent': continent, 'nowConfirm': nowConfirm, 'confirm': confirm, 'confirmAdd': confirmAdd, 'suspect': suspect, 'heal': heal, 'dead': dead, 'confirmAddCut': confirmAddCut, 'confirmCompare': confirmCompare, 'nowConfirmCompare': nowConfirmCompare, 'healCompare': healCompare, 'deadCompare': deadCompare, } return world
三、插入数据库
def insert_world(): """ 更新 world 表 :return: """ cursor = None conn = None try: dic = get_world_data() print(dic) conn, cursor = get_conn() sql = "insert into world values(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)" sql_query = 'select %s=(select dt from world order by id desc limit 1)' #对比当前最大时间戳 cursor.execute(sql_query,dic['美国']['dt']) if not cursor.fetchone()[0]: print(f"{time.asctime()}开始插入世界数据") for k, v in dic.items(): # item 格式 {'2021-01-13': {'confirm': 41, 'suspect': 0, 'heal': 0, 'dead': 1} cursor.execute(sql, [0,v.get('dt'), k, v.get("continent"), v.get("nowConfirm"), v.get("confirm"), v.get("confirmAdd"),v.get("suspect"),v.get("heal"), v.get("dead") , v.get("confirmAddCut"), v.get("confirmCompare"), v.get("nowConfirmCompare"), v.get("healCompare"), v.get("deadCompare")]) conn.commit() # 提交事务 print(f"{time.asctime()}插入世界数据完毕") else: print(f"{time.asctime()}世界数据已是最新数据!") except: traceback.print_exc() finally: close_conn(conn, cursor)
总结一下在完成这两个方法的过程中遇到的问题,首先是最基础的问题,数据的类型和格式的转换,这里主要是指json字符串和
Python里对应的数据对象(list和字典)。
(1)一般来讲对我们而言,需要抓取的是某个网站或者某个应用的内容,提取有用的价值。内容一般分为三部分,
结构化的数据、半结构化的数据和非机构化数据。
1.结构化数据:
可以用统一的结构加以表示的数据。可以使用关系型数据库表示和存储,表现为二维形式的数据,一般特点是:数据以行为单位,
一行数据表示一个实体的信息,每一行的数据的属性是相同的。
2.半结构化数据:
结构化数据的一种形式,并不符合关系型数据库或其他数据表的形式关联起来的数据模型结构,但包含相关标记,
用来分隔语义元素以及对记录和字段进行分层。因此他也被成为自描述的结构。常见的半结构数据有:html,xml和json等、
实际上是以树或者图的结构来存储的。
对于半结构化数据,节点中属性的顺序是不重要的,不同的半结构化数据的属性的个数是不一样的。这样的数据格式,
可以自由的表达很多有用的信息,
包含自描述信息。所以半结构化数据的扩展性很好,特别适合于在互联网中大规模传播。
3.非结构化数据
就是没有固定的结构。各种文档,图片,视频或者音频都属于非结构化数据。对于这类数据,我们一般直接整体进行存储,而且一般存储为二进制形式。
原文链接:/newsqa/v1/automation/foreign/country/ranklist' headers={'user-agent': 'WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36'} res = requests.get(url, headers=headers) # print(res.text) response_data_0 = json.loads(res.text.replace('jQuery34102848205531413024_1584924641755(', '')[:-1]) #转化json对象
这里进行了第一步解析,通过json.loads( ) 方法把从网页获取的json字符串数据转化成Python对应的list或者字典。
如果第一步解析之后data对应的value不是list,那么可以进行第二次解析,本次操作中,世界疫情数据的data对
应的数据是一个list,所以也就不需要进行第二次转化,可以直接通过list的下标去访问。
数据转化是必要的,在网络中json字符串传递小巧安全速度快,但是我们读取数据,如果直接对字符串进行操作
会非常不方便,所以我们需要解析json字符串,也就是通过json.loads()方法把字符串转化成Python对应的list或
者字典对象,这样我们访问操作这些数据会变得简单。
以上就是Python爬虫爬取全球疫情数据并存储到mysql数据库的步骤的详细内容,更多关于python 爬取疫情数据存储到mysql的资料请关注其它相关文章!