Python+Flask实现全国、全球疫情大数据可视化!
一、实现效果
最近简单学习了一下flask,决定来做一个疫情大数据的网页出来。话不多说先上效果图。还是比较喜欢这样的排版的。
二、编写工具类utils从数据库中获取数据
我们首先要明确每个部分要获取哪些信息。我们先看下数据格式
比如累计确诊的数据,我们只需要统计出当日的各地区确诊人数之和即能得到总的确诊人数,而不是对整列直接求和。因此每个表格的数据怎么获得需要简单思考一下。以下是工具类的代码。由于我们会处理两张结构一样的表,因此类的初始化参数定义为数据库库名称、要获取的表名称、数据库用户名、数据库密码。关于查询,是通过pandas读取数据库表,由pandas来操作数据。个人觉得这样写起来更方便。
import pymysql from sqlalchemy import create_engine import pandas as pd import datetime class utils: def __init__(self,db_name,table_name,user,password): self.db_name=db_name self.table_name=table_name self.user=user self.password=password self.data = self.querry() def get_conn(self): ''' :return:连接 ''' #创建连接 conn=pymysql.connect(host="127.0.0.1",port=3306,user=self.user,password=self.password, db=self.db_name,charset="utf8") cursor=conn.cursor() return conn,cursor def close_conn(self,conn,cursor): cursor.close() conn.close() def querry(self): #使用pandas从数据库中读取疫情数据 conn = create_engine('mysql://{}:{}@localhost:3306/{}?charset=utf8'.format(self.user,self.password,self.db_name)) sql="SELECT * FROM {}".format(self.table_name) epidemic = pd.read_sql(sql, con=conn) return epidemic def get_c1_data(self): ''' 获取c1的四个数据:累计确诊、累计治愈、累计死亡、新增死亡 :return: ''' df=self.data #获取最新数据 # 由于接口数据只能拿到前一天,因此我们的日期数据应该-1天 t = datetime.datetime.now() + datetime.timedelta(days=-1) t= t.strftime('%Y-%m-%d') today = df[df.日期 == t] dignose=str(today.确诊.sum()) heal=str(today.治愈.sum()) dead=str(today.死亡.sum()) add=str(today.新增死亡.sum()) return [dignose,heal,dead,add] def get_c2_data(self): ''' 获取中国各省的疫情数据 :return: ''' #将地区-确诊人数以键值对的形式保存 dict={} # 获取最新数据 # 由于接口数据只能拿到前一天,因此我们的日期数据应该-1天 df=self.data t = datetime.datetime.now() + datetime.timedelta(days=-1) t = t.strftime('%Y-%m-%d') today = df[df.日期 == t] for p,v in zip(today.疫情地区,today.确诊): dict[p]=v return dict def get_l1_data(self): ''' 获取疫情期间每日累计数据 :return: ''' df=self.data days=df.groupby("日期").sum() return days def get_l2_data(self): ''' 获取疫情期间每日新增数据 :return: ''' df=self.data days=df.groupby("日期").sum().diff().dropna() return days def get_r1_data(self): ''' 获取除湖北地区确诊人数最多的省份 :return: ''' dict={} df=self.data t = datetime.datetime.now() + datetime.timedelta(days=-1) t = t.strftime('%Y-%m-%d') today = df[df.日期 == t] #按确诊人数排序 today=today.sort_values(by='确诊',ascending=False)[:6] for key,value in zip(today.疫情地区,today.确诊): if key=='湖北': continue dict[key]=value return dict def get_r2_data(self): ''' 获取世界各国的疫情数据 :return: ''' #将地区-确诊人数以键值对的形式保存 dict={} # 获取最新数据 # 由于接口数据只能拿到前一天,因此我们的日期数据应该-1天 df=self.data t = datetime.datetime.now() + datetime.timedelta(days=-1) t = t.strftime('%Y-%m-%d') today = df[df.日期 == t] for p,v in zip(today.name,today.确诊): dict[p]=v return dict if __name__=="__main__": u=utils("myspider","world_epidemic","root","123456") print(list(u.get_r1_data().values()))
三、编写app.py
接着我们来编写flask的核心类app.py。注册路由。我们的路由命名规则直接按我们定义的main.html中的各部分的id名来命名。即左边第一个为l1,中间第二个为c2等等…。在各个方法中,我们需要将从数据库中获取的数据转换为json格式,用以传入到前台页面。代码如下:
from flask import Flask from flask import render_template from flask import jsonify import time import utils app = Flask(__name__) #工具类,初始化参数为数据库名,数据库表名,数据库账号,数据库密码 u=utils.utils("myspider","epidemic","root","123456") @app.route('/') def hello_world(): return render_template("main.html") @app.route('/time') def get_time(): time_str=time.strftime("%Y{}%m{}%d{}%X") return time_str.format("年","月","日") @app.route('/c1') def get_c1_data(): data=u.get_c1_data() print(data) return jsonify({"dignose":data[0],"heal":data[1],"dead":data[2],"newly_add":data[3]}) @app.route('/c2') def get_c2_data(): res=[] data=u.get_c2_data() for key,value in data.items(): res.append({"name":key,"value":value}) return jsonify({"data":res}) @app.route('/l1') def get_l1_data(): data=u.get_l1_data() day = [] for d in data.index: day.append(d.strftime("%m-%d")) print(day) dignose=data.确诊.tolist() heal=data.治愈.tolist() dead=data.死亡.tolist() return jsonify({"days":day,"dignose":dignose,"heal":heal,"dead":dead}) @app.route('/l2') def get_l2_data(): data = u.get_l2_data() day = [] for d in data.index: day.append(d.strftime("%m-%d")) dignose=data.确诊.tolist() heal=data.治愈.tolist() dead=u.get_l1_data().新增死亡.tolist() return jsonify({"days":day,"dignose":dignose,"heal":heal,"dead":dead}) @app.route('/r1') def get_r1_data(): data=u.get_r1_data() keys=list(data.keys()) values=list(data.values()) print(keys,values) return jsonify({"keys":keys,"values":values}) @app.route('/r2') def get_r2_data(): res=[] myutil=utils.utils("myspider","world_epidemic","root","123456") data=myutil.get_r2_data() for key, value in data.items(): res.append({"name": key, "value": value}) #还需要添加中国的总数据 china=int(u.get_c1_data()[0]) res.append({"name":"China","value":china}) return jsonify({"data": res}) if __name__ == '__main__': app.run()
四、ajax实现数据交互
这里我们定义一个控制器controller.js。用来获取当前时间,以及将数据库中得到的信息传递到echarts中并显示。
function gettime() { $.ajax({ url:"/time", timeout:10000, success:function (data) { $("#time").html(data) }, error:function (xhr,type,errorThrown) { } }) } function get_c1_data(){ $.ajax({ url:"/c1", timeout:10000, success:function (data) { $(".num h1").eq(0).text(data.dignose) $(".num h1").eq(1).text(data.heal) $(".num h1").eq(2).text(data.dead) $(".num h1").eq(3).text(data.newly_add) }, error:function (xhr,type,errorThrown) { } }) } function get_c2_data(){ $.ajax({ url:"/c2", timeout:10000, success:function (data) { ec_center_option.series[0].data=data.data ec_center.setOption(ec_center_option) }, error:function (xhr,type,errorThrown) { } }) } function get_l1_data(){ $.ajax({ url:"/l1", timeout:10000, success:function (data) { ec_left1_option.xAxis.data=data.days ec_left1_option.series[0].data=data.dignose ec_left1_option.series[1].data=data.heal ec_left1_option.series[2].data=data.dead ec_left1.setOption(ec_left1_option) }, error:function (xhr,type,errorThrown) { } }) } function get_l2_data(){ $.ajax({ url:"/l2", timeout:10000, success:function (data) { ec_left2_option.xAxis.data=data.days ec_left2_option.series[0].data=data.dignose ec_left2_option.series[1].data=data.heal ec_left2_option.series[2].data=data.dead ec_left2.setOption(ec_left2_option) }, error:function (xhr,type,errorThrown) { } }) } function get_r1_data(){ $.ajax({ url:"/r1", timeout:10000, success:function (data) { ec_right1_option.xAxis.data=data.keys ec_right1_option.series[0].data=data.values ec_right1.setOption(ec_right1_option) }, error:function (xhr,type,errorThrown) { } }) } function get_r2_data(){ $.ajax({ url:"/r2", timeout:10000, success:function (data) { ec_right2_option .series[0].data=data.data ec_right2.setOption(ec_right2_option) }, error:function (xhr,type,errorThrown) { } }) } gettime() get_c1_data() get_c2_data() get_l1_data() get_l2_data() get_r1_data() get_r2_data() setInterval(gettime,1000)
完整项目代码获取加群:850591259