前言
這兩年,新冠肺炎肆虐而來,隨著確診人數的不斷上升,全世界的人都陷入了恐慌中,我們經常能在手機、電視上看到各個地區疫情的情況,但那些資料大多數都是零碎的,我們不可能去記住每個資料,但我們可以用爬蟲爬取各個地區發出的新聞資料,再將這些資料進行整理分析,所以我們在疫情期間可以通過訪問一個網站,就能知道各個地區的疫情情況,
資料來源
中國的新冠肺炎疫情資料
國外的新冠肺炎疫情資料
爬蟲設計方案
1. 爬蟲名稱
新冠肺炎疫情資料的爬取與可視化分析
2. 爬取內容與資料特征分析
爬取的內容包括了全球新冠肺炎疫情資料、中國各省市新冠肺炎疫情資料和福建各市新冠肺炎疫情資料,
爬取的資料都由中文和數字組成,所有數字資料都是大于等于0,不會出現小于0的情況,
3. 方案概述
分析網站頁面結構,找到爬取資料的位置,根據不同的資料制定不同的爬取方法,將爬取的資料保存成csv檔案,然后再將csv檔案里的資料進行可視化處理,
網站頁面的結構特征分析
1. 網站頁面結構分析
從下面的網站截圖中可以看出,該網站的結構分為三個部分,一部分是左上的疫情總覽,一部分是右邊各個地區的疫情訊息,還有一部分就是左下各個地區具體的疫情資料,而這部分資料就是我們要爬取的資料,

2. 網站html頁面結構分析
從下面的網站html截圖中可以看出,該網站由div標簽進行分割內容,總共分了兩大塊,左邊和右邊,我們需要的資料在左邊,

進一步分析網站的html,發現資料都在class=data-list的div標簽里,在div標簽里的串列標簽ul,存放著中國每個省的疫情資料,

在li標簽下,還有一個div,這個div里的ul串列存放的資料是每個省市的資料,

3. 標簽查找方法與遍歷方法
通過上面網站html頁面的分析,可以畫出標簽樹,

(1)地區名稱所在標簽的查找方法
各個省份的名稱在class=list-pro-name的div標簽里,而各省份的城市的名稱在class=list-city-name的div標簽里,因為這兩個標簽的class屬性不同,所以可以用BeautifulSoup庫的find()方法,利用標簽屬性值檢索,
(2)地區疫情資料所在標簽的查找方法
從上面的標簽樹中可以看出,省疫情資料和市疫情資料分別在不同的li標簽下的div標簽里,第二個li是第一個li的子標簽,在這兩個標簽之間沒有可以唯一標識的熟悉,所以要查找到這兩個標簽需要BeautifulSoup庫的CSS選擇器,通過標簽的父子關系分別找到兩個li標簽,
爬蟲程式設計
1. 資料的爬取
(1)中國新冠疫情資料的爬取
# 獲取中國每個省的疫情資料
def getProvinceData(html):
total_data=https://www.cnblogs.com/yusama/p/[]
temporary=[]
new_diagnosis_data=[]
cumulative_diagnosis_data=[]
cured_data=[]
dead_data=[]
soup = BeautifulSoup(html,'html.parser')
# 找到 class=data-list 的div標簽
data = https://www.cnblogs.com/yusama/p/soup.find('div',{'class':'data-list'})
ul = data.find('ul')
div = ul.find_all('div',{'class':'list-pro-name'})
province_name_data=https://www.cnblogs.com/yusama/p/[]
for i in div:
# 獲取省的名稱
# 省名稱在label標簽里
province_name = i.find('label').string
province_name_data.append(province_name)
# 用CSS選擇器獲取第一層的資料(每個省的資料)
diagnosis = soup.select('div.data-list > ul > li > div.list-city-data')
for i in diagnosis:
temporary.append(i.string)
total = [temporary[i:i+4] for i in range(0,len(temporary),4)]
for i in range(len(total)):
# 獲取新增確診人數
new_diagnosis_data.append(total[i][0])
# 獲取累計確診人數
cumulative_diagnosis_data.append(total[i][1])
# 獲取治愈人數
cured_data.append(total[i][2])
# 獲取死亡人數
dead_data.append(total[i][3])
total_data.append(province_name_data)
total_data.append(new_diagnosis_data)
total_data.append(cumulative_diagnosis_data)
total_data.append(cured_data)
total_data.append(dead_data)
return total_data
(2)福建省新冠疫情資料的爬取
# 獲取福建省每個市的疫情資料
def getCitiData(html):
citi_name_data=https://www.cnblogs.com/yusama/p/[]
new_diagnosis_data=[]
cumulative_diagnosis_data=[]
cured_data=[]
dead_data=[]
total_data=[]
soup = BeautifulSoup(html,'html.parser')
data = https://www.cnblogs.com/yusama/p/soup.find('div',{'class':'data-list'})
# 找到有唯一標識的屬性的input標簽
input1 = data.find('input',{'id':'_209'})
# 找到input標簽的的父標簽
div = input1.parent
# 找到所有的li
li = div.find_all('li')
# 遍歷li組成的串列
for i in range(1,len(li)):
# 獲取市名稱
citi_name = li[i].find('div',{'class':'list-city-name'})
citi_name_data.append(citi_name.string+'市')
div = li[i].find_all('div',{'class':'list-city-data'})
# 獲取新增確診人數
new_diagnosis = div[0].string
new_diagnosis_data.append(new_diagnosis)
# 獲取累計確診人數
cumulative_diagnosis = div[1].string
cumulative_diagnosis_data.append(cumulative_diagnosis)
# 獲取治愈人數
cured = div[2].string
cured_data.append(cured)
# 獲取死亡人數
dead = div[3].string
dead_data.append(dead)
total_data.append(citi_name_data)
total_data.append(new_diagnosis_data)
total_data.append(cumulative_diagnosis_data)
total_data.append(cured_data)
total_data.append(dead_data)
return total_data
(3)國外新冠疫情資料的爬取
# 獲取全球每個國家的疫情資料
def getWorldData(html):
country_name_data=https://www.cnblogs.com/yusama/p/[]
new_diagnosis_data=[]
cumulative_diagnosis_data=[]
cured_data=[]
dead_data=[]
total_data=[]
soup = BeautifulSoup(html,'html.parser')
data = https://www.cnblogs.com/yusama/p/soup.find('div',{'class':'data-list'})
# 因為有兩層li,我們需要的是第二層的li,所以可以通過CSS選擇器來獲取第二層的li
data_list = data.select('ul > li > div > div > ul > li')
for i in range(12,len(data_list)-1):
div = data_list[i].find_all('div')
# 獲取國家名稱
country_name = div[0].string
country_name_data.append(country_name)
# 獲取新增確診人數
new_diagnosis = div[1].string
new_diagnosis_data.append(new_diagnosis)
# 獲取累計確診人數
cumulative_diagnosis = div[2].string
cumulative_diagnosis_data.append(cumulative_diagnosis)
# 獲取治愈人數
cured = div[3].string
cured_data.append(cured)
# 獲取死亡人數
dead = div[4].string
dead_data.append(dead)
total_data.append(country_name_data)
total_data.append(new_diagnosis_data)
total_data.append(cumulative_diagnosis_data)
total_data.append(cured_data)
total_data.append(dead_data)
return total_data
(4)保存資料
疫情資料爬取完后,通過Pandask庫的to_csv()方法,將爬取后的資料保存為csv檔案,
保存后的部分資料:



2. 資料清洗與處理
(1)因為全球疫情的資料量較大,所以我們可以通過pandas庫來查看資料是否有例外、缺失、重復
import pandas as pd
#匯入資料
df_world = pd.read_csv("各國家的新冠肺炎疫情資料.csv")
# 查看資料的簡要資訊
df_world.describe()
(2)通過查看資料的簡要資訊,資料正常,資料的最小值也不是負數

(3)通過pandas庫的isnull()方法查看是否有空值
# 查看是否有空值,有空值回傳True,沒有空值回傳False
df_world.isnull().value_counts()

(4)通過pandas庫的duplicated()方法查看是否有重復行
# 查看是否有重復行,有重復行回傳True,沒有重復行回傳False
df_world.duplicated()

(5)為了之后能更好的分析資料,需要對資料進行排序,后面再排序也可以
#根據累計確診人數對資料進行降序排序
df = df_world.sort_values(by='累計確診',ascending=False)
(6)保存處理后的資料
#保存處理后的資料
import pandas as pd
df = df.set_index('名稱')
df.to_csv("各國家的新冠肺炎疫情資料.csv",encoding='utf-8')
df_world = pd.read_csv("各國家的新冠肺炎疫情資料.csv")
df_world.head()

3. 資料可視化分析
(1)中國新冠肺炎疫情地圖
# 用pyecharts庫畫中國新冠疫情地圖
from pyecharts import options as opts
from pyecharts.charts import Map
import pandas as pd
# 自定義分段圖例
pieces=[
{"max": 70000, "min": 3000, "label": ">3000", "color": "#B40404"},
{"max": 3000, "min": 1000, "label": "1000-3000", "color": "#DF0101"},
{"max": 1000, "min": 100, "label": "100-1000", "color": "#F78181"},
{"max": 100, "min": 10, "label": "10-100", "color": "#F5A9A9"},
{"max": 10, "min": 0, "label": "<10", "color": "#FFFFCC"},
]
name = []
values = []
# 匯入資料
df = pd.DataFrame(pd.read_csv("各省的新冠肺炎疫情資料.csv"))
# 處理資料,將資料處理成Map所要求的資料
for i in range(df.shape[0]): # shape[0]:行數,shape[1]:列數
name.append(df.at[i,'名稱'])
values.append(str(df.at[i,'累計確診']))
total = [[name[i],values[i]] for i in range(len(name))]
# 創建地圖(Map)
china_map = (Map())
# 設定中國地圖
china_map.add("確診人數",total ,maptype="china",is_map_symbol_show=False)
china_map.set_global_opts(
# 設定地圖示題
title_opts=opts.TitleOpts(title="中國各省、直轄市、自治區、特別行政區新冠肺炎確診人數"),
# 設定自定義圖例
visualmap_opts=opts.VisualMapOpts(max_=70000,is_piecewise=True,pieces=pieces),
legend_opts=opts.LegendOpts(is_show=False)
)
# 直接在notebook顯示地圖,默認是保存為html檔案
china_map.render_notebook()

(2)中國確診人數前15地區的治愈率與死亡率的折線圖
import pandas as pd
import matplotlib.pyplot as plt
# 創建畫布
fig=plt.figure(figsize=(10,8))
ax=fig.add_subplot(1,1,1)
#中文字體
plt.rcParams['font.family'] = ['SimHei']
# 匯入資料
df_china = pd.read_csv("各省的新冠肺炎疫情資料.csv")
df_china['治愈率'] = df_china['治愈']/df_china['累計確診']
df_china['死亡率'] = df_china['死亡']/df_china['累計確診']
plt.plot(df_china.iloc[0:16,0],df_china.iloc[0:16,5],label="治愈率")
plt.plot(df_china.iloc[0:16,0],df_china.iloc[0:16,6],label="死亡率")
# y軸刻度標簽
ax.set_yticks([0.05,0.2,0.4,0.6,0.8,1.0])
ax.set_yticklabels(["5 %","20 %","40 %","60 %","80 %","100 %"],fontsize=12)
# 圖例
plt.legend(loc='center right',fontsize=12)
# 標題
plt.title("中國確診人數前15地區的治愈率與死亡率")
# 網格
plt.grid()
plt.show()

(3)中國確診人數前15地區的新增確診人數的折線圖
import pandas as pd
import matplotlib.pyplot as plt
# 創建畫布
fig=plt.figure(figsize=(10,8))
#中文字體
plt.rcParams['font.family'] = ['SimHei']
#匯入資料
df_china = pd.read_csv("各省的新冠肺炎疫情資料.csv")
plt.plot(df_china.iloc[0:15,0],df_china.iloc[0:15,1],label="新增確診")
# 圖例
plt.legend(fontsize=12)
# 標題
plt.title("中國確診人數前15地區的新增確診人數")
# y軸標簽
plt.ylabel('人數')
# 網格
plt.grid()
plt.show()

(4)福建新冠肺炎疫情地圖
#用pyecharts庫畫福建疫情分布地圖
import pandas as pd
from pyecharts.charts import Map,Geo
from pyecharts import options as opts
#自定義分段圖例
pieces=[
{"max": 100, "min": 70, "label": ">70", "color": "#B40404"},
{"max": 70, "min": 40, "label": "40-79", "color": "#DF0101"},
{"max": 40, "min": 20, "label": "20-40", "color": "#F78181"},
{"max": 20, "min": 10, "label": "10-20", "color": "#F5A9A9"},
{"max": 10, "min": 0, "label": "<10", "color": "#FFFFCC"},
]
name = []
values = []
#匯入資料
df_citi = pd.read_csv("各市的新冠肺炎疫情資料.csv")
# 處理資料,將資料處理成Map所要求的資料
for i in range(df_citi.shape[0]): # shape[0]:行數,shape[1]:列數
name.append(df_citi.at[i,'名稱'])
values.append(str(df_citi.at[i,'累計確診']))
total = [[name[i],values[i]] for i in range(len(name))]
# 創建地圖
chinaciti_map = (Map())
# 設定福建省地圖
chinaciti_map.add("確診人數",total ,maptype="福建",is_map_symbol_show=False)
chinaciti_map.set_global_opts(
# 地圖示題
title_opts=opts.TitleOpts(title="福建各市新冠肺炎確診人數"),
# 設定自定義圖例
visualmap_opts=opts.VisualMapOpts(max_=100,is_piecewise=True,pieces=pieces),
legend_opts=opts.LegendOpts(is_show=False)
)
# 直接在notebook顯示地圖,默認是保存為html檔案
chinaciti_map.render_notebook()

(5)福建新冠肺炎疫情餅圖
import matplotlib.pyplot as plt
import pandas as pd
# 創建畫布
plt.figure(figsize=(6,4))
#中文字體
plt.rcParams['font.family'] = ['SimHei']
#匯入資料
df_citi = pd.read_csv("各市的新冠肺炎疫情資料.csv")
labels = df_citi['名稱'].values
data = https://www.cnblogs.com/yusama/p/df_citi['累計確診'].values
plt.pie(data ,labels=labels, autopct='%1.1f%%')
#設定顯示影像為圓形
plt.axis('equal')
# 標題
plt.title('福建省各市新冠疫情比例')
plt.show()

(6)全球新冠肺炎疫情地圖
因為世界地圖的國家名是英文的,而爬取的資料的國家名是中文的,國家名對不上會導致資料顯示不到地圖上,所以要先建一個映射字典,將英文替換成中文
#中文國家名映射字典
nameMap = {
'Singapore Rep.':'新加坡','Dominican Rep.':'多米尼加','Palestine':'巴勒斯坦','Bahamas':'巴哈馬','Timor-Leste':'東帝汶','Afghanistan':'阿富汗',
'Guinea-Bissau':'幾內亞比紹',"C?te d'Ivoire":'科特迪瓦','Siachen Glacier':'錫亞琴冰川',"Br. Indian Ocean Ter.":'英屬印度洋領土','Angola':'安哥拉',
'Albania':'阿爾巴尼亞','United Arab Emirates':'阿聯酋','Argentina':'阿根廷','Armenia':'亞美尼亞','French Southern and Antarctic Lands':'法屬南半球和南極領地',
'Australia':'澳大利亞','Austria':'奧地利','Azerbaijan':'阿塞拜疆','Burundi':'布隆迪','Belgium':'比利時','Benin':'貝寧','Burkina Faso':'布基納法索',
'Bangladesh':'孟加拉國','Bulgaria':'保加利亞','The Bahamas':'巴哈馬','Bosnia and Herz.':'波斯尼亞和黑塞哥維那','Belarus':'白俄羅斯','Belize':'伯利茲',
'Bermuda':'百慕大','Bolivia':'玻利維亞','Brazil':'巴西','Brunei':'文萊','Bhutan':'不丹','Botswana':'博茨瓦納','Central African Rep.':'中非','Canada':'加拿大',
'Switzerland':'瑞士','Chile':'智利','China':'中國','Ivory Coast':'象牙海岸','Cameroon':'喀麥隆','Dem. Rep. Congo':'剛果(金)','Congo':'剛果(布)',
'Colombia':'哥倫比亞','Costa Rica':'哥斯達黎加', 'Cuba':'古巴','N. Cyprus':'北塞浦路斯','Cyprus':'塞浦路斯','Czech Rep.':'捷克','Germany':'德國',
'Djibouti':'吉布提','Denmark':'丹麥','Algeria':'阿爾及利亞','Ecuador':'厄瓜多爾','Egypt':'埃及','Eritrea':'厄立特里亞','Spain':'西班牙','Estonia':'愛沙尼亞',
'Ethiopia':'埃塞俄比亞','Finland':'芬蘭','Fiji':'斐','Falkland Islands':'福克蘭群島','France':'法國','Gabon':'加蓬','United Kingdom':'英國','Georgia':'格魯吉亞',
'Ghana':'加納','Guinea':'幾內亞','Gambia':'岡比亞','Guinea Bissau':'幾內亞比紹','Eq. Guinea':'赤道幾內亞','Greece':'希臘','Greenland':'格陵蘭島',
'Guatemala':'危地馬拉','French Guiana':'法屬圭亞那','Guyana':'圭亞那','Honduras':'洪都拉斯','Croatia':'克羅地亞','Haiti':'海地','Hungary':'匈牙利',
'Indonesia':'印度尼西亞','India':'印度','Ireland':'愛爾蘭','Iran':'伊朗','Iraq':'伊拉克','Iceland':'冰島','Israel':'以色列','Italy':'意大利','Jamaica':'牙買加',
'Jordan':'約旦','Japan':'日本','Kazakhstan':'哈薩克斯坦','Kenya':'肯尼亞','Kyrgyzstan':'吉爾吉斯斯坦','Cambodia':'柬埔寨','Korea':'韓國','Kosovo':'科索沃',
'Kuwait':'科威特','Lao PDR':'老撾','Lebanon':'黎巴嫩','Liberia':'利比里亞','Libya':'利比亞','Sri Lanka':'斯里蘭卡','Lesotho':'萊索托','Lithuania':'立陶宛',
'Luxembourg':'盧森堡','Latvia':'拉脫維亞','Morocco':'摩洛哥','Moldova':'摩爾多瓦','Madagascar':'馬達加斯加','Mexico':'墨西哥','Macedonia':'馬其頓',
'Mali':'馬里','Myanmar':'緬甸','Montenegro':'黑山','Mongolia':'蒙古國','Mozambique':'莫桑比克', 'Mauritania':'毛里塔尼亞','Malawi':'馬拉維',
'Malaysia':'馬來西亞','Namibia':'納米比亞','New Caledonia':'新喀里多尼亞','Niger':'尼日爾','Nigeria':'尼日利亞','Nicaragua':'尼加拉瓜','Netherlands':'荷蘭',
'Norway':'挪威','Nepal':'尼泊爾','New Zealand':'新西蘭','Oman':'阿曼','Pakistan':'巴基斯坦','Panama':'巴拿馬','Peru':'秘魯','Philippines':'菲律賓',
'Papua New Guinea':'巴布亞新幾內亞','Poland':'波蘭','Puerto Rico':'波多黎各','Dem. Rep. Korea':'朝鮮','Portugal':'葡萄牙','Paraguay':'巴拉圭',
'Qatar':'卡塔爾','Romania':'羅馬尼亞','Russia':'俄羅斯','Rwanda':'盧旺達','W. Sahara':'西撒哈拉','Saudi Arabia':'沙特阿拉伯','Sudan':'蘇丹',
'S. Sudan':'南蘇丹','Senegal':'塞內加爾','Solomon Is.':'所羅門群島','Sierra Leone':'塞拉利昂','El Salvador':'薩爾瓦多','Somaliland':'索馬里蘭',
'Somalia':'索馬里','Serbia':'塞爾維亞','Suriname':'蘇里南','Slovakia':'斯洛伐克','Slovenia':'斯洛文尼亞','Sweden':'瑞典','Swaziland':'斯威士蘭',
'Syria':'敘利亞','Chad':'乍得','Togo':'多哥','Thailand':'泰國','Tajikistan':'塔吉克斯坦','Turkmenistan':'土庫曼斯坦','East Timor':'東帝汶',
'Trinidad and Tobago':'特里尼達和多巴哥','Tunisia':'突尼斯','Turkey':'土耳其','Tanzania':'坦桑尼亞','Uganda':'烏干達','Ukraine':'烏克蘭',
'Uruguay':'烏拉圭','United States':'美國','Uzbekistan':'烏茲別克斯坦','Venezuela':'委內瑞拉','Vietnam':'越南','Vanuatu':'瓦努阿圖','West Bank':'西岸',
'Yemen':'也門','South Africa':'南非','Zambia':'贊比亞','Zimbabwe':'津巴布韋'
}
映射字典弄好后,就可以作圖了
#用pyecharts庫畫全球疫情分布地圖
import pandas as pd
from pyecharts.charts import Map,Geo
from pyecharts import options as opts
#自定義分段圖例
pieces=[
{"max": 50000000, "min": 10000000, "label": ">1000萬", "color": "#8B1A1A"},
{"max": 10000000, "min": 5000000, "label": "500萬-1000萬", "color": "#CD2626"},
{"max": 5000000, "min": 1000000, "label": "100萬-500萬", "color": "#EE2C2C"},
{"max": 1000000, "min": 100000, "label": "10萬-100萬", "color": "#FF3030"},
{"max": 100000, "min": 10000, "label": "10000-10萬", "color": "#FA8072"},
{"max": 10000, "min": 1000, "label": "1000-10000", "color": "#FFF8DC"},
{"max": 1000, "min": 0, "label": "<500", "color": "#FFFFF0"},
]
name = []
values = []
# 匯入資料
df_world = pd.read_csv("各國家的新冠肺炎疫情資料.csv")
df_china = pd.read_csv("各省的新冠肺炎疫情資料.csv")
# 因為爬取的全球資料不包括中國,所以要把中國的資料加進去
china_data = https://www.cnblogs.com/yusama/p/sum(df_china['累計確診'])
values.append(china_data)
name.append('中國')
# 處理資料,將資料處理成Map所要求的資料
for i in range(df_world.shape[0]): # shape[0]:行數,shape[1]:列數
name.append(df_world.at[i,'名稱'])
values.append(str(df_world.at[i,'累計確診']))
total = [[name[i],values[i]] for i in range(len(name))]
world_map = (Map())
#設定地圖為世界地圖、設定中文國家名、設定不顯示國家首都紅點
world_map.add("確診人數",total ,maptype="world",name_map=nameMap,is_map_symbol_show=False)
#設定不顯示國家名
world_map.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
world_map.set_global_opts(
# 標題
title_opts=opts.TitleOpts(title="全球各個國家新冠肺炎確診人數"),
#設定自定義分段圖例
visualmap_opts=opts.VisualMapOpts(max_=50000000,is_piecewise=True,pieces=pieces),
legend_opts=opts.LegendOpts(is_show=False)
)
# 直接在notebook顯示地圖,默認是保存為html檔案
world_map.render_notebook()

(7)全球新冠肺炎疫情確診人數排名前10的國家的條形圖
# 全球新冠肺炎疫情確診人數排名前10的國家
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
#畫布大小
fig=plt.figure(figsize=(10,8))
ax=fig.add_subplot(1,1,1)
#中文字體
plt.rcParams['font.family'] = ['SimHei']
#匯入資料
df_world = pd.read_csv("各國家的新冠肺炎疫情資料.csv")
sns.barplot(x = df_world.iloc[0:11,0].values,y =df_world.iloc[0:11,2].values,palette="rocket")
#y軸刻度標簽
ax.set_yticks([5000000,10000000,15000000,20000000,25000000,30000000,35000000])
ax.set_yticklabels(["500萬","1000萬","1500萬","2000萬","2500萬","3000萬","3500萬"],fontsize=12)
#標題
plt.title("全球新冠肺炎疫情確診人數排名前10的國家",fontsize=12)
#y軸標簽
plt.ylabel("確 診 人 數")
plt.show()

(8)全球新冠肺炎疫情確診人數前5國家的確診人數、治愈人數的條形圖
import matplotlib.pyplot as plt
#畫布大小
fig=plt.figure(figsize=(10,8))
ax=fig.add_subplot(1,1,1)
#中文字體
plt.rcParams['font.family'] = ['SimHei']
#匯入資料
df_world = pd.read_csv("各國家的新冠肺炎疫情資料.csv")
#國家
country = df_world.iloc[0:6,0]
#確診人數
diagnosis = df_world.iloc[0:6,2]
#治愈人數
cured = df_world.iloc[0:6,3]
x = list(range(len(country)))
#設定間距
total_width, n = 0.5, 2
width = total_width / n
#柱狀圖1
for i in range(len(x)):
x[i] += width
plt.bar(x, diagnosis, width=width, label='確診人數', tick_label=country,color='#FF3030' )
#柱狀圖2
for i in range(len(x)):
x[i] += width
plt.bar(x, cured, width=width, label='治愈人數',color='#32CD32')
#y軸刻度標簽
ax.set_yticks([5000000,10000000,15000000,20000000,25000000,30000000,35000000])
ax.set_yticklabels(["500萬","1000萬","1500萬","2000萬","2500萬","3000萬","3500萬"],fontsize=12)
#標題
plt.title("全球新冠肺炎疫情確診人數前5國家的確診人數、治愈人數")
#y軸標簽
plt.ylabel("確 診 人 數",fontsize=12)
#圖例
plt.legend(loc='upper right',fontsize=12)
plt.show()

(9)全球新冠肺炎疫情確診人數前15國家的治愈率與死亡率的折線圖
import pandas as pd
import matplotlib.pyplot as plt
# 創建畫布
fig=plt.figure(figsize=(10,8))
ax=fig.add_subplot(1,1,1)
#中文字體
plt.rcParams['font.family'] = ['SimHei']
#匯入資料
df_world = pd.read_csv("各國家的新冠肺炎疫情資料.csv")
df_world['治愈率'] = df_world['治愈']/df_world['累計確診']
df_world['死亡率'] = df_world['死亡']/df_world['累計確診']
plt.plot(df_world.iloc[0:16,0],df_world.iloc[0:16,5],label="治愈率")
plt.plot(df_world.iloc[0:16,0],df_world.iloc[0:16,6],label="死亡率")
#y軸刻度標簽
ax.set_yticks([0.05,0.2,0.4,0.6,0.8,1.0])
ax.set_yticklabels(["5 %","20 %","40 %","60 %","80 %","100 %"],fontsize=12)
plt.legend(loc='center right',fontsize=12)
plt.title("全球新冠肺炎疫情確診人數前15國家的治愈率與死亡率")
plt.grid()
plt.show()

完整代碼
疫情資料爬取的完整代碼
import requests
from bs4 import BeautifulSoup
import pandas as pd
# 主函式
def main():
# 中國新冠疫情資料網址
url = "https://www.haoyunbb.com/news/3/36573.html"
html = getUrlData(url)
total_data1 = getProvinceData(html)
total_data2 = getCitiData(html)
# 全球(國外)新冠疫情資料網址
url = "https://www.haoyunbb.com/news/3/39230.html"
html = getUrlData(url)
total_data3 = getWorldData(html)
saveData(total_data1,total_data2,total_data3)
# 獲取網頁資料
def getUrlData(url):
try:
# get請求,設定超時時間
r = requests.get(url,headers=headers,timeout=30)
r.raise_for_status
r.encoding=r.apparent_encoding
html = r.text
return html
except:
return '發生例外'
# 獲取中國每個省的疫情資料
def getProvinceData(html):
total_data=https://www.cnblogs.com/yusama/p/[]
temporary=[]
new_diagnosis_data=[]
cumulative_diagnosis_data=[]
cured_data=[]
dead_data=[]
soup = BeautifulSoup(html,'html.parser')
# 找到 class=data-list 的div標簽
data = https://www.cnblogs.com/yusama/p/soup.find('div',{'class':'data-list'})
ul = data.find('ul')
div = ul.find_all('div',{'class':'list-pro-name'})
province_name_data=https://www.cnblogs.com/yusama/p/[]
for i in div:
# 獲取省的名稱
# 省名稱在label標簽里
province_name = i.find('label').string
province_name_data.append(province_name)
# 用CSS選擇器獲取第一層的資料(每個省的資料)
diagnosis = soup.select('div.data-list > ul > li > div.list-city-data')
for i in diagnosis:
temporary.append(i.string)
total = [temporary[i:i+4] for i in range(0,len(temporary),4)]
for i in range(len(total)):
# 獲取新增確診人數
new_diagnosis_data.append(total[i][0])
# 獲取累計確診人數
cumulative_diagnosis_data.append(total[i][1])
# 獲取治愈人數
cured_data.append(total[i][2])
# 獲取死亡人數
dead_data.append(total[i][3])
total_data.append(province_name_data)
total_data.append(new_diagnosis_data)
total_data.append(cumulative_diagnosis_data)
total_data.append(cured_data)
total_data.append(dead_data)
return total_data
# 獲取福建省每個市的疫情資料
def getCitiData(html):
citi_name_data=https://www.cnblogs.com/yusama/p/[]
new_diagnosis_data=[]
cumulative_diagnosis_data=[]
cured_data=[]
dead_data=[]
total_data=[]
soup = BeautifulSoup(html,'html.parser')
data = https://www.cnblogs.com/yusama/p/soup.find('div',{'class':'data-list'})
# 找到有唯一標識的屬性的input標簽
input1 = data.find('input',{'id':'_209'})
# 找到input標簽的的父標簽
div = input1.parent
# 找到所有的li
li = div.find_all('li')
# 遍歷li組成的串列
for i in range(1,len(li)):
# 獲取市名稱
citi_name = li[i].find('div',{'class':'list-city-name'})
citi_name_data.append(citi_name.string+'市')
div = li[i].find_all('div',{'class':'list-city-data'})
# 獲取新增確診人數
new_diagnosis = div[0].string
new_diagnosis_data.append(new_diagnosis)
# 獲取累計確診人數
cumulative_diagnosis = div[1].string
cumulative_diagnosis_data.append(cumulative_diagnosis)
# 獲取治愈人數
cured = div[2].string
cured_data.append(cured)
# 獲取死亡人數
dead = div[3].string
dead_data.append(dead)
total_data.append(citi_name_data)
total_data.append(new_diagnosis_data)
total_data.append(cumulative_diagnosis_data)
total_data.append(cured_data)
total_data.append(dead_data)
return total_data
# 獲取全球每個國家的疫情資料
def getWorldData(html):
country_name_data=https://www.cnblogs.com/yusama/p/[]
new_diagnosis_data=[]
cumulative_diagnosis_data=[]
cured_data=[]
dead_data=[]
total_data=[]
soup = BeautifulSoup(html,'html.parser')
data = https://www.cnblogs.com/yusama/p/soup.find('div',{'class':'data-list'})
# 因為有兩層li,我們需要的是第二層的li,所以可以通過CSS選擇器來獲取第二層的li
data_list = data.select('ul > li > div > div > ul > li')
for i in range(12,len(data_list)-1):
div = data_list[i].find_all('div')
# 獲取國家名稱
country_name = div[0].string
country_name_data.append(country_name)
# 獲取新增確診人數
new_diagnosis = div[1].string
new_diagnosis_data.append(new_diagnosis)
# 獲取累計確診人數
cumulative_diagnosis = div[2].string
cumulative_diagnosis_data.append(cumulative_diagnosis)
# 獲取治愈人數
cured = div[3].string
cured_data.append(cured)
# 獲取死亡人數
dead = div[4].string
dead_data.append(dead)
total_data.append(country_name_data)
total_data.append(new_diagnosis_data)
total_data.append(cumulative_diagnosis_data)
total_data.append(cured_data)
total_data.append(dead_data)
return total_data
# 保存資料
def saveData(total_data1,total_data2,total_data3):
df1 = data(total_data1)
df2 = data(total_data2)
df3 = data(total_data3)
# 將爬取的資料保存為csv檔案
df1.to_csv("各省的新冠肺炎疫情資料.csv",encoding='utf-8')
df2.to_csv("各市的新冠肺炎疫情資料.csv",encoding='utf-8')
df3.to_csv("各國家的新冠肺炎疫情資料.csv",encoding='utf-8')
def data(total_data):
df = pd.DataFrame({'名稱':total_data[0],'新增確診':total_data[1],'累計確診':total_data[2],'治愈':total_data[3],'死亡':total_data[4]})
# 將名稱列設定為索引列
df = df.set_index('名稱')
return df
# 程式入口
if __name__== "__main__":
main()
# 資料清洗與處理
#因為全球疫情的資料量較大,所以我們可以通過pandas庫來查看資料是否有例外、缺失、重復
import pandas as pd
#匯入資料
df_world = pd.read_csv("各國家的新冠肺炎疫情資料.csv")
# 查看資料的簡要資訊
# 通過查看資料的簡要資訊,資料正常,資料的最小值也不是負數
df_world.describe()
# 查看是否有空值,有空值回傳True,沒有空值回傳False
df_world.isnull().value_counts()
# 查看是否有重復行,有重復行回傳True,沒有重復行回傳False
df_world.duplicated()
#根據累計確診人數對資料進行降序排序
df = df_world.sort_values(by='累計確診',ascending=False)
#保存處理后的資料
import pandas as pd
df = df.set_index('名稱')
df.to_csv("各國家的新冠肺炎疫情資料.csv",encoding='utf-8')
df_world = pd.read_csv("各國家的新冠肺炎疫情資料.csv")
df_world.head()
# 資料可視化
# 用pyecharts庫畫中國新冠疫情地圖
from pyecharts import options as opts
from pyecharts.charts import Map
import pandas as pd
# 自定義分段圖例
pieces=[
{"max": 70000, "min": 3000, "label": ">3000", "color": "#B40404"},
{"max": 3000, "min": 1000, "label": "1000-3000", "color": "#DF0101"},
{"max": 1000, "min": 100, "label": "100-1000", "color": "#F78181"},
{"max": 100, "min": 10, "label": "10-100", "color": "#F5A9A9"},
{"max": 10, "min": 0, "label": "<10", "color": "#FFFFCC"},
]
name = []
values = []
# 匯入資料
df = pd.DataFrame(pd.read_csv("各省的新冠肺炎疫情資料.csv"))
# 處理資料,將資料處理成Map所要求的資料
for i in range(df.shape[0]): # shape[0]:行數,shape[1]:列數
name.append(df.at[i,'名稱'])
values.append(str(df.at[i,'累計確診']))
total = [[name[i],values[i]] for i in range(len(name))]
# 創建地圖(Map)
china_map = (Map())
# 設定中國地圖
china_map.add("確診人數",total ,maptype="china",is_map_symbol_show=False)
china_map.set_global_opts(
# 設定地圖示題
title_opts=opts.TitleOpts(title="中國各省、直轄市、自治區、特別行政區新冠肺炎確診人數"),
# 設定自定義圖例
visualmap_opts=opts.VisualMapOpts(max_=70000,is_piecewise=True,pieces=pieces),
legend_opts=opts.LegendOpts(is_show=False)
)
# 直接在notebook顯示地圖,默認是保存為html檔案
china_map.render_notebook()
中國確診人數前15地區的治愈率與死亡率折線圖
import pandas as pd
import matplotlib.pyplot as plt
# 創建畫布
fig=plt.figure(figsize=(10,8))
ax=fig.add_subplot(1,1,1)
#中文字體
plt.rcParams['font.family'] = ['SimHei']
# 匯入資料
df_china = pd.read_csv("各省的新冠肺炎疫情資料.csv")
df_china['治愈率'] = df_china['治愈']/df_china['累計確診']
df_china['死亡率'] = df_china['死亡']/df_china['累計確診']
plt.plot(df_china.iloc[0:16,0],df_china.iloc[0:16,5],label="治愈率")
plt.plot(df_china.iloc[0:16,0],df_china.iloc[0:16,6],label="死亡率")
# y軸刻度標簽
ax.set_yticks([0.05,0.2,0.4,0.6,0.8,1.0])
ax.set_yticklabels(["5 %","20 %","40 %","60 %","80 %","100 %"],fontsize=12)
# 圖例
plt.legend(loc='center right',fontsize=12)
# 標題
plt.title("中國確診人數前15地區的治愈率與死亡率")
# 網格
plt.grid()
plt.show()
# 中國確診人數前15地區的新增確診人數折線圖
import pandas as pd
import matplotlib.pyplot as plt
# 創建畫布
fig=plt.figure(figsize=(10,8))
#中文字體
plt.rcParams['font.family'] = ['SimHei']
#匯入資料
df_china = pd.read_csv("各省的新冠肺炎疫情資料.csv")
plt.plot(df_china.iloc[0:15,0],df_china.iloc[0:15,1],label="新增確診")
# 圖例
plt.legend(fontsize=12)
# 標題
plt.title("中國確診人數前15地區的新增確診人數")
# y軸標簽
plt.ylabel('人數')
# 網格
plt.grid()
plt.show()
#用pyecharts庫畫福建疫情分布地圖
import pandas as pd
from pyecharts.charts import Map,Geo
from pyecharts import options as opts
#自定義分段圖例
pieces=[
{"max": 100, "min": 70, "label": ">70", "color": "#B40404"},
{"max": 70, "min": 40, "label": "40-79", "color": "#DF0101"},
{"max": 40, "min": 20, "label": "20-40", "color": "#F78181"},
{"max": 20, "min": 10, "label": "10-20", "color": "#F5A9A9"},
{"max": 10, "min": 0, "label": "<10", "color": "#FFFFCC"},
]
name = []
values = []
#匯入資料
df_citi = pd.read_csv("各市的新冠肺炎疫情資料.csv")
# 處理資料,將資料處理成Map所要求的資料
for i in range(df_citi.shape[0]): # shape[0]:行數,shape[1]:列數
name.append(df_citi.at[i,'名稱'])
values.append(str(df_citi.at[i,'累計確診']))
total = [[name[i],values[i]] for i in range(len(name))]
# 創建地圖
chinaciti_map = (Map())
# 設定福建省地圖
chinaciti_map.add("確診人數",total ,maptype="福建",is_map_symbol_show=False)
chinaciti_map.set_global_opts(
# 地圖示題
title_opts=opts.TitleOpts(title="福建各市新冠肺炎確診人數"),
# 設定自定義圖例
visualmap_opts=opts.VisualMapOpts(max_=100,is_piecewise=True,pieces=pieces),
legend_opts=opts.LegendOpts(is_show=False)
)
# 直接在notebook顯示地圖,默認是保存為html檔案
chinaciti_map.render_notebook()
#福建省各市新冠疫情比例餅圖
import matplotlib.pyplot as plt
import pandas as pd
# 創建畫布
plt.figure(figsize=(6,4))
#中文字體
plt.rcParams['font.family'] = ['SimHei']
#匯入資料
df_citi = pd.read_csv("各市的新冠肺炎疫情資料.csv")
labels = df_citi['名稱'].values
data = https://www.cnblogs.com/yusama/p/df_citi['累計確診'].values
plt.pie(data ,labels=labels, autopct='%1.1f%%')
#設定顯示影像為圓形
plt.axis('equal')
# 標題
plt.title('福建省各市新冠疫情比例')
plt.show()
#用pyecharts庫畫全球疫情分布地圖
import pandas as pd
from pyecharts.charts import Map,Geo
from pyecharts import options as opts
#自定義分段圖例
pieces=[
{"max": 50000000, "min": 10000000, "label": ">1000萬", "color": "#8B1A1A"},
{"max": 10000000, "min": 5000000, "label": "500萬-1000萬", "color": "#CD2626"},
{"max": 5000000, "min": 1000000, "label": "100萬-500萬", "color": "#EE2C2C"},
{"max": 1000000, "min": 100000, "label": "10萬-100萬", "color": "#FF3030"},
{"max": 100000, "min": 10000, "label": "10000-10萬", "color": "#FA8072"},
{"max": 10000, "min": 1000, "label": "1000-10000", "color": "#FFF8DC"},
{"max": 1000, "min": 0, "label": "<500", "color": "#FFFFF0"},
]
name = []
values = []
# 匯入資料
df_world = pd.read_csv("各國家的新冠肺炎疫情資料.csv")
df_china = pd.read_csv("各省的新冠肺炎疫情資料.csv")
# 因為爬取的全球資料不包括中國,所以要把中國的資料加進去
china_data = https://www.cnblogs.com/yusama/p/sum(df_china['累計確診'])
values.append(china_data)
name.append('中國')
# 處理資料,將資料處理成Map所要求的資料
for i in range(df_world.shape[0]): # shape[0]:行數,shape[1]:列數
name.append(df_world.at[i,'名稱'])
values.append(str(df_world.at[i,'累計確診']))
total = [[name[i],values[i]] for i in range(len(name))]
world_map = (Map())
#設定地圖為世界地圖、設定中文國家名、設定不顯示國家首都紅點
world_map.add("確診人數",total ,maptype="world",name_map=nameMap,is_map_symbol_show=False)
#設定不顯示國家名
world_map.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
world_map.set_global_opts(
# 標題
title_opts=opts.TitleOpts(title="全球各個國家新冠肺炎地圖"),
#設定自定義分段圖例
visualmap_opts=opts.VisualMapOpts(max_=50000000,is_piecewise=True,pieces=pieces),
legend_opts=opts.LegendOpts(is_show=False)
)
# 直接在notebook顯示地圖,默認是保存為html檔案
world_map.render_notebook()
# 全球新冠肺炎疫情確診人數排名前10的國家
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
#畫布大小
fig=plt.figure(figsize=(10,8))
ax=fig.add_subplot(1,1,1)
#中文字體
plt.rcParams['font.family'] = ['SimHei']
#匯入資料
df_world = pd.read_csv("各國家的新冠肺炎疫情資料.csv")
sns.barplot(x = df_world.iloc[0:11,0].values,y =df_world.iloc[0:11,2].values,palette="rocket")
#y軸刻度標簽
ax.set_yticks([5000000,10000000,15000000,20000000,25000000,30000000,35000000])
ax.set_yticklabels(["500萬","1000萬","1500萬","2000萬","2500萬","3000萬","3500萬"],fontsize=12)
#標題
plt.title("全球新冠肺炎疫情確診人數排名前10的國家",fontsize=12)
#y軸標簽
plt.ylabel("確 診 人 數")
plt.show()
import matplotlib.pyplot as plt
#畫布大小
fig=plt.figure(figsize=(10,8))
ax=fig.add_subplot(1,1,1)
#中文字體
plt.rcParams['font.family'] = ['SimHei']
#匯入資料
df_world = pd.read_csv("各國家的新冠肺炎疫情資料.csv")
#國家
country = df_world.iloc[0:6,0]
#確診人數
diagnosis = df_world.iloc[0:6,2]
#治愈人數
cured = df_world.iloc[0:6,3]
x = list(range(len(country)))
#設定間距
total_width, n = 0.5, 2
width = total_width / n
#柱狀圖1
for i in range(len(x)):
x[i] += width
plt.bar(x, diagnosis, width=width, label='確診人數', tick_label=country,color='#FF3030' )
#柱狀圖2
for i in range(len(x)):
x[i] += width
plt.bar(x, cured, width=width, label='治愈人數',color='#32CD32')
#y軸刻度標簽
ax.set_yticks([5000000,10000000,15000000,20000000,25000000,30000000,35000000])
ax.set_yticklabels(["500萬","1000萬","1500萬","2000萬","2500萬","3000萬","3500萬"],fontsize=12)
#標題
plt.title("全球新冠肺炎疫情確診人數前5國家的確診人數、治愈人數")
#y軸標簽
plt.ylabel("確 診 人 數",fontsize=12)
#圖例
plt.legend(loc='upper right',fontsize=12)
plt.show()
import pandas as pd
import matplotlib.pyplot as plt
# 創建畫布
fig=plt.figure(figsize=(10,8))
ax=fig.add_subplot(1,1,1)
#中文字體
plt.rcParams['font.family'] = ['SimHei']
#匯入資料
df_world = pd.read_csv("各國家的新冠肺炎疫情資料.csv")
df_world['治愈率'] = df_world['治愈']/df_world['累計確診']
df_world['死亡率'] = df_world['死亡']/df_world['累計確診']
plt.plot(df_world.iloc[0:16,0],df_world.iloc[0:16,5],label="治愈率")
plt.plot(df_world.iloc[0:16,0],df_world.iloc[0:16,6],label="死亡率")
#y軸刻度標簽
ax.set_yticks([0.05,0.2,0.4,0.6,0.8,1.0])
ax.set_yticklabels(["5 %","20 %","40 %","60 %","80 %","100 %"],fontsize=12)
plt.legend(loc='center right',fontsize=12)
plt.title("全球新冠肺炎疫情確診人數前15國家的治愈率與死亡率")
plt.grid()
plt.show()
總結
因為這次的主題爬蟲爬的是最基礎的網站,所以進行的還是比較順利的,在資料的可視化上,除了用pyecharts庫的Map模塊將資料顯示到地圖上花了一些功夫,其他都還好,達到了我的預期效果,
因為現在很多網站是用JSON存盤資料或者用JS動態加載資料的,所以之后會多學習這些方面的知識,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/287050.html
標籤:Python
上一篇:PHP中操作資料庫的預處理陳述句
