Python+Flask实现全国、全球疫情大数据可视化(一):爬取疫情数据并保存至mysql数据库
Python+Flask实现全国、全球疫情大数据可视化(二):网页页面布局+echarts可视化中国地图、世界地图、柱状图和折线图
最近简单学习了一下flask,决定来做一个疫情大数据的网页出来。
话不多说先上效果图。还是比较喜欢这样的排版的。
我们首先要明确每个部分要获取哪些信息。
我们先看下数据格式
比如累计确诊的数据,我们只需要统计出当日的各地区确诊人数之和即能得到总的确诊人数,而不是对整列直接求和。因此每个表格的数据怎么获得需要简单思考一下。以下是工具类的代码。由于我们会处理两张结构一样的表,因此类的初始化参数定义为数据库库名称、要获取的表名称、数据库用户名、数据库密码。
关于查询,是通过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()))
接着我们来编写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()
这里我们定义一个控制器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)
关注以下公众号,回复"0007"即可get完整项目源码