Python⽹络爬⾍设计————爬取丁⾹园疫情数据数据可视化1.选题背景
⾃新冠肺炎疫情爆发以来,这场疫情⼏乎影响了每个⼈的⽣活,为了对疫情做数据分析,需要采集疫情的数据。
此次期末作业设计我选择了利⽤爬⾍⽹路来获取疫情相关数据的⽅法,通过对丁⾹园⽹站爬取相关疫情数据,在本地对数据处理后将疫情数据⽤视图等形式进⾏展现。
2.主题思路
1.发送请求获取数据
2.从疫情⾸页中提取最各国疫情字符串
3.从最近各国疫情字符串共媒体去json格式字符串
4.把json格式字符串,转换为Python类型
5.把python类型的数据,以json格式存⼊⽂件之中
6.利⽤pandas、matplotlib、numpy将数据读出绘制数据对应的图
3.丁⾹园⽹页页⾯
从上部分模块我们可以获得具体省会的城市对应的疫情感染数据,同时⽹页根据内嵌式css+id对应⽂本框嵌套窗⼝来显⽰数据
我们根据对应id显⽰的需要内容来进⾏获取,字符串识别对应ID来达到我们想要的效果
4.Python爬⾍代码设计
1.从丁⾹园⽹站采集最近⼀⽇疫情各国状况
#导⼊模块
import requests
from bs4 import BeautifulSoup
#发送请求
url="ncov.dxy/ncovh5/view/pneumonia"
#伪装请求头
headers ={'User-Agent':'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'}
(url,timeout=30,headers=headers)
home_page = t.decode()
#print(home_page)
#使⽤beautifulsoup提取疫情数据
soup=BeautifulSoup(home_page,'lxml')
script=soup.find(id="getListByCountryTypeService2true")
text=
print(text)
接下来将获取的字段⽤json.dump将它导出到⽂件
#从数据中获取json格式字符串
json_str = re.findall(r'\[.+\]',text)[0]
#把json格式字符串转换为python类型
last_day_corona_virus = json.loads(json_str)
#print(last_day_corona_virus)
with open('last_day_corona_virus','w')as fp:
json.dump(last_day_corona_virus,fp,ensure_ascii=False)
这⾥为了能⽅便打开确定导出成功我更改了代码(ensure_ascii=True,不更改了话是json⽂件⽆法在⽹页编辑⾥⾯直接打开)
由上我们就获得了各国的疫情数据现在我们就要利⽤pandas来调⽤
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib as mpl
import matplotlib.animation as animation
lors import rgb2hex
from matplotlib.patches import Polygon
s as ccrs
import cartopy.io.shapereader as shpreader
# 加载世界现有确诊病例数据
last_day_corona_virus = pd.read_json('last_day_corona_virus.json')
# 计算疫情⽇期
current_date = pd.to_datetime(last_day_corona_virus['createTime'][0], unit='ms')
current_date_str = f'{ar}年{h}⽉{current_date.day-1}⽇'
# print(current_date_str)
# 统计最近⼀⽇各国现有确诊病例数量
datas = last_day_corona_virus.pivot_table(values='currentConfirmedCount', index='provinceName')['currentConfirmedCount']
# 按现有确诊确诊数量, 进⾏倒叙排
datas = datas.sort_values(ascending=False)
# 国家地理⽂件
shpfilename = shpreader.natural_earth(resolution='110m', category='cultural', name='admin_0_countries')
# 地理信息⽂件阅读器
reader = shpreader.Reader(shpfilename)
# 获取⽂件中国家地理信息
countries_map = ds()
由于获取的json⽂件转换,接下来⽤采数据字典对应ascii码将代码转换,不使⽤往常上课的导⼊到表格再将表格转换成图⽚对应的⽅式# 定义字典⽅便根据名字地理信息
# 疫情国家与地图国家映射关系
names_dict = {'斐济':'斐濟', '苏⾥南':'蘇利南','加纳':'迦納','⼏内亚⽐绍':'幾內亞⽐索','中⾮共和国':'中⾮共和國','赞⽐亚共和国':'赞⽐亚',
'中国':'中华⼈民共和国','亚美尼亚':'亞美尼亞','刚果(⾦)':'刚果民主共和国', '刚果(布)':'刚果共和国','北马其顿':'⾺其頓共和國',
'罗马尼亚':'羅⾺尼亞','博茨⽡纳':'波札那','马⾥':'马⾥共和国','圣马丁岛':'荷属圣马丁','塞浦路斯':'賽普勒斯','多⽶尼加':'多明尼加',
'委内瑞拉':'委內瑞拉', '尼⽇利亚':'奈及利亞','韩国':'⼤韩民国','布隆迪共和国':'蒲隆地','⿊⼭':'蒙特內哥羅','蒙古':'蒙古国',
渝快政下载android版'荷兰':'荷蘭','苏丹':'苏丹共和国','突尼斯':'突尼西亞','⽩俄罗斯':'⽩罗斯','玻利维亚':'玻利維亞','爱尔兰':'爱尔兰共和国',
'津巴布韦':'⾟巴威', '波⿊':'波斯尼亚和⿊塞哥维那', '新喀⾥多尼亚':'新喀⾥多尼亞','斯⾥兰卡':'斯⾥蘭卡', '也门共和国':'也门',
'阿联酋':'阿拉伯联合酋长国','拉脱维亚':'拉脫維亞'
}
# 获取画布与坐标系
fig, ax = plt.subplots(figsize=(10, 6), subplot_kw={'projection': ccrs.PlateCarree()})
# 把所有的国家设定绘制颜⾊为灰⾊的
geom_dict = {}
# 最⼤值
vmax = 10000
cmap = YlOrRd
# 边框⾊
edgecolor = 'black'
# 初始疫情地图颜⾊, 准备国家名字与其地理位置的对应关系
for country in countries_map:
geom_dict[country.attributes['NAME_ZH']] = ry
# 清空当前坐标系
ax.clear()
for country_name in datas.index:
# 获取现有确诊数量
value = datas[country_name]
# 把疫情的国家名称转换为地图的国家名称
tmp_name = (country_name) or country_name
# 根据国家名称, 获取国家地理位置信息
geom = (tmp_name)
# 遍历地理数据, 更新国家颜⾊
if geom is not None:
# 根据疫情数据, ⽣成国家颜⾊
facecolor = rgb2hex(cmap(value/vmax))
# 绘制国家颜⾊到地图上
ax.add_geometries(geom, ccrs.PlateCarree(), facecolor=facecolor, edgecolor=edgecolor)
# 设置世界地图标题
ax.set_title(f'{current_date_str} 全世界疫情地图')
# 添加刻度条
cax = fig.add_axes([0.92, 0.2, 0.02, 0.6])
# 颜⾊条
norm = lors.Normalize(vmin=0, vmax=vmax)
# 调⾊板
cb = lorbar.ColorbarBase(cax, cmap=cmap, norm=norm,
spacing='proportional')
教剪头发初学的视频cb.set_label('现有确诊⼈数')
plt.show()
事实证明更具表对应字段转换的时候会快捷⽅便许多但是新学习的⽅法⽤字典来对应也是⼀种⽅式
类似的我们还做了针对国内的
以下为国内的数据提取(利⽤def我们分类采集了不同时段的疫情数据)
import requests
from bs4 import BeautifulSoup
import re
import json
from tqdm import tqdm
class CoronaVirusSpider(object):
def__init__(self):
self.home_url = 'ncov.dxy/ncovh5/view/pneumonia'
def get_content_from_url(self, url):
"""
根据URL获取响应内容
:
param url: 请求的URL
:return: URL的响应的内容字符串
"""
response = (url)
t.decode()
def parse_home_page(self, home_page, tag_id):
"""
从疫情⾸页中提取数据
"""
# 从疫情⾸页, 提取疫情数据
soup = BeautifulSoup(home_page, 'lxml')
script = soup.find(id=tag_id)
text =
# print(text)
# 从疫情数据中, 获取json格式的字符串
json_str = re.findall(r'\[.+\]', text)[0]
# print(json_str)
# 把json格式的字符串转换为Python类型
data = json.loads(json_str)
return data
def load(self, path):
"""
根据路径加载数据
:param path:
"""
with open(path) as fp:
data = json.load(fp)
return data
def save(self, data, path):
# print(last_day_corona_virus)
# 以json格式保存, 最近⼀⽇各国疫情数据
with open(path, 'w') as fp:
json.dump(data, fp, ensure_ascii=False)
def crawl_last_day_corona_virus(self):
# 获取⾸页内容
home_page = _content_from_url(self.home_url)
# 解析数据
last_day_corona_virus = self.parse_home_page(home_page, tag_id='getListByCountryTypeService2true') # 保存数据
self.save(last_day_corona_virus, 'last_day_corona_virus.json')
def crawl_corona_virus(self):
"""
采集各国疫情数据
:return:
"""
# 1. 加载各国疫情数据
last_day_corona_virus = self.load('last_day_corona_virus.json')
# 2. 定义列表, ⽤于存储各国疫情数据
corona_virus = self.parse_corona_virus(last_day_corona_virus, '采集各国疫情信息') # 3. 把列表以json格式保存为⽂件
self.save(corona_virus, 'corona_virus.json')
def crawl_last_day_corona_virus_of_china(self):
"""
采集最近⼀⽇各省疫情数据
"""
# 1.发送请求, 获取疫情⾸页
home_page = _content_from_url(self.home_url)
# 2. 解析疫情⾸页, 获取最近⼀⽇各省疫情数据
last_day_corona_virus_of_china = self.parse_home_page(home_page, tag_id='getAreaStat') # 3. 保存疫情数据
self.save(last_day_corona_virus_of_china, 'last_day_corona_virus_of_china.json')
def crawl_corona_virus_of_china(self):
"""
采集全国各省的疫情数据
:return:
"""
# 加载最近⼀⽇全国疫情信息
last_day_corona_virus_of_china = self.load('last_day_corona_virus_of_china.json')
# 遍历最近⼀⽇全国疫情信息, 获取各省疫情URL
corona_virus = self.parse_corona_virus(last_day_corona_virus_of_china, '采集各省疫情信息') # 以json格式保存疫情信息
self.save(corona_virus, 'corona_virus_of_china.json')
def parse_corona_virus(self, last_day_corona_virus_of_china, desc):
# 定义列表, ⽤于存储各国疫情数据
corona_virus = []
# 2. 遍历各国疫情数据, 获取统计的URL
for country in tqdm(last_day_corona_virus_of_china, desc):
# 发送请求, 获取各省疫情json字符串
statistics_data_url = country['statisticsData']
statistics_data_json_str = _content_from_url(statistics_data_url)
# print(statistics_data_json_str)
# 4. 解析各省疫情json字符串, 并添加列表中
statistics_data = json.loads(statistics_data_json_str)['data']
# print(statistics_data)
for one_day in statistics_data:
one_day['provinceName'] = country['provinceName']
('countryShortCode'):
one_day['countryShortCode'] = country['countryShortCode']
# print(statistics_data)
d(statistics_data)
# print(corona_virus)
return corona_virus
def run(self):
# awl_last_day_corona_virus()
# awl_last_day_corona_virus_of_china()
if__name__ == '__main__':
spider = CoronaVirusSpider()
spider.run()
⾄此我们所有的数据采集任务都全部完成了,接下来重复之前的步骤进⾏数据可视化
我们这⾥做了⼀些改变不再沿⽤数据字典对应的⽅式
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import matplotlib
import matplotlib.figure
from matplotlib.patches import Polygon
from mpl_toolkits.basemap import Basemap
# 准备⾏政区域确诊分布数据
last_day_corona_virus_of_china = pd.read_json('last_day_corona_virus_of_china.json')
python请求并解析json数据current_confirmed_count = last_day_corona_virus_of_china.pivot_table(values='currentConfirmedCount', index='provinceName') data = current__dict()['currentConfirmedCount']
windows2008r2清除开机密码# 绘制⾏政区域确诊分布数据
lat_min = 0
lat_max = 60
lon_min = 70
lon_max = 140
handles = [
如何制作属于自己的网站matplotlib.patches.Patch(color='#ffaa85', alpha=1, linewidth=0),
matplotlib.patches.Patch(color='#ff7b69', alpha=1, linewidth=0),
matplotlib.patches.Patch(color='#bf2121', alpha=1, linewidth=0),
matplotlib.patches.Patch(color='#7f1818', alpha=1, linewidth=0),
]
labels = ['1-9⼈', '10-99⼈', '100-999⼈', '>1000⼈']
fig = plt.figure(figsize=(8, 10))
axes = fig.add_axes((0.1, 0.12, 0.8, 0.8)) # rect = l,b,w,h
vue路由跳转传递参数m = Basemap(llcrnrlon=lon_min, urcrnrlon=lon_max, llcrnrlat=lat_min, urcrnrlat=lat_max, resolution='l', ax=axes)
# 洲际线
m.drawcoastlines(color='black')
# 国界线
m.drawcountries(color='black')
# 画经度线
m.drawparallels(np.arange(lat_min, lat_max, 10), labels=[1, 0, 0, 0])
# 画纬度线
m.drawmeridians(np.arange(lon_min, lon_max, 10), labels=[0, 0, 0, 1])
for info, shape in zip(m.province_info, m.province):
pname = info['OWNER'].strip('\x00')
fcname = info['FCNAME'].strip('\x00')
if pname != fcname: # 不绘制海岛
continue
for key in data.keys():
if key in pname:
if data[key] == 0:
color = '#f0f0f0'
elif data[key] < 10:
color = '#ffaa85'
elif data[key] < 100:
color = '#ff7b69'
elif data[key] < 1000:
color = '#bf2121'
else:
color = '#7f1818'
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论