文章目錄
- 1 前言
- 2 開發簡介
- 3 資料集
- weibo.json 新浪微博實時熱搜前50的資料
- ProvinceData.json 省市疫情詳情
- 4 實作技術
- 4.1 系統架構
- 4.2 開發環境
- 4.3 疫情地圖
- 4.3.1 填充圖(Choropleth maps)
- 4.3.2 氣泡圖
- 4.4 全國疫情實時追蹤
- 4.6 其他頁面
- 5 關鍵代碼
1 前言
Hi,大家好,這里是丹成學長,今天做一個 基于大資料的疫情可視化系統,這只是一個demo,嘗試對疫情資料進行分析,并可視化系統
畢設幫助,開題指導,技術解答
🇶746876041
2 開發簡介
學長從各省累計確診人數隨時間增長的態勢以及空間分布隨時間增長的態勢入手,利用所收集的資料將各省累計確診人數的時空分布用地圖、折線圖、堆疊條形圖的形式呈現出來,從總體態勢進行大致分析,然后再通過在不同粒度上展示各省疫情相關的詳細資訊,以發現其在不同時間段影響其態勢變化的原因(境外輸入、相關政策頒布等),
同時還將疫情相關確診、死亡等資料與各省的GDP、受教育程度、城鎮化率、醫療衛生水平進行聯系,以發現其與GDP、受教育程度、城鎮化率之間是否存在關系,
其目標用戶是政府等防控機關,通過本系統可以分析疫情時空分布模式、監控疫情發展態勢、評估疫情防控措施,
3 資料集
資料源于爬蟲與手動搜集:
weibo.json 新浪微博實時熱搜前50的資料

ProvinceData.json 省市疫情詳情

源于中國國家統計局(2018年中國統計年鑒)的資料
2020-01-10至2020-02-06資料來自國家,各省,武漢市衛健委疫情公告,2020-02-07后資料從今日頭條介面采集


境外輸入資料(手動從網上新聞中搜集)

4 實作技術
4.1 系統架構

4.2 開發環境
- 1、Node.js(前端Vue和后端node都依賴該環境)
- 2、開發工具:Git,vscode,Hbuilder,pycharm
- 3、開發語言:Python,HTML+CSS+JavaScript
- 4、重點依賴庫:echarts,bootstrap,jQuery
4.3 疫情地圖
新型冠狀病毒肺炎已經開始全球蔓延,形勢越來越嚴峻,我們除了關注國內發展疫情發展,也開始關注境外疫情的發展變化,通過地理可視化我們能夠很直觀的看到的各個區域的疫情嚴重程度,
4.3.1 填充圖(Choropleth maps)
- 填充圖適合表達區域之間的差異,
- 填充圖能夠很好的展現形全域差異,細微的差異很難表達,
- 但填充圖的展現效果受區域面積影響比較大,容易形成誤導

上面的填充圖,我們可以關注到亞洲,歐洲,美洲三大疫情區域,但是我們很難關注到,意大利、韓國的疫情嚴重程度,
4.3.2 氣泡圖
氣泡圖使用不同大小的圓圈表示區域上的數值,它在每個地理坐標上顯示一個氣泡,或在每個區域顯示一個氣泡,
下圖我們以氣泡圖形式進行疫情地圖可視化

通過氣泡圖我們可以很明確的看出世界上疫情比較嚴重的國家,而且不會受到區域面積的干擾,歐洲一些面積比較小的國家我們也能夠清晰的識別出來,氣泡圖表達方式缺點在于氣泡過多,過大將會產生遮蓋現在,
氣泡是一種比較好的展現形式,如果使用方式不當也會產生干擾,比如資料映射方法選擇,顏色色帶選擇都會影響資料表達的結果,
關鍵代碼:
# 作者:丹成學長 q746876041
import json
import requests
import jsonpath
from pyecharts.charts import Map,Geo
from pyecharts import options as opts
from pyecharts.globals import GeoType,RenderType
# 1.目標網站
url='https://api.inews.qq.com/newsqa/v1/automation/foreign/country/ranklist'
# 2.請求資源
resp=requests.get(url)
# 3.提取資料
# 型別轉換 json-->dict
data=json.loads(resp.text)
name = jsonpath.jsonpath(data,"$..name")
# print(name)
confirm = jsonpath.jsonpath(data,"$..confirm")
# print(confirm)
data_list = zip(name,confirm)
# print(list(data_list))
# 4.可視化 matplotlib 和 pyecharts
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':'日本',
'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':'津巴布韋'
}
map = Map().add(series_name='世界疫情分布',
data_pair=data_list,
maptype='world',
name_map=nameMap,
is_map_symbol_show=False
)
map.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
map.render('世界疫情分布情況3.html')
# 作者:丹成學長 q746876041
4.4 全國疫情實時追蹤
全國疫情實時追蹤頁面,支持折線圖、條形圖、扇形圖、地圖熱力圖展示,圖表由Echarts實作,支持左上角側邊欄跳轉,


4.6 其他頁面



5 關鍵代碼
兩個資料表
CREATE TABLE `history` (
`ds` datetime NOT NULL COMMENT '日期',
`confirm` int(11) DEFAULT NULL COMMENT '累計確診',
`confirm_add` int(11) DEFAULT NULL COMMENT '當日新增確診',
`suspect` int(11) DEFAULT NULL COMMENT '剩余疑似',
`suspect_add` int(11) DEFAULT NULL COMMENT '當日新增疑似',
`heal` int(11) DEFAULT NULL COMMENT '累計治愈',
`heal_add` int(11) DEFAULT NULL COMMENT '當日新增治愈',
`dead` int(11) DEFAULT NULL COMMENT '累計死亡',
`dead_add` int(11) DEFAULT NULL COMMENT '當日新增死亡',
PRIMARY KEY (`ds`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `details` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`update_time` datetime DEFAULT NULL COMMENT '資料最后更新時間',
`province` varchar(50) DEFAULT NULL COMMENT '省',
`city` varchar(50) DEFAULT NULL COMMENT '市',
`confirm` int(11) DEFAULT NULL COMMENT '累計確診',
`confirm_add` int(11) DEFAULT NULL COMMENT '新增治愈',
`heal` int(11) DEFAULT NULL COMMENT '累計治愈',
`dead` int(11) DEFAULT NULL COMMENT '累計死亡',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
import requests
import json
import time
import pymysql
#回傳歷史資料和當日詳細資料
def get_tencent_data():
url1 = "https://view.inews.qq.com/g2/getOnsInfo?name=disease_h5"
url2 = "https://view.inews.qq.com/g2/getOnsInfo?name=disease_other"
headers = {
'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36'
}
r1 = requests.get(url1, headers)
r2 = requests.get(url2, headers)
#json字串轉字典
res1 = json.loads(r1.text)
res2 = json.loads(r2.text)
data_all1 = json.loads(res1["data"])
data_all2 = json.loads(res2["data"])
#歷史資料
history = {}
for i in data_all2["chinaDayList"]:
ds = "2020." + i["date"]
tup = time.strptime(ds, "%Y.%m.%d") # 匹配時間
ds = time.strftime("%Y-%m-%d", tup) #改變時間輸入格式,不然插入資料庫會報錯,資料庫是datatime格式
confirm = i["confirm"]
suspect = i["suspect"]
heal = i["heal"]
dead = i["dead"]
history[ds] = {"confirm": confirm, "suspect": suspect, "heal": heal, "dead": dead}
for i in data_all2["chinaDayAddList"]:
ds = "2020." + i["date"]
tup = time.strptime(ds, "%Y.%m.%d") # 匹配時間
ds = time.strftime("%Y-%m-%d", tup) #改變時間輸入格式,不然插入資料庫會報錯,資料庫是datatime格式
confirm = i["confirm"]
suspect = i["suspect"]
heal = i["heal"]
dead = i["dead"]
history[ds].update({"confirm_add": confirm, "suspect_add": suspect, "heal_add": heal, "dead_add": dead})
#當日詳細資料
details = []
update_time = data_all1["lastUpdateTime"]
data_country = data_all1["areaTree"] #list 25個國家
data_province = data_country[0]["children"] #中國各省
for pro_infos in data_province:
province = pro_infos["name"] #省名
for city_infos in pro_infos["children"]:
city = city_infos["name"]
confirm = city_infos["total"]["confirm"]
confirm_add = city_infos["today"]["confirm"]
heal = city_infos["total"]["heal"]
dead = city_infos["total"]["dead"]
details.append([update_time, province, city, confirm, confirm_add, heal, dead])
return history, details
def get_conn():
#建立連接
conn = pymysql.connect(host="127.0.0.1", user="root", password="*", db="cov", charset="utf8")
#創建游標
cursor = conn.cursor()
return conn,cursor
def close_conn(conn,cursor):
if cursor:
cursor.close()
if conn:
conn.close()
#插入details資料
def update_details():
cursor = None
conn = None
try:
li = get_tencent_data()[1] #0是歷史資料,1是當日詳細資料
conn,cursor = get_conn()
sql = "insert into details(update_time,province,city,confirm,confirm_add,heal,dead) values(%s,%s,%s,%s,%s,%s,%s)"
sql_query = "select %s=(select update_time from details order by id desc limit 1)" #對比當前最大時間戳
#對比當前最大時間戳
cursor.execute(sql_query,li[0][0])
if not cursor.fetchone()[0]:
print(f"{time.asctime()}開始更新資料")
for item in li:
cursor.execute(sql,item)
conn.commit()
print(f"{time.asctime()}更新到最新資料")
else:
print(f"{time.asctime()}已是最新資料!")
except:
traceback.print_exc()
finally:
close_conn(conn,cursor)
#插入history資料
def insert_history():
cursor = None
conn = None
try:
dic = get_tencent_data()[0]#0代表歷史資料字典
print(f"{time.asctime()}開始插入歷史資料")
conn,cursor = get_conn()
sql = "insert into history values (%s,%s,%s,%s,%s,%s,%s,%s,%s)"
for k,v in dic.items():
cursor.execute(sql,[k, v.get("confirm"),v.get("confirm_add"),v.get("suspect"),
v.get("suspect_add"),v.get("heal"),v.get("heal_add"),
v.get("dead"),v.get("dead_add")])
conn.commit()
print(f"{time.asctime()}插入歷史資料完畢")
except:
traceback.print_exc()
finally:
close_conn(conn,cursor)
#更新歷史資料
def update_history():
cursor = None
conn = None
try:
dic = get_tencent_data()[0]#0代表歷史資料字典
print(f"{time.asctime()}開始更新歷史資料")
conn,cursor = get_conn()
sql = "insert into history values (%s,%s,%s,%s,%s,%s,%s,%s,%s)"
sql_query = "select confirm from history where ds=%s"
for k,v in dic.items():
if not cursor.execute(sql_query,k):
cursor.execute(sql,[k, v.get("confirm"),v.get("confirm_add"),v.get("suspect"),
v.get("suspect_add"),v.get("heal"),v.get("heal_add"),
v.get("dead"),v.get("dead_add")])
conn.commit()
print(f"{time.asctime()}歷史資料更新完畢")
except:
traceback.print_exc()
finally:
close_conn(conn,cursor)
insert_history()
update_details()
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/344159.html
標籤:其他
上一篇:關于本地向虛擬機上的Hadoop上傳檔案時報錯解決方案
下一篇:ELK日志分析系統
