Python新型冠状病毒疫情数据自动爬取+统计+发送报告+数据屏幕(二)统计篇

在这里插入图片描述

新型冠状病毒其实没那么可怕,但是它赶上了空前绝后哺乳动物大迁徙

殷忧启圣,多难兴邦

项目功能设计:
  1. 定时爬取疫情数据存入Mysql (已完成)
  2. 进行数据分析制作疫情报告
  3. 使用itchat给亲人朋友发送分析报告
  4. 基于Django做数据屏幕
  5. 使用Tableau做数据分析
来看看最终效果在这里插入图片描述

目前已经完成80% 完成后第一时间分享给大家

需要用到Mysql数据库

前面说到要将数据存储到Mysql数据库, 这是数据库创建SQL语句

create table all_data
(
    id             int auto_increment comment '主键'
        primary key,
    cityName       varchar(255) charset utf8 null comment '姓名',
    confirmedCount int(255)                  null comment '确诊',
    curedCount     int(255)                  null comment '治愈',
    deadCount      int(255)                  null comment '死亡',
    province_name  varchar(255) charset utf8 null comment '省份',
    date_info      varchar(255) charset utf8 null comment '日期',
    detail_time    varchar(255) charset utf8 null comment '时间',
    cycle          varchar(255) charset utf8 null comment 'cycle'
)
    charset = latin1;

接下来我们介绍数据统计分析

  • 我们的目的是通过微信或短信接口自动给发送数据报告信息提醒家人,效果如下
您好!
我是你的智能疫情监控机器人
现在是北京时间: 21:12:35 星期一
[0203] 西安天气:多云转晴,白天 9℃,夜晚 -3℃,西风转东风,<3级
在十二小时内
全国内陆30个地区:
总病例:17302
全国新增病例:165
西安新增病例:8 积累病例:55
陕西积累病例:128
下面是新增疫情详细数据:
广东新增病例: 42
北京新增病例: 21
福建新增病例: 20
山东新增病例: 13
陕西新增病例: 12
重庆新增病例: 12
上海新增病例: 10
云南新增病例: 9
天津新增病例: 8
内蒙古新增病例: 7
宁夏新增病例: 3
黑龙江新增病例: 3
辽宁新增病例: 3
青海新增病例: 2
疫情期间,注意保护好自己和家人的健康!
  • 先看看数据吧
    在这里插入图片描述
    看过前面文章的朋友应该知道这些字段的含义, 唯一需要提到的是cycle这个字段,它表示爬取的次数, 第一次,第二次, 我的程序是每天定时爬取两次, 早晚九点收集各收集一次

  • 读取相关数据

number = pd.read_sql("select cycle from all_data order by id DESC limit 1", coon)["cycle"].to_list()[0]
data1 = pd.read_sql("select * from all_data where cycle = %s" % number, coon)
data2 = pd.read_sql("select * from all_data where cycle = %s" % (int(number) - 1), coon)
  1. number : 用来确定最新的数据
  2. data1: 最新数据
  3. data2: 历史最新数据
  • 获取时间
 def get_week_day(date):
 	week_day = {
            0: '星期一',
            1: '星期二',
            2: '星期三',
            3: '星期四',
            4: '星期五',
            5: '星期六',
            6: '星期日',
        }
	day = date.weekday()
	return week_day[day]
  • 使用pandas提取总增长人数
add_all_num = data1["confirmedCount"].sum() - data2["confirmedCount"].sum()  # 总新增人数
  • 使用pandas提取本地数据
sx_all = data1[data1["province_name"] == importance_province]["confirmedCount"].sum()  # 省份总感染人数
add_xian = int(data1[data1["cityName"] == importance_city]["confirmedCount"]) - int(data2[data2["cityName"] == importance_city]["confirmedCount"])  # 本地新增感染人数
xian_all = int(data1[data1["cityName"] == importance_city]["confirmedCount"])  # 本地感染总人数
  • 统计新增感染地区的数据
temp_a1 = data1.groupby("province_name")["confirmedCount"].sum()
temp_a2 = data2.groupby("province_name")["confirmedCount"].sum()
add_city = (temp_a1 - temp_a2).sort_values(ascending=False)
add_city = add_city[add_city.values != 0]  # 新增地区及人数

在这里插入图片描述

  • 获取天气数据
    天气数据以及聊天功能使用的是一个免费的聊天机器人的聊天机器人API 青云客聊天机器人API 有机会自己也训练个练一练, 这次先用这个API 非常不错!
import requests
import json


def get_window():
    url = "http://api.qingyunke.com/api.php?key=free&appid=0&msg=%E8%A5%BF%E5%AE%89%E5%A4%A9%E6%B0%94"
    response = requests.get(url)
    content = json.loads(response.content.decode())
    if content["result"]:
        return "未获取到天气信息"
    else:
        return content["content"]

如果想要获取不同地区的天气自行修改key=中文编码

下面是完整代码(运行前提是Mysql配置完成)
import re
import time
import json
import datetime
import requests
import pymysql
import pandas as pd


class VirusSupervise(object):
    def __init__(self):
        self.url = 'https://3g.dxy.cn/newh5/view/pneumonia?scene=2&clicktime=1579582238&enterid=1579582238&from=timeline&isappinstalled=0'
        self.all_data = list()
        self.host_ip = "127.0.0.1"  # 数据库地图
        self.host_user = "root"  # 用户
        self.password = 111111  # 数据库密码

    def request_page(self):
        """
        请求页面数据
        """
        res = requests.get(self.url)
        res.encoding = 'utf-8'
        pat0 = re.compile('window.getAreaStat = ([\s\S]*?)</script>')
        data_list = pat0.findall(res.text)
        data = data_list[0].replace('}catch(e){}', '')
        data = eval(data)
        return data

    def deep_spider(self, data, province_name):
        """
        深度提取出标签里详细的数据
        :param data:
        :param province_name:
        :return:
        """
        for temp_data in data:
            self.all_data.append([temp_data["cityName"], temp_data["confirmedCount"], temp_data["curedCount"],
                                  temp_data["deadCount"], province_name, datetime.date.today(),
                                  datetime.datetime.now().strftime('%H:%M:%S')])

    def filtration_data(self):
        """
        过滤数据
        """
        temp_data = self.request_page()
        province_short_names, confirmed_counts, cured_counts, dead_counts = list(), list(), list(), list()
        for i in temp_data:
            province_short_names.append(i['provinceShortName'])  # 省份
            confirmed_counts.append(i['confirmedCount'])  # 确诊
            cured_counts.append(i['curedCount'])  # 治愈
            dead_counts.append(i['deadCount'])  # 死亡
            self.deep_spider(i['cities'], i["provinceShortName"])  # 深度解析数据添加到实例属性中

        data_all = pd.DataFrame(self.all_data, columns=["城市", "确诊", "治愈", "死亡", "省份", "日期", "时间"])
        # print(data_all[data_all["省份"] == "陕西"])
        df = pd.DataFrame()
        df['省份'] = province_short_names
        df['确诊'] = confirmed_counts
        df['治愈'] = cured_counts
        df['死亡'] = dead_counts
        print(df)
        # data_all.to_csv("疫情数据_1.csv", encoding="utf_8_sig")
        return data_all

    def insert_wis_sql(self):
        data = self.filtration_data()

        coon = pymysql.connect(host=self.host_ip, user=self.host_user, password=self.password, database="epidemic_data",
                                    charset="utf8")
        number = int(pd.read_sql("select cycle from all_data order by id DESC limit 1", coon)["cycle"].to_list()[0]) + 1
        print("正在向阿里云服务器插入数据: ", number)
        cursor = coon.cursor()  # 创建事务
        sql = "insert into all_data(cityName, confirmedCount, curedCount, deadCount, province_name, " \
              "date_info, detail_time, cycle) values(%s, %s, %s, %s, %s, %s, %s, %s)"

        print("正在插入数据...")
        for cityName, confirmedCount, curedCount, deadCount, province_name, date_info, detail_time in zip(data["城市"],
                        data["确诊"], data["治愈"], data["死亡"], data["省份"], data["日期"], data["时间"]):
            cursor.execute(sql, (cityName, confirmedCount, curedCount, deadCount, province_name, date_info, detail_time, number))
            coon.commit()
        print("数据插入完成...")
        cursor.close()
        coon.close()

    def data_analysis(self):
        """
        数据分析返回结果
        :return:
        """
        importance_province = "陕西"  # 你所在的省市(注意数据库里是否有此数据)
        importance_city = "西安"  # 你所在的城市(同上) result中的需要自己修改
        result = "您好!\n我是你的智能疫情监控机器人ABL\n现在是北京时间: %s %s\n%s\n在十二小时内\n全国内陆" \
                 "30个地区:\n总病例:%s\n全国新增病例:%s\n西安新增病例:%s 积累病例:%s\n陕西积累病例:%s\n下面是新增疫情详细数据:%s疫情期间,注意保护好自己和家" \
                 "人的健康\n如什么问题可以问我哦"  # 时间 天气 昨天时间 今日时间 疫情数据
        coon = pymysql.connect(host=self.host_ip, user=self.host_user, password=self.password, database="epidemic_data",
                               charset="utf8")
        number = pd.read_sql("select cycle from all_data order by id DESC limit 1", coon)["cycle"].to_list()[0]
        data1 = pd.read_sql("select * from all_data where cycle = %s" % number, coon)
        data2 = pd.read_sql("select * from all_data where cycle = %s" % (int(number) - 1), coon)
        now_time = data1.date_info.unique()[0] + " " + data1.detail_time.unique()[0]  # 查询数据收集时间
        week_info = self.get_week_day(datetime.date.today())
        weather = self.get_window()  # 天气数据
        all_num = data1["confirmedCount"].sum()  # 目前总人数
        add_all_num = data1["confirmedCount"].sum() - data2["confirmedCount"].sum()  # 总新增人数

        sx_all = data1[data1["province_name"] == importance_province]["confirmedCount"].sum()
        add_xian = int(data1[data1["cityName"] == importance_city]["confirmedCount"]) - \
                   int(data2[data2["cityName"] == importance_city]["confirmedCount"])  # 西安新增人数
        xian_all = int(data1[data1["cityName"] == importance_city]["confirmedCount"])

        temp_a1 = data1.groupby("province_name")["confirmedCount"].sum()
        temp_a2 = data2.groupby("province_name")["confirmedCount"].sum()
        add_city = (temp_a1 - temp_a2).sort_values(ascending=False)
        add_city = add_city[add_city.values != 0]  # 新增地区及人数
        result_str = "\n"
        for city_name, number in zip(add_city.index.tolist(), add_city.values.tolist()):
            str_data = str(city_name) + "新增病例: " + str(number) + "\n"
            result_str += str_data

        danger_area = data2.groupby("province_name")["confirmedCount"].sum().sort_values(ascending=False)[: 10]
        danger_str = "\n"  # 疫情严重地区可以自己添加
        for city_name, number in zip(danger_area.index.tolist(), danger_area.values.tolist()):
            str_data = str(city_name) + "出现病例: " + str(number) + "\n"
            danger_str += str_data

        result = result % (str(now_time).split(" ")[1], week_info, weather, all_num, add_all_num,
                           add_xian, xian_all, sx_all, result_str)
        coon.close()
        return result

    @staticmethod
    def get_week_day(date):
        week_day = {
            0: '星期一',
            1: '星期二',
            2: '星期三',
            3: '星期四',
            4: '星期五',
            5: '星期六',
            6: '星期日',
        }
        day = date.weekday()  # weekday()可以获得是星期几
        return week_day[day]

    @staticmethod
    def get_window():
        url = "http://api.qingyunke.com/api.php?key=free&appid=0&msg=%E8%A5%BF%E5%AE%89%E5%A4%A9%E6%B0%94"
        response = requests.get(url)
        content = json.loads(response.content.decode())
        if content["result"]:
            return "未获取到天气信息"
        else:
            return content["content"]


if __name__ == '__main__':
    sup = VirusSupervise()
    print(sup.data_analysis())

在这里插入图片描述
如果你也能输出这段报告那么恭喜你, 完成第二阶段!

欢迎交流! 如有需要历史疫情数据(1月29-现在)的SQL文件和源码等, 评论区留下邮箱

如果对你有帮助那么就点个赞吧!

发布了18 篇原创文章 · 获赞 15 · 访问量 2782

猜你喜欢

转载自blog.csdn.net/qq_42768234/article/details/104162180