Big Data

2020大数据导论期末大作业

目标:

1.实现对新浪网美国疫情大数据爬取

2.将美国疫情大数据存储进入hive

3.利用Spark对hive中的数据进行分析

4.将分析结果可视化展示

前期工作:

刚打开Ubuntu虚拟机,先打开hadoop,成功打开后,进入hive目录,执行命令show databases;出现以下错误:

上网一搜发现是初始化元数据库的问题,又一次执行了初始化命令,显示初始化失败,顺便发现了hive-site.xml配置文件中的一个错误,从家里的WiFi变成学校的网络,由于之前虚拟机的网络模式是桥接模式,主机的IP地址变了,虚拟机的IP地址也变了,重新做了hadoop的地址映射,忘了改hive-site.xml中的IP地址了,将javax.jdo.option.ConnectionURL项中的IP地址由192.168.2.127改成192.168.43.196

重新运行一遍hive,发现还是有相同问题,又搜了一下,发现是Metastore服务未启动,重新启动一下Metastore服务,执行hive --service metastore &,接着按Ctrl+C组合键,再次执行hive问题解决。

一、数据采集

疫情大数据爬取:

(1)确定疫情大数据所在网页链接

这里使用新浪网的网页链接:http://t.cn/A67OCJyZ

因为国内的疫情数据在网上已被多人分析统计过,这里我们选择疫情相对严重的美国的疫情数据进行分析,点开网页中的世界疫情选项卡,在重点疫情国家累计确诊趋势中选择美国,进入网页后按F12打开网页开发者工具,进入network页面,获得网页加载时所传输的各种资源。试了几个数据类的js链接之后,发现是ncp_foreign.d.json?citycode=SCUS0001&_=1591359081788&callback=jsoncallback这个文件。

在右侧Preview中可以看到预览的数据。

点击左侧的Headers可以获取请求的URL,这里是https://gwpre.sina.cn/interface/news/wap/ncp_foreign.d.json?citycode=SCUS0001&_=1591359081788&callback=jsoncallback

(2)疫情大数据获取

执行以下Python代码

获得部分输出如下:

{"data_title":"fymap","data":{"contotal":"1924189","sustotal":"0","curetotal":"712252","deathtotal":"110179","adddaily":{"conadd":"+22158","conadd_n":22158,"susadd":"+0","susadd_n":0,"cureadd":"+23582","cureadd_n":23582,"deathadd":"+1033","de...}

(3)疫情大数据解析和整理

上一步获得了新浪提供的疫情数据,但通过爬虫获得的数据都是字符串,需要转换为Python里的字典对象才能进一步使用,此时就需要json模块发挥作用了。

在程序开始写入:import json

由于data中的数据有jsoncallback()字样,导致data不是完全的json格式的,这样data_dict不能直接用json.loads(data)把data中的数据转换为字典对象,我们先把data输出到code.txt文本文档中,删除jsoncallback()字样,另开一个Python文件,命名为cope.py,将改正过的code.txt中的数据用json.loads(data)转换为字典对象并输出

获取部分数据显示如下:

{'data_title': 'fymap', 'data': {'contotal': '1924189', 'sustotal': '0', 'curetotal': '712252', 'deathtotal': '110179', 'adddaily': {'conadd': '+22158', 'conadd_n': 22158, 'susadd': '+0', 'susadd_n': 0, 'cureadd': '+23582', 'cureadd_n': 23582, 'deathadd': '+1033', 'deathadd_n': 1033}, 'country': '美国', 'is_show_entrance': 1, 'is_show_map': 1, 'population': '327167434', 'uc...}

接下来进一步看清数据组织,打印字典对象,并且打印出键值为history_data和city的数据,分别表示美国1月份到6月5日的疫情数据和美国各州的6月5日疫情总数据,代码如下:

部分数据显示如下:

0 contotal 1924189
1 sustotal 0
2 curetotal 712252
3 deathtotal 110179
4 adddaily {'conadd': '+22158', 'conadd_n': 22158, 'susadd': '+0', 'susadd_n': 0, 'cureadd': '+23582', 'cureadd_n': 23582, 'deathadd': '+1033', 'deathadd_n': 1033}
5 country 美国
6 is_show_entrance 1
7 is_show_map 1
8 population 327167434
9 ucarea 150439.0300

{'conNum': '1902031', 'susNum': '0', 'cureNum': '688670', 'deathNum': '109146', 'conadd': '19553', 'susadd': '0', 'cureadd': '42256', 'deathadd': '1042', 'date': '06.04'}
{'conNum': '1882478', 'susNum': '0', 'cureNum': '646414', 'deathNum': '108104', 'conadd': '21004', 'susadd': '0', 'cureadd': '30760', 'deathadd': '1114', 'date': '06.03'}
{'conNum': '1861474', 'susNum': '0', 'cureNum': '615654', 'deathNum': '106990', 'conadd': '22355', 'susadd': '0', 'cureadd': '11765', 'deathadd': '749', 'date': '06.02'}
{'conNum': '1839119', 'susNum': '0', 'cureNum': '603889', 'deathNum': '106241', 'conadd': '19331', 'susadd': '0', 'cureadd': '0', 'deathadd': '607', 'date': '06.01'}
{'conNum': '1819788', 'susNum': '0', 'cureNum': '603889', 'deathNum': '105634', 'conadd': '26258', 'susadd': '0', 'cureadd': '0', 'deathadd': '1092', 'date': '05.31'}
{'conNum': '1793530', 'susNum': '0', 'cureNum': '603889', 'deathNum': '104542', 'conadd': '23200', 'susadd': '0', 'cureadd': '0', 'deathadd': '1163', 'date': '05.30'}
{'conNum': '1770330', 'susNum': '0', 'cureNum': '603889', 'deathNum': '103379', 'conadd': '24527', 'susadd': '0', 'cureadd': '0', 'deathadd': '1272', 'date': '05.29'}
{'conNum': '1745803', 'susNum': '0', 'cureNum': '603889', 'deathNum': '102107', 'conadd': '16849', 'susadd': '0', 'cureadd': '0', 'deathadd': '1421', 'date': '05.28'}
{'conNum': '1728954', 'susNum': '0', 'cureNum': '603889', 'deathNum': '100686', 'conadd': '19561', 'susadd': '0', 'cureadd': '0', 'deathadd': '777', 'date': '05.27'}
{'conNum': '1709393', 'susNum': '0', 'cureNum': '603889', 'deathNum': '99909', 'conadd': '19666', 'susadd': '0', 'cureadd': '0', 'deathadd': '528', 'date': '05.26'}
{'conNum': '1689727', 'susNum': '0', 'cureNum': '603889', 'deathNum': '99381', 'conadd': '21234', 'susadd': '0', 'cureadd': '80393', 'deathadd': '675', 'date': '05.25'}
{'conNum': '1668493', 'susNum': '0', 'cureNum': '523496', 'deathNum': '98706', 'conadd': '20210', 'susadd': '0', 'cureadd': '0', 'deathadd': '974', 'date': '05.24'}
{'conNum': '1648283', 'susNum': '0', 'cureNum': '523496', 'deathNum': '97732', 'conadd': '24931', 'susadd': '0', 'cureadd': '0', 'deathadd': '1300', 'date': '05.23'}
{'conNum': '1623352', 'susNum': '0', 'cureNum': '523496', 'deathNum': '96432', 'conadd': '26419', 'susadd': '0', 'cureadd': '0', 'deathadd': '1373', 'date': '05.22'}
{'conNum': '1596933', 'susNum': '0', 'cureNum': '523496', 'deathNum': '95059', 'conadd': '24819', 'susadd': '0', 'cureadd': '0', 'deathadd': '1465', 'date': '05.21'}
{'conNum': '1572114', 'susNum': '0', 'cureNum': '523496', 'deathNum': '93594', 'conadd': '19810', 'susadd': '0', 'cureadd': '1721', 'deathadd': '1522', 'date': '05.20'}

{'name': '加利福尼亚州', 'mapName': 'California', 'conNum': '122808', 'susNum': '0', 'cureNum': '86053', 'deathNum': '4484', 'conadd': '2548', 'susadd': '0', 'cureadd': '0', 'deathadd': '63', 'is_show_entrance': 0, 'is_show_map': 0}
{'name': '亚利桑那州', 'mapName': 'Arizona', 'conNum': '22753', 'susNum': '0', 'cureNum': '5172', 'deathNum': '996', 'conadd': '530', 'susadd': '0', 'cureadd': '96', 'deathadd': '15', 'is_show_entrance': 0, 'is_show_map': 0}
{'name': '伊利诺伊州', 'mapName': 'Illinois', 'conNum': '124759', 'susNum': '0', 'cureNum': '53837', 'deathNum': '5736', 'conadd': '929', 'susadd': '0', 'cureadd': '0', 'deathadd': '115', 'is_show_entrance': 0, 'is_show_map': 0}
{'name': '马萨诸塞州', 'mapName': 'Massachusetts', 'conNum': '102063', 'susNum': '0', 'cureNum': '47416', 'deathNum': '7201', 'conadd': '471', 'susadd': '0', 'cureadd': '0', 'deathadd': '49', 'is_show_entrance': 0, 'is_show_map': 0}
{'name': '华盛顿州', 'mapName': 'Washington', 'conNum': '23847', 'susNum': '0', 'cureNum': '15125', 'deathNum': '1149', 'conadd': '363', 'susadd': '0', 'cureadd': '0', 'deathadd': '8', 'is_show_entrance': 0, 'is_show_map': 0}
{'name': '威斯康辛州', 'mapName': 'Wisconsin', 'conNum': '19892', 'susNum': '0', 'cureNum': '12980', 'deathNum': '626', 'conadd': '492', 'susadd': '0', 'cureadd': '808', 'deathadd': '10', 'is_show_entrance': 0, 'is_show_map': 0}
{'name': '钻石公主号', 'mapName': '', 'conNum': '46', 'susNum': '0', 'cureNum': '2', 'deathNum': '0', 'conadd': '0', 'susadd': '0', 'cureadd': '0', 'deathadd': '0', 'is_show_entrance': 0, 'is_show_map': 0}
{'name': '撤回侨民', 'mapName': '', 'conNum': '3', 'susNum': '0', 'cureNum': '0', 'deathNum': '0', 'conadd': '0', 'susadd': '0', 'cureadd': '0', 'deathadd': '0', 'is_show_entrance': 0, 'is_show_map': 0}

将history_data中的数据值以空格为分隔符写入history_data.txt文件中,同理city也是如此

由于新浪网上的数据最后一项日期的格式是月-日形式的,很可能与hive中的日期类型数据格式不符,为避免可能出现的格式不匹配的错误,用Python扫描整个文件内容,在遇到'-'字符时在月份前面加上年份'2020-',以history_data.txt为例,处理代码如下:

经过实验,city_data.txt中的部分数据中,有的地区不属于美国州级别的地区,只有个位数的确诊病例,且没有英文名称,有的州的英文名称中间有空格,这些数据都给后期导入hive造成了问题,由于数据量较小,所以我们对city_data.txt进行肉眼清洗,把英文名称中间的空格删掉并且删除不属于美国州级别地区的数据。

爬取数据链接:(有效期至2021-06-07)

history_data.txt:https://paste.ubuntu.com/p/HTM6p2Kx64/

city_data.txt:https://paste.ubuntu.com/p/TbDYk5344T/

二、数据持久化存储

打开FileZilla Client软件,输入主机IP地址、用户名、密码和端口号,将爬取的history_data.txt和city_data.txt传入虚拟机/home/dcrusher/目录下。

启动Ubuntu虚拟机,我们打开city_data.txt文件发现原先在Windows上能显示中文在Linux下显示乱码,这是Windows默认是gbk编码而Linux默认是utf-8编码导致的,执行命令iconv -f gbk -t utf8 city_data.txt > city.txt,这是将city_data.txt用utf-8编码到city.txt,这时候打开city.txt就能显示中文了,再用命令mv city.txt city_data.txt将city.txt重命名回city_data.txt

打开终端启动hadoop和hive,这部分命令就不再展示了,然后create database terminal;创建数据库terminal

创建两个表history_data和city_data,分别存放美国疫情总数据和各州疫情数据,命令如下:

create table history_data (conNum int,susNum int,cureNum int,deathNum int,conadd int,susadd int,cureadd int,deathadd int,datetime date) row format delimited fields terminated by ' ';

create table city_data (name string,mapname string,connum int,susnum int,curenum int,deathnum int,conadd int,susadd int,cureadd int,deathadd int,is_show_entrance int,is_show_map int) row format delimited fields terminated by ' ';

接下来是导入数据,命令如下:

load data local inpath '/home/dcrusher/history_data.txt' into table history_data;

load data local inpath '/home/dcrusher/city_data.txt' into table city_data;

部分数据显示如下:

三、数据聚合统计分析

(1)使用虚拟环境创建flask项目

①建立虚拟环境env,并激活使用

首先新建一个flask工程目录,并使用python3 -m venv env命令创建虚拟环境目录:

mkdir Flask_Proj

cd Flask_Proj

python3 -m venv env

上述命令执行完成后,就会在Flask_Proj目录下新建一个env目录,并有以下内容:

然后使用source命令激活bin目录下的activate,就可以激活虚拟环境使用了:source env/bin/activate

②有了虚拟环境后,在当前工程目录下pip install flask,开启安装flask库,使用阿里云镜像安装:pip install -i https://mirrors.aliyun.com/pypi/simple flask

安装完成后,在env/lib/python3.6/site-packages找到flask库已经在Python默认安装目录里了,继续下面的工作

flask安装成功后,可以在工程目录下新建一个main.py文件,在其中输入如下内容:

直接python运行文件,就可以开启一个测试的web服务:

这时可以在外部浏览器上访问这个地址,端口号为2021

(2)Gunicorn部署flask项目

在flask工程项目中创建env虚拟环境,是为了保证许多依赖的第三方库版本的一致。如上在启动了flask自带的server后,可以实现外部访问。但这种方式仅适用于测试,无法用于实际部署,因此一般推荐使用Gunicorn来搭建flask服务器。

Gunicorn是一个高效的Python WSGI Server,通常用它来运行wsgi application或者wsgi framework,地位相当于Java中的Tomcat。

①安装Gunicorn

Gunicorn是一个第三方库,可以直接使用pip来安装:

pip install -i https://mirrors.aliyun.com/pypi/simple gunicorn

②使用Gunicorn命令

基本使用方式:

gunicorn --workers=3 main:app

--workers=3表示三个进程,main:app,其中main为之前flask工程中的main.py,意味着将main.py对象实例化为app

③使用参数配置文件设定

3.1 安装异步模块

要使用异步模块,就要安装相应的异步模块,这里我们只需安装greenlet和gevent即可,命令如下:

pip install greenlet

在gevent安装的时候显示error: invalid command 'bdist_wheel'的错误,原因是系统缺少相应的wheel包,只需安装上就可以了

pip install wheel

接下来再pip install -i https://mirrors.aliyun.com/pypi/simple gevent就可以了

3.2 编辑配置文件config.py

执行命令gunicorn -c config.py main:app

这时打开浏览器输入192.168.43.196:2021就能看到Hello World 2020!的字样了

至此基本的gunicorn+flask异步服务部署就实现了

(3)Spark对hive数据仓库中city_data表进行分析

①创建一个连接hive的SparkSession对象,命令行输入:

scala> import org.apache.spark.sql.SparkSession

scala> val spark=SparkSession.builder.enableHiveSupport().master("dcrusher:9083").getOrCreate

其中master的参数应与hive中thrift的通信地址相同

②开始使用SparkSession对象的sql语句查询方法,获得hive数据库中的数据生成DataFrame,前提条件是hive数据仓库中有对应数据并且已开启hive的metastore服务

scala> val df=spark.sql("select * from terminal.city_data")

scala> df.show

③统计terminal数据库中city_data表中疫情最严重的前10个州,疫情的严重程度以现存确诊人数的多少来决定,显示州名和现存确诊人数,命令如下:

scala> val df=spark.sql("select name,conNum from terminal.city_data order by conNum desc limit 10")

scala> df.show

④将统计结果导入MySQL数据库

4.1 创建MySQL数据库并建表

mysql -u root -p输入密码进入MySQL,创建数据库terminal,注意设置字符集为utf-8,命令如下:

create database terminal character set utf8 collate utf8_general_ci;

建表命令:

create table city_data (name varchar(20),connum int);

4.2 将DataFrame数据输出到MySQL中

使用如下命令:

scala> df.write.mode("overwrite").format("jdbc").option("url","jdbc:mysql://dcrusher:3306/terminal").option("dbtable","city_data").option("user","root").option("password","tyc0520!").save()

需要注意的是,我们需要提前把mysql-connector-...的jar包复制粘贴进spark的jars目录下,另外spark-shell在使用过程中容易内存溢出,可以在输入命令的过程中加入cache命令缓存一下

(4)Spark对hive数据仓库中history_data表进行分析

①创建一个连接hive的SparkSession对象,命令行输入:

scala> import org.apache.spark.sql.SparkSession

scala> val spark=SparkSession.builder.enableHiveSupport().master("dcrusher:9083").getOrCreate

其中master的参数应与hive中thrift的通信地址相同

②开始使用SparkSession对象的sql语句查询方法,获得hive数据库中的数据生成DataFrame,前提条件是hive数据仓库中有对应数据并且已开启hive的metastore服务

scala> val df=spark.sql("select * from terminal.history_data")

scala> df.show

③统计表中日期和对应的现存确诊人数,命令如下:

scala> val df=spark.sql("select datetime,conNum from terminal.history_data")

scala> df.show

④统计表中每天的病死率(死亡数/确诊数),命令如下:

scala> val df=spark.sql("select datetime,deathNum/conNum from terminal.history_data")

scala> df.show

⑤将统计结果导入MySQL数据库

5.1 创建history_data和deathrate表,命令如下:

create table history_data (datetime date,conNum int);

create table deathrate (datetime date,rate double);

5.2 将DataFrame数据输出到MySQL中

使用如下命令:

scala> df.write.mode("overwrite").format("jdbc").option("url","jdbc:mysql://dcrusher:3306/terminal").option("dbtable","history_data").option("user","root").option("password","tyc0520!").save()

scala> df.write.mode("overwrite").format("jdbc").option("url","jdbc:mysql://dcrusher:3306/terminal").option("dbtable","deathrate").option("user","root").option("password","tyc0520!").save()

传输完数据去MySQL中查看一下表内容:

四、数据前端可视化展示

echarts属于百度开源的可视化组件,目前已被Apache孵化为顶级项目之一。echarts官网为:https://echarts.apache.org/zh/index.html

将echarts.min.js和jQuery-3.5.1.min.js放到E盘,用FileZilla Client软件传入虚拟机env虚拟环境中

①切换到虚拟环境env,重命名相应文件夹

source env/bin/activate激活虚拟环境

mv includes templates将includes文件夹重命名为templates,templates文件夹用来存放我们的html文件,也就是前端显示页面

mkdir static新建static文件夹,static文件夹用来存放html文件需要引入的js文件,比如jQuery和echarts

②编辑final.py文件

用pymysql连接MySQL数据库,将history_data表中数据存储为json格式,再将其转换为字符串形式返回

③编辑template.html文件

从final.py的代码中我们可以看到我们将ajax请求的数据传送到template.html文件,所以我们在templates文件夹下编辑template.html文件

④部署Web服务器端,进行页面浏览

执行命令gunicorn -c config.py final:app

然后打开浏览器,地址栏输入192.168.43.196:2021,就会出现如下界面

⑤将界面进行优化,并加入city_data柱形图以及deathrate折线柱形图

最终代码展示:

发表评论

邮箱地址不会被公开。 必填项已用*标注