基于Django的疫情数据可视化

题目一:疫情数据分析

文章目录

  • 实验要求
  • 实验目的
  • 实验环境
    • 1. 计算机环境
    • 2. 软件环境
  • 实验方法
    • 1. 查找方便爬取的疫情数据网站。
    • 2. 使用Django框架创建Python Web工程。
    • 3. 实现阶段
    • 4. 运行、调试、部署Web项目。
  • 实验过程
    • 1. 创建Django工程
    • 2. 查找合适的疫情数据获取网站
    • 3. 实现爬虫方法
    • 4. 设计创建Models
    • 5. 实现数据库操作方法
    • 6. 创建html页面
    • 7. 前后端交互业务逻辑部分views.py
  • 实验结果

实验要求

编写程序(用Java或Python或javascript)获取实时疫情数据,并进行统计分析,显示各种统计图。

实验目的

获取大数据,进行统计分析是大数据技术研究的基础。

  1. 巩固之前学习的Python、Django。

  2. 学习掌握数据可视化工具:echarts。

  3. 学习掌握爬虫流程与方法。

  4. 对收集的数据可视化。

  5. 提升遇到问题、解决问题的能力。

实验环境

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工作流程:
基于Django的疫情数据可视化_第1张图片

3. 实现阶段

设计、实现:html页面布局(即Template)、Model存储数据、View业务逻辑。

4. 运行、调试、部署Web项目。

在实现过程中多次运行,发现bug及时修改。

Utools上有个“内网穿透”的插件,可以把运行的Web通过外网查看,方便老师看到实现的效果。

基于Django的疫情数据可视化_第2张图片

实验过程

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. 查找合适的疫情数据获取网站

本实验采用的是腾讯的数据:

  1. 国外各国实时疫情数据

    地址: 新冠肺炎疫情最新动态,实时更新 - 腾讯

F12打开开发者模式可看到以下内容:

  • 反爬:Requests设置请求头Headers

在请求网页爬取的时候,输出的text信息中会出现抱歉,无法访问等字眼,这就是禁止爬取,需要通过反爬机制去解决这个问题。headers是解决requests请求反爬的方法之一,相当于我们进去这个网页的服务器本身,假装自己本身在爬取数据。对反爬虫网页,可以设置一些headers信息,模拟成浏览器取访问网站 。
基于Django的疫情数据可视化_第3张图片

  • 根据请求地址与请求方式爬取其中的疫情数据

基于Django的疫情数据可视化_第4张图片

  • 可以在Preview或Response中看到其中的数据,查找需要的数据。

基于Django的疫情数据可视化_第5张图片

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对应数据库中的表,属性对应字段。

  1. 定义模型类
  • 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)
  1. 模型迁移(建表)

迁移由两步完成 :

  • 生成迁移文件:根据模型类生成创建表的语句

    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文件


<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 3Dh3>
<form method="post">
    top(请输入数字):
    <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>



#}
{#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)) #

    #初次或未选择时,二者为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) #第二个参数表示返回的界面,第三个表示返回的数据(字典形式)

实验结果

基于Django的疫情数据可视化_第6张图片
基于Django的疫情数据可视化_第7张图片
基于Django的疫情数据可视化_第8张图片

基于Django的疫情数据可视化_第9张图片
基于Django的疫情数据可视化_第10张图片

你可能感兴趣的:(Python学习)