题目一:疫情数据分析
文章目录
实验要求
编写程序(用Java或Python或javascript)获取实时疫情数据,并进行统计分析,显示各种统计图。
实验目的
获取大数据,进行统计分析是大数据技术研究的基础。
-
巩固之前学习的Python、Django。
-
学习掌握数据可视化工具:echarts。
-
学习掌握爬虫流程与方法。
-
对收集的数据可视化。
-
提升遇到问题、解决问题的能力。
实验环境
1. 计算机环境
操作系统:Windows 10 (x64)
处理器:Intel® Core™ i5-7200U
内存:4.00GB
2. 软件环境
IDE:JetBrains PyCharm Professional Edition with Anaconda plugin 2019.2.6 x64
数据库:MySQL 5.55
Python版本:Python 3.7
Django版本:Django 1.11.11
实验方法
1. 查找方便爬取的疫情数据网站。
2. 使用Django框架创建Python Web工程。
Django是一个开放源代码的Web应用框架,由Python写成。采用了MTV的框架模式,即模型M,视图V和模版T。
Django 框架的核心组件有:
-
用于创建模型的对象关系映射;
-
为最终用户设计较好的管理界面;
-
URL 设计;
-
设计者友好的模板语言;
-
缓存系统。
Django 的 MTV 分别是指:
-
M模型(Model):编写程序应有的功能,负责业务对象与数据库的映射(ORM)。
-
T模板 (Template):负责如何把页面(html)展示给用户。
-
V视图(View):负责业务逻辑,并在适当时候调用 Model和 Template。
MTV工作流程:
3. 实现阶段
设计、实现:html页面布局(即Template)、Model存储数据、View业务逻辑。
4. 运行、调试、部署Web项目。
在实现过程中多次运行,发现bug及时修改。
Utools上有个“内网穿透”的插件,可以把运行的Web通过外网查看,方便老师看到实现的效果。
实验过程
1. 创建Django工程
-
创建Django项目
- django-admin startproject Cov_django
-
创建子应用
-
python manager.py startapp info
-
设置setting文件
#ALLOWED_HOSTS是一个字符串列表,代表了这个Django网站可以服务的主机名或域名。这是为了阻止HTTP Host头攻击而采用的一种安全措施 ALLOWED_HOSTS = ['covdjango.utools.club','127.0.0.1'] INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'info.apps.InfoConfig', #添加子应用 ] #数据库设置,默认数据库改为MySQL数据库 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'HOST': '127.0.0.1', # 数据库主机 'PORT': 3306, # 数据库端口 'USER': 'root', # 数据库用户名 'PASSWORD': '123456', # 数据库用户密码 'NAME': 'Cov_django' # 数据库名字 } } LANGUAGE_CODE = 'zh-Hans'#语言 TIME_ZONE = 'Asia/Shanghai'#时区 #静态文件 在static添加的任何静态文件都可以使用网址/static/文件在static中的路径来访问了 STATIC_URL = '/static/' STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'static'), ]
-
设置Cov_django访问地址urls.py文件
from django.contrib import admin from django.conf.urls import url,include urlpatterns = [ url(r'^admin/', admin.site.urls),#在设置管理员的情况下访问地址后以为admin/则进入到管理员界面 url(r'^',include('info.urls',namespace='info')),#根据正则表达式顺序匹配,匹配不成功就匹配下一个,直到匹配成功为止,全没匹配成功返回404 #第二个匹配成功后会进入到info下的urls继续进行二级匹配 ]
-
设置子应用下urls文件
from django.conf.urls import url from info.views import index app_name = 'info' urlpatterns = [ url(r'^$',index,name = 'index'), url(r'^index/$',index,name = 'index'),#连个都返回到views下index实现业务逻辑 ]
2. 查找合适的疫情数据获取网站
本实验采用的是腾讯的数据:
-
国外各国实时疫情数据
F12打开开发者模式可看到以下内容:
- 反爬:Requests设置请求头Headers
在请求网页爬取的时候,输出的text信息中会出现抱歉,无法访问等字眼,这就是禁止爬取,需要通过反爬机制去解决这个问题。headers是解决requests请求反爬的方法之一,相当于我们进去这个网页的服务器本身,假装自己本身在爬取数据。对反爬虫网页,可以设置一些headers信息,模拟成浏览器取访问网站 。
- 根据请求地址与请求方式爬取其中的疫情数据
- 可以在Preview或Response中看到其中的数据,查找需要的数据。
3. 实现爬虫方法
在info子应用下创建一个名为‘CrawlingDataUtils.py’爬虫工具文件,里面封装了爬虫方法
import requests #用于请求页面,得到相应内容
import json #将实现数据字到json的互相转换
import jsonpath #当遇到层级比较深的字典时,要想取值使用jsonpath取值比较方便,可以一下取到。
#获取每日全球数据信息
def get_globalStatis_data():
url = 'https://view.inews.qq.com/g2/getOnsInfo?name=disease_foreign' #请求地址
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36',
} #请求头,作用:伪装成浏览器反爬虫
#这个网址请求方式为get
r = requests.get(url, headers)
res = json.loads(r.text) # 将网页中的json字符串 转成 字典
data_all = json.loads(res['data']) #根据数据格式,进一步拆分数据,得到想要的data数据
lastUpdateTime = data_all['globalStatis']['lastUpdateTime'] # Time格式:YYYY-MM-DD HH:mm:ss
nowConfirm = data_all['globalStatis']['nowConfirm']
confirm = data_all['globalStatis']["confirm"]
heal = data_all['globalStatis']["heal"]
dead = data_all['globalStatis']["dead"]
nowConfirmAdd = data_all['globalStatis']['nowConfirmAdd']
confirmAdd = data_all['globalStatis']['confirmAdd']
healAdd = data_all['globalStatis']['healAdd']
deadAdd = data_all['globalStatis']['deadAdd']
#将上述数据组合成字典,方便返回与获取
globalStatis = {"lastUpdateTime": lastUpdateTime, "nowConfirm": nowConfirm, "confirm": confirm, "heal": heal,
"dead": dead,
"nowConfirmAdd": nowConfirmAdd, "confirmAdd": confirmAdd, "healAdd": healAdd,
"deadAdd": deadAdd}
return globalStatis
#获取外国数据
def get_foreign_data():
# 1.目标网站
url = 'https://api.inews.qq.com/newsqa/v1/automation/foreign/country/ranklist'
# 2.请求资源 Request Method: POST
resp = requests.post(url)
# print(resp.text)
# 3.提取数据
# 类型转换 json-->dict
data = json.loads(resp.text)
# print(type(data))
# for i in range(0,len(data['data'])) :
# print(data['data'][i]['name'])
# data是我们的内容,$表示根节点下,而$..name表示根节点下的任意层级name键值的部分
name = jsonpath.jsonpath(data, "$..name")#JsonPath是一种简单的方法来提取给定JSON文档的部分内容
confirm = jsonpath.jsonpath(data, "$..confirm") #返回是各个国家的confirm组成的列表
confirmAdd = jsonpath.jsonpath(data, "$..confirmAdd")
confirmCompare = jsonpath.jsonpath(data, "$..confirmCompare")
date = jsonpath.jsonpath(data, "$..date")
dead = jsonpath.jsonpath(data, "$..dead")
deadCompare = jsonpath.jsonpath(data, "$..deadCompare")
heal = jsonpath.jsonpath(data, "$..heal")
healCompare = jsonpath.jsonpath(data, "$..healCompare")
nowConfirm = jsonpath.jsonpath(data, "$..nowConfirm")
nowConfirmCompare = jsonpath.jsonpath(data, "$..nowConfirmCompare")
#zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。
#返回的是[(一个国家各项数据组成的元组),(一个国家各项数据组成的元组)...]
data_list = list(zip(name,confirm,confirmAdd,confirmCompare,date,dead,deadCompare,heal,healCompare,nowConfirm,nowConfirmCompare))
#返回各项数据,其中data_list是方便向数据库中添加一条数据,其他的方便echarts使用(echarts坐标为列表形式的数据)
return [name,confirm,confirmAdd,confirmCompare,date,dead,deadCompare,heal,healCompare,nowConfirm,nowConfirmCompare,data_list]
#获取美国历史确诊数据
def get_USA_history_confirm_data():
url = 'https://api.inews.qq.com/newsqa/v1/automation/modules/list?modules=FAutoCountryMerge'
resp = requests.post(url)
dic = json.loads(resp.text)
nation_data = dic['data']['FAutoCountryMerge']
usaData = nation_data['美国']['list']
# 由字典组成的列表 [{'date': '01.28', 'confirm': 5},{'date': '01.29', 'confirm': 5},...]
return usaData
#获取全球每日数据
def get_GlobalDailyList():
url = 'https://api.inews.qq.com/newsqa/v1/automation/modules/list?modules=FAutoGlobalStatis,FAutoContinentStatis,FAutoGlobalDailyList,FAutoCountryConfirmAdd'
resp = requests.post(url)
dic = json.loads(resp.text)
ls = dic['data']['FAutoGlobalDailyList'] #list 昨天以前全球疫情数据
today = dic['data']['FAutoGlobalStatis'] #字典 今天全球疫情数据
#[{'date': '01.28',
# 'all': {'confirm': 57,
# 'dead': 0,
# 'heal': 3,
# 'newAddConfirm': 0,
# 'deadRate': '0.00',
# 'healRate': '5.26'}},
# {'date': '01.29',
# 'all': {'confirm': 74,
# 'dead': 0,
# 'heal': 3,
# 'newAddConfirm': 13,
# 'deadRate': '0.00',
# 'healRate': '4.05'}},......]
return {'ls':ls,'today':today}
#整合历史数据 :日期date/美国确诊usaconfirm/全球确诊、全球死亡、全球治愈、全球新增,方便插入数据库中
def get_all_data():
usaData = get_USA_history_confirm_data()
all_date = jsonpath.jsonpath(usaData, "$..date")
USA_history_confirm = jsonpath.jsonpath(usaData, "$..confirm")
#全球历史疫情数据
ls = get_GlobalDailyList()['ls']
today = get_GlobalDailyList()['today']
before_confirm = jsonpath.jsonpath(ls,"$..confirm")
before_dead = jsonpath.jsonpath(ls,"$..dead")
before_heal = jsonpath.jsonpath(ls,"$..heal")
before_newAddConfirm = jsonpath.jsonpath(ls,"$..newAddConfirm") #新增确诊
today_confirm = today['confirm']
today_dead = today['dead']
today_heal = today['heal']
today_confirmAdd = today['confirmAdd']
before_confirm.append(today_confirm)
# print(all_confirm):None append这个操作是没有返回值的(即返回一个None),b.append(a) append只更新b本身,正确的写法应该分开写:
before_dead.append(today_dead)
#all_dead = before_dead #before_dead 添加完today的数据,就为全的数据了 ==all_dead
before_heal.append(today_heal)
before_newAddConfirm.append(today_confirmAdd)
datalist = list(zip(all_date,USA_history_confirm,before_confirm,before_dead,before_heal,before_newAddConfirm))
return datalist
#https://voice.baidu.com/newpneumonia/get?target=trend&isCaseIn=1&stage=publish&callback=jsonp_1594382062559_46273
#https://voice.baidu.com/act/newpneumonia/newpneumonia#tab4 有国外的历史数据
4. 设计创建Models
Models中的class对应数据库中的表,属性对应字段。
- 定义模型类
- 在
models.py
中定义模型类,继承自models.Model
#定义模型类
from django.db import models
# Create your models here.
class foreign_data(models.Model):
date = models.DateField(verbose_name='更新时间')
name = models.CharField(max_length=20,verbose_name='国家')
confirm = models.IntegerField(verbose_name='确认总数')
confirmAdd = models.IntegerField(verbose_name='新增确诊人数')
heal = models.IntegerField(verbose_name='治愈人数')
dead = models.IntegerField(verbose_name='死亡人数')
nowConfirm = models.IntegerField(verbose_name='现存确诊')
class Meta:
#改表名
db_table = 'foreign_data'
#修改后台admin对的显示信息的配置
verbose_name_plural = '国外疫情数据(每个国家不同日期的数据)'
def __str__(self):
#后台显示
return self.name +':' + str(self.date)
class globalStatic(models.Model):
lastUpdateTime = models.DateTimeField(verbose_name='更新时间')
nowConfirm = models.IntegerField(verbose_name='现存确诊')
confirm = models.IntegerField(verbose_name='确认总数')
heal = models.IntegerField( verbose_name='治愈人数')
dead = models.IntegerField(verbose_name='死亡人数')
nowConfirmAdd = models.IntegerField(verbose_name='新增现存确诊人数')
confirmAdd = models.IntegerField(verbose_name='新增确诊人数')
healAdd = models.IntegerField(verbose_name='新增治愈人数')
deadAdd = models.IntegerField(verbose_name='新增死亡人数')
class Meta:
# 改表名
db_table = 'globalStatic'
# 修改后台admin对的显示信息的配置
verbose_name_plural = '全球疫情总数据'
def __str__(self):
return '更新时间'+str(self.lastUpdateTime)
class USA_history_confirm_data(models.Model):
date = models.DateField(verbose_name='日期')
confirm = models.IntegerField(verbose_name='确认数')
class Meta:
# 改表名
db_table = 'USA_history_confirm_data'
# 修改后台admin对的显示信息的配置
verbose_name_plural = '美国历史疫情数据'
def __str__(self):
return '日期:'+str(self.date)
#全球疫情实体类
class usa_global_all_data(models.Model):
date = models.DateField(verbose_name='日期')
usaconfirm = models.IntegerField(verbose_name='美国确诊')
confirm = models.IntegerField(verbose_name='全球确诊')
dead = models.IntegerField(verbose_name='全球死亡')
heal = models.IntegerField(verbose_name='全球治愈')
confirmAdd = models.IntegerField(verbose_name='全球新增')
class Meta:
# 改表名
db_table = 'usa_global_all_data'
# 修改后台admin对的显示信息的配置
verbose_name_plural = '美国和全球历史疫情数据'
def __str__(self):
return '日期:'+str(self.date)
- 模型迁移(建表)
迁移由两步完成 :
-
生成迁移文件:根据模型类生成创建表的语句
python manage.py makemigrations
-
执行迁移:根据第一步生成的语句在数据库中创建表
python manage.py migrate
5. 实现数据库操作方法
在info子应用下创建一个名为‘dbUtils.py’数据库操作工具文件,里面封装了数据库操作方法
from info.models import globalStatic,foreign_data,USA_history_confirm_data,usa_global_all_data
from info.CrawlingDataUtils import get_globalStatis_data,get_foreign_data,get_USA_history_confirm_data,get_all_data
import time
# 数据库中添加foreign_data
def insert_foreign_data():
foreignData = get_foreign_data()
ls = foreignData[11] #数据下标为11的数据是每个(国家数据的元组)组成的列表
print(f"{time.asctime()}开始插入各国数据")
for i in range(0,len(ls)):
ds = "2020." + ls[i][4]
tup = time.strptime(ds, "%Y.%m.%d")
date = time.strftime("%Y-%m-%d", tup)
foreign_data.objects.get_or_create(
#get_or_create若数据库中没有这条数据就插入,若已存在就不插入,避免数据是重复
date=date,
name=ls[i][0],
confirm=ls[i][1],
confirmAdd=ls[i][2],
heal=ls[i][7],
dead=ls[i][5],
nowConfirm=ls[i][9],
)
print(f"{time.asctime()}插入数据完毕")
def insert_globalStatic():
dict = get_globalStatis_data() # 全球数据字典
print(f"{time.asctime()}开始插入全球数据")
globalStatic.objects.get_or_create(
lastUpdateTime=dict['lastUpdateTime'],
nowConfirm=dict['nowConfirm'],
confirm=dict['confirm'],
heal=dict['heal'],
dead=dict['dead'],
nowConfirmAdd=dict['nowConfirmAdd'],
confirmAdd=dict['confirmAdd'],
healAdd=dict['healAdd'],
deadAdd=dict['deadAdd'],
)
print(f"{time.asctime()}插入数据完毕")
def insert_USA_history_confirm_data():
ls = get_USA_history_confirm_data()
print(f"{time.asctime()}开始插入美国历史疫情数据")
for i in ls :
ds = "2020." + i['date']
tup = time.strptime(ds, "%Y.%m.%d")
date = time.strftime("%Y-%m-%d", tup)
USA_history_confirm_data.objects.get_or_create(
date=date,
confirm = i['confirm'],
)
print(f"{time.asctime()}插入数据完毕")
def insert_usa_global_all_data():
ls = get_all_data()
print(f"{time.asctime()}开始插入美国和全球历史疫情数据")
for i in ls:
ds = "2020." + i[0]
tup = time.strptime(ds, "%Y.%m.%d")
date = time.strftime("%Y-%m-%d", tup)
usa_global_all_data.objects.get_or_create(
date=date,
usaconfirm=i[1],
confirm=i[2],
dead=i[3],
heal=i[4],
confirmAdd=i[5]
)
print(f"{time.asctime()}插入数据完毕")
def selectData_ByDate(select_date,top):
#根据选择的日期,返回(显示)排名前五的国家疫情数据 (国家名一个列表,每种数据一个列表)
datas = foreign_data.objects.filter(date=select_date).order_by('-confirm')[0:top]
# print(datas[0].name) #美国
ls_name = []
ls_confirm = []
ls_dead = []
ls_heal = []
ls_confirmAdd = []
ls_nowConfirm = []
for i in datas:
ls_name.append(i.name)
ls_confirm.append(i.confirm)
ls_dead.append(i.dead)
ls_heal.append(i.heal)
ls_confirmAdd.append(i.confirmAdd)
ls_nowConfirm.append(i.nowConfirm)
return {'ls_name':ls_name,'ls_confirm':ls_confirm,'ls_dead':ls_dead,'ls_heal':ls_heal,'ls_confirmAdd':ls_confirmAdd,'ls_nowConfirm':ls_nowConfirm}
6. 创建html页面
在templates文件夹中创建一个名为‘index’的html文件
<!DOCTYPE html>
<html style="height: 100%">
<head>
<meta charset="UTF-8">
<title>疫情数据显示</title>
</head>
<body style="height: 100%; margin: 0">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts/dist/echarts.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts-gl/dist/echarts-gl.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts-stat/dist/ecStat.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts/dist/extension/dataTool.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts/map/js/china.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts/map/js/world.js"></script>
<script type="text/javascript" src="https://api.map.baidu.com/api?v=2.0&ak=xfhhaTThl11qYVrqLZii6w8qE5ggnhrY&__ec_v__=20190126"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts/dist/extension/bmap.min.js"></script>
<div>
<form method="post">
<h3>1.将最新疫情数据存入数据库</h3>
<select name="Refresh">
<option value="Refresh">刷新</option>
<option value="noRefresh">不刷新</option>
</select>
<input type="submit" value="选择">
</form>
</div>
<h3>2.查看国外疫情数据</h3>
来源:数据库---时间范围:[6.27,今天] (中间有几天忘记存了,会没有数据)<br>
请选择:<br>
<form method="post">
日期:<input type="text" id="test11" name="selectDate">
Top(请输入数字):<input type="text" name="top">
{# 选择日期看 #}
<input type="submit" value="查看">
</form>
<script src="../static/laydate/laydate.js"></script> <!-- 改成你的路径 -->
<script>
//执行一个laydate实例,选择日期时出现日历形式
//自定义格式
laydate.render({
elem: '#test11'
,format: 'yyyy-MM-dd'
,done: function(value) {
{#alert(value); //得到日期生成的值,如:2017-08-18#}
}
});
</script>
<p>查看 日期:{{ selectDate }},疫情严重程度 Top:{{ top_str }}国家的疫情数据:</p>
<div id="container1" style="height: 100%"></div>
<script type="text/javascript">
var dom = document.getElementById("container1");
var myChart = echarts.init(dom);
var app = {};
option = null;
option = {
tooltip: {
trigger: 'axis',
axisPointer: { // 坐标轴指示器,坐标轴触发有效
type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
}
},
legend: {
data: ['确诊', '死亡', '治愈', '新增确诊', '现存确诊']
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'value'
},
yAxis: {
type: 'category',
data: {{foregin_name|safe}} // 后台views中返回的数据,|safe表示禁用转义,告诉模板这个变量是安全的,可以解释执行
},
series: [
{
name: '确诊',
type: 'bar',
stack: '总量',
label: {
show: true,
position: 'insideRight'
},
data: {{foregin_confirm}}
},
{
name: '死亡',
type: 'bar',
stack: '总量',
label: {
show: true,
position: 'insideRight'
},
data: {{foregin_dead}}
},
{
name: '治愈',
type: 'bar',
stack: '总量',
label: {
show: true,
position: 'insideRight'
},
data: {{foregin_heal}}
},
{
name: '新增确诊',
type: 'bar',
stack: '总量',
label: {
show: true,
position: 'insideRight'
},
data: {{foregin_confirmAdd}}
},
{
name: '现存确诊',
type: 'bar',
stack: '总量',
label: {
show: true,
position: 'insideRight'
},
data: {{foregin_nowConfirm}}
}
]
};;
if (option && typeof option === "object") {
myChart.setOption(option, true);
}
</script>
<h3>3.历史疫情数据趋势图</h3>
<div id="container" style="height: 100%"></div>
<script type="text/javascript">
var dom = document.getElementById("container");
var myChart = echarts.init(dom);
var app = {};
option = null;
option = {
title: {
text: '历史疫情数据'
},
tooltip: {
trigger: 'axis'
},
legend: {
data: ['美国确诊','全球确诊','全球死亡','全球治愈','全球新增']
{# 线 #}
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
toolbox: {
feature: {
saveAsImage: {}
}
},
xAxis: {
type: 'category',
boundaryGap: false,
data: {{all_date|safe}},
name: '日期'
},
yAxis: {
type: 'value',
name:'人数'
},
series: [
{
name: '美国确诊',
type: 'line',
stack: '美国确诊',
data: {{USA_history_confirm}}
},
{
name: '全球确诊',
type: 'line',
stack: '全球确诊',
data: {{all_confirm}}
},
{
name: '全球死亡',
type: 'line',
stack: '全球死亡',
data: {{all_dead}}
},
{
name: '全球治愈',
type: 'line',
stack: '全球治愈',
data: {{all_heal}}
},
{
name: '全球新增',
type: 'line',
stack: '全球新增',
data: {{all_confirmAdd}}
}
]
};
;
if (option && typeof option === "object") {
myChart.setOption(option, true);
}
</script>
<h3>4.今日top 3D</h3>
<form method="post">
top(请输入数字):<input type="text" name = '3dtop'>
<input type="submit">
</form>
<p>top:{{ n_str }} , 国家:{{ topname|safe }}</p>
<div id="3d" style="height: 100%"></div>
<script type="text/javascript">
var dom = document.getElementById("3d");
var myChart = echarts.init(dom);
var app = {};
option = null;
var nation = {{topname|safe}};
var data_type = ['确诊', '死亡', '治愈',
'新增确诊', '现存确诊'];
var data = {{ topdata|safe }};
option = {
tooltip: {},
visualMap: {
max: 20,
inRange: {
color: ['#313695', '#4575b4', '#74add1', '#abd9e9', '#e0f3f8', '#ffffbf', '#fee090', '#fdae61', '#f46d43', '#d73027', '#a50026']
}
},
xAxis3D: {
type: 'category',
data: data_type
},
yAxis3D: {
type: 'category',
data: nation
},
zAxis3D: {
type: 'value'
},
grid3D: {
boxWidth: 200,
boxDepth: 80,
light: {
main: {
intensity: 1.2
},
ambient: {
intensity: 0.3
}
}
},
series: [{
type: 'bar3D',
data: data.map(function (item) {
return {
value: [item[1], item[0], item[2]]
}
}),
shading: 'color',
label: {
show: false,
textStyle: {
fontSize: 16,
borderWidth: 1
}
},
itemStyle: {
opacity: 0.4
},
emphasis: {
label: {
textStyle: {
fontSize: 20,
color: '#900'
}
},
itemStyle: {
color: '#900'
}
}
}]
};
if (option && typeof option === "object") {
myChart.setOption(option, true);
}
</script>
<!--
<form method="get" title="选择日期" name="date" action="">
</form>
<form>
<input type="checkbox" value="美国" name="nation">美国
<input type="checkbox" value="日本" name="nation">日本
<input type="submit">
</form>
<h3 align="center">
{# {% for foo in nation %}#}
{# {{ foo }}#}
{# {% endfor %}#}
{# 的数据</h3>#}
{#{% for foo in nation %}#}
{# {{ foo }}#}
{#{% endfor %}#}
{##}
{#<h3 align="center">{{ amricao.name }}的数据</h3>#}
{#-->#}
{#</body>#}
{#</html>#}
7. 前后端交互业务逻辑部分views.py
from django.shortcuts import render
from django.http import HttpRequest,HttpResponse
import jsonpath,datetime
from info.CrawlingDataUtils import get_USA_history_confirm_data,get_foreign_data,get_globalStatis_data,get_GlobalDailyList
from info.dbUtils import insert_foreign_data,insert_globalStatic,insert_usa_global_all_data,insert_USA_history_confirm_data,selectData_ByDate
# from django.contrib.auth.mixins import LoginRequiredMixin
# Create your views here.
def index(request):
#刷新按钮:爬取最新数据并插入到数据库中
Refresh = request.POST.get('Refresh') #根据表单中标签name
if Refresh == 'Refresh':
insert_USA_history_confirm_data()
insert_globalStatic()
insert_foreign_data()
insert_usa_global_all_data()
# nation = request.GET.getlist('nation')
selectDate = request.POST.get('selectDate')
top_str = request.POST.get('top')
# print(selectDate)
# print(type(selectDate)) #<class 'str'>
#初次或未选择时,二者为None,进不去导致foregin_confirm等,没赋值导致context处出错
#先定义一个空列表
foregin_name = []
foregin_confirm = []
foregin_confirmAdd = []
foregin_heal = []
foregin_dead = []
foregin_nowConfirm = []
if (selectDate != None and top_str != None) and (selectDate != '' and top_str != ''):
top = int(str(top_str))
#选择日期将str转化成date
select_date = datetime.datetime.strptime(selectDate, '%Y-%m-%d').date()
foregin_dic = selectData_ByDate(select_date,top)
foregin_name = foregin_dic['ls_name']
foregin_confirm = foregin_dic['ls_confirm']
foregin_confirmAdd = foregin_dic['ls_confirmAdd']
foregin_heal = foregin_dic['ls_heal']
foregin_dead = foregin_dic['ls_dead']
foregin_nowConfirm = foregin_dic['ls_nowConfirm']
else:
selectDate = '____'
top_str = '____'
# print(type(selectDate))
#print(type(selectDate))
# 美国历史数据,最终目的返回 两个列表:USA_history_date、USA_history_confirm 供echarts使用
usaData = get_USA_history_confirm_data()
all_date = jsonpath.jsonpath(usaData, "$..date")
USA_history_confirm = jsonpath.jsonpath(usaData, "$..confirm")
#全球历史疫情数据
ls = get_GlobalDailyList()['ls']
today = get_GlobalDailyList()['today']
before_confirm = jsonpath.jsonpath(ls,"$..confirm")
before_dead = jsonpath.jsonpath(ls,"$..dead")
before_heal = jsonpath.jsonpath(ls,"$..heal")
before_newAddConfirm = jsonpath.jsonpath(ls,"$..newAddConfirm") #新增确诊
today_confirm = today['confirm']
today_dead = today['dead']
today_heal = today['heal']
today_confirmAdd = today['confirmAdd']
before_confirm.append(today_confirm)
# print(all_confirm):None append这个操作是没有返回值的(即返回一个None),b.append(a) append只更新b本身,正确的写法应该分开写:
before_dead.append(today_dead)
#all_dead = before_dead #before_dead 添加完today的数据,就为全的数据了 ==all_dead
before_heal.append(today_heal)
before_newAddConfirm.append(today_confirmAdd)
#当日外国数据 3d使用 整合坐标数据
n_str = request.POST.get('3dtop')
topdata = []
topname = []
if n_str != None and n_str != '' :
n = int(n_str)
topname = get_foreign_data()[0][0:n]#前n名 国家名字
topconfirm = get_foreign_data()[1][0:n]
topdead = get_foreign_data()[5][0:n]
topheal = get_foreign_data()[7][0:n]
topconfirmAdd = get_foreign_data()[2][0:n]
topnowConfirm = get_foreign_data()[9][0:n]
toplist = list(zip(topconfirm,topdead,topheal,topconfirmAdd,topnowConfirm))
for i in range(0,len(topname)):
# for j in : # 显示5个: ['确诊', '死亡', '治愈','新增确诊', '现存确诊'];
for j,k in zip(range(0, 5), toplist[i]): # python 如何在一个for循环中遍历两个列表,利用python自带的zip函数可同时对两个列表进行遍历,代码如下
temp = [i, j, k]
topdata.append(temp)
else:
n_str = '___'
context = {
#全球、美国 历史数据
'all_date':all_date,
'USA_history_confirm':USA_history_confirm,
'all_confirm':before_confirm,
'all_dead':before_dead,
'all_heal':before_heal,
'all_confirmAdd':before_newAddConfirm,
#选择日期,选择显示个数,显示外国疫情数据可视化
'selectDate':selectDate,
'top_str':top_str,
'foregin_name':foregin_name,
'foregin_confirm':foregin_confirm,
'foregin_confirmAdd':foregin_confirmAdd,
'foregin_heal':foregin_heal,
'foregin_dead':foregin_dead,
'foregin_nowConfirm':foregin_nowConfirm,
'topname':topname,
'topdata':topdata,
'n_str':n_str
}
return render(request,'index.html',context=context) #第二个参数表示返回的界面,第三个表示返回的数据(字典形式)
实验结果