本来只想着通过api进行爬虫,爬取一些数据来试试水的,结果爬取到了疫情的数据之后,忽然又想着用可视化图表把疫情的数据给表示上去,然后就有了这篇博客,中间遇到或小或大的各类问题,都得到了一一的妥善解决。
获取数据
数据的获取,我是在“天行数据”官网获取了一个海外肺炎疫情数据(该网站有很多免费的api接口可以使用,注册即可用)
官网给的参考代码可以直接拿来用
这里面的key是你自己注册之后官网会给你的一个小密钥,修改成自己的,就可以直接拿来使用,不过我觉得这里官网给的python代码是python2的代码,我这里用的是python3.7.9,这里没法下载urllib2第三方库,因为在python3.x中就将urllib和urllib2做了一个整合,所以这里我做了一些小改变,但整体含义不变
这里面的key我给的是“?”,这里填上自己的密钥即可,在这里用分割线上面的代码和下面的代码都可以获取数据
import sys, urllib, json
import requests
import urllib.request as req
url = 'http://api.tianapi.com/ncovabroad/index?key=?'
req = req.Request(url)
resp = urllib.request.urlopen(req)
content = resp.read()
if(content):
print(content)
print()
print("***************************************************************")
print()
res = requests.get(url)
print(res.text)
这里获得的数据格式是json的格式:
(前面的分割是我自己做的,为了看起来方便,如果不做分割,那结果就是下面那样)
处理数据
这里我们需要的数据是“国家”、“感染人数“,所以我们单独将这两个数据给提取出来
定义一个获取数据的类
# 定义获取数据的类
class Crawl:
def __init__(self, url):
self.url = url
def get_data(self):
r = requests.get(self.url)
content = json.loads(r.text)
# print('content', content)
return content
获取所有国家的名称
# 获取所有国家名称
def provinceName():
url = 'http://api.tianapi.com/ncovabroad/index?key=?'
s = Crawl(url)
content = s.get_data()
list1 = []
for i in range(101):
list1.append(content['newslist'][i]['provinceName'])
return list1
获取当前感染人数
# 获取currentConfirmedCount--当前感染人数
def currentConfirmedCount():
url = 'http://api.tianapi.com/ncovabroad/index?key=?'
s = Crawl(url)
content = s.get_data()
list1 = []
for i in range(101):
list1.append(content['newslist'][i]['currentConfirmedCount'])
return list1
值得一提的是,这里我在测试数据的时候,写了三个,一个是获取大洲名称,一个是获取国家名称,一个是获取感染人数,然后会出现这个错误
后来一点一点测试问题发现,这个问题并不是写错了代码,而是因为数据跑的太快,被确认为是在爬虫,所以这里给它一个休眠就可
这里给它一个休眠之后,就可以持续的爬取数据了
不过我们这里只需要两列数据,不需要加上休眠
在这里获取了”国家“和”感染人数“两列之后,在通过zip函数将这两列数据关联到一起,并变成一个集合打印出来
nvs = list(zip(provinceName,currentConfirmedCount))
print(nvs)
这里我们所需要的数据就变成了(“国家”:“感染人数”)
构图
这里我们通过
pyecharts.charts 中的 Map 来进行绘图
这里的绘图中,我们所需要的数据格式是下图上面的这种类型,但是我们的pycharm运行出来的结果是下图下面的这种类型,我们对它做一个全员转换即可得到上面这种类型
def draw():
map1 = (
Map()
.add("感染人数", nvs, maptype="world")
.set_global_opts(
visualmap_opts=opts.VisualMapOpts(max_=1000)
)
)
map1.render("mycharts.html")
在这里我们又会遇到一个小问题,就是,这里我们运行出来的图片的样式为这样,这里不管是哪个国家,显示的人数都为0,是因为我们这里图片显示的国家名称都是英文,但是我们所给的数据的格式都是中文,这里我们还需要对数据做一个变换
这里我从网上找到了一份国家和英文名称的对照表
做一些变换,我们现在所需要做的就是将nvs中的国家名称,换成下面name_map中的英文国家名称
这里我们先将这里name_map中国家的中文和英文做一个转移,也就是key变成value,value变成key
new_dict = dict()
for key in name_map.keys():
new_dict[name_map[key]] = key
print(new_dict)
将国家名称都换成英文
def revert_to_english(listN):
english_name = name_map.get(listN[0],'')
return [english_name, listN[1]]
# result = revert_to_english(listN=name_map)
# print(result)
new_list = list(map(revert_to_english,nvs))
print(new_list)
完整代码
代码比较乱,有的没的都写进去了,关键的东西一个不少
import json
import requests
from pyecharts.charts import Map, Geo
from pyecharts import options as opts
import time
url = 'http://api.tianapi.com/ncovabroad/index?key=?'
fr = open("D:\BigDaTa\PYTHON项目\ShuJia01\data\全球疫情数据.txt", mode="r")
# print(fr.name)
# 定义获取数据的类
class Crawl:
def __init__(self, url):
self.url = url
def get_data(self):
r = requests.get(self.url)
content = json.loads(r.text)
print('content', content)
return content
# 获取所有大洲的名称
def continent():
url = 'http://api.tianapi.com/ncovabroad/index?key=?'
s = Crawl(url)
content = s.get_data()
list1 = []
for i in range(101):
list1.append(content['newslist'][i]['continents'])
return list1
# 获取所有国家名称
def provinceName():
url = 'http://api.tianapi.com/ncovabroad/index?key=?'
s = Crawl(url)
content = s.get_data()
list1 = []
for i in range(101):
list1.append(content['newslist'][i]['provinceName'])
return list1
# 获取currentConfirmedCount--当前感染人数
def currentConfirmedCount():
url = 'http://api.tianapi.com/ncovabroad/index?key=?'
s = Crawl(url)
content = s.get_data()
list1 = []
for i in range(101):
list1.append(content['newslist'][i]['currentConfirmedCount'])
return list1
# continent = continent()
# time.sleep(3)
# provinceName = provinceName()
# time.sleep(3)
# currentConfirmedCount = currentConfirmedCount()
# time.sleep(3)
# print(currentConfirmedCount)
# print(continent)
# print(provinceName)
# print(currentConfirmedCount)
# nvs = list(zip(provinceName,currentConfirmedCount))
# print(nvs)
nvs = [["美国", 8494342], ["法国", 6822253], ["英国", 2220045], ["荷兰", 2096912], ["比利时", 1283074], ["瑞典", 1146032],
["塞尔维亚", 1098019], ["土耳其", 1058457], ["哈萨克斯坦", 871580], ["俄罗斯", 869660], ["巴西", 640971], ["伊朗", 607110],
["瑞士", 536915], ["印度", 521913], ["乌克兰", 455189], ["爱尔兰", 400931], ["墨西哥", 364685], ["希腊", 340698],
["斯洛文尼亚", 313570], ["洪都拉斯", 248572], ["波兰", 215485], ["德国", 198192], ["罗马尼亚", 197053], ["斯洛伐克", 192046],
["波多黎各", 180982], ["意大利", 133727], ["澳大利亚", 133004], ["芬兰", 123397], ["伊拉克", 113910], ["哥斯达黎加", 112854],
["挪威", 111564], ["保加利亚", 107909], ["古巴", 97641], ["格鲁吉亚", 94444], ["泰国", 89701], ["利比亚", 88302],
["西班牙", 80508], ["奥地利", 78351], ["越南", 75995], ["马来西亚", 73223], ["巴勒斯坦", 69030], ["阿尔及利亚", 65051],
["斯里兰卡", 64920], ["危地马拉", 57867], ["留尼旺", 54066], ["瓜德罗普岛", 53473], ["捷克", 50698], ["阿塞拜疆", 50149],
["亚美尼亚", 50116], ["菲律宾", 49412], ["加拿大", 48513], ["克罗地亚", 46900], ["波黑", 45734], ["法属圭亚那", 43923],
["马提尼克", 42230], ["斯威士兰", 42209], ["阿根廷", 39649], ["委内瑞拉", 39098], ["厄瓜多尔", 38823], ["哥伦比亚", 38677],
["立陶宛", 37308], ["约旦", 37263], ["黎巴嫩", 36459], ["埃及", 32413], ["塞浦路斯", 32220], ["拉脱维亚", 31666],
["玻利维亚", 31014], ["葡萄牙", 30052], ["乌干达", 30032], ["新加坡", 29937], ["阿曼", 29780], ["牙买加", 29659],
["老挝", 27508], ["匈牙利", 25775], ["刚果(金)", 25504], ["智利", 25456], ["坦桑尼亚", 25223], ["丹麦", 24571],
["巴基斯坦", 24196], ["阿富汗", 24047], ["韩国", 23975], ["孟加拉国", 23522], ["法属波利尼西亚", 23411], ["爱沙尼亚", 23398],
["多米尼加", 22858], ["白俄罗斯", 21610], ["苏里南", 20361], ["马约特", 20315], ["埃塞俄比亚", 20133], ["布隆迪共和国", 19912],
["南非", 18916], ["缅甸", 18846], ["喀麦隆", 18256], ["摩洛哥", 16528], ["叙利亚", 15683], ["毛里求斯", 15402],
["萨尔瓦多", 14646], ["摩尔多瓦", 14295], ["印度尼西亚", 14130], ["莱索托", 14101], ["乌兹别克斯坦", 14049]]
name_map = {'新加坡': 'Singapore Rep.', '多米尼加': 'Dominican Rep.', '巴勒斯坦': 'Palestine', '巴哈马': 'The Bahamas',
'东帝汶': 'East Timor', '阿富汗': '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', '波斯尼亚和黑塞哥维那': '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', '赤道几内亚': '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',
'特里尼达和多巴哥': 'Trinidad and Tobago', '突尼斯': 'Tunisia', '土耳其': 'Turkey', '坦桑尼亚': 'Tanzania',
'乌干达': 'Uganda', '乌克兰': 'Ukraine', '乌拉圭': 'Uruguay', '美国': 'United States', '乌兹别克斯坦': 'Uzbekistan',
'委内瑞拉': 'Venezuela', '越南': 'Vietnam', '瓦努阿图': 'Vanuatu', '西岸': 'West Bank', '也门': 'Yemen',
'南非': 'South Africa', '赞比亚': 'Zambia', '津巴布韦': 'Zimbabwe', '科摩罗': 'Comoros'}
def revert_to_english(listN):
english_name = name_map.get(listN[0],'')
return [english_name, listN[1]]
# result = revert_to_english(listN=name_map)
# print(result)
new_list = list(map(revert_to_english,nvs))
print(new_list)
# 绘制世界地图
def draw():
new_list = list(map(revert_to_english, nvs))
map1 = (
Map()
.add("感染人数", new_list, maptype="world")
.set_global_opts(
visualmap_opts=opts.VisualMapOpts(max_=1000)
)
)
map1.render("mycharts.html")
# draw()
最后制作完成,可以自己设置出现图片的路径
由于这里是海外的数据,所以没有中国的数据,当然中国的防疫工作本身也做得非常好,加上中国的话,可能显示的也是白色。
这里尤其感恩志凯的帮助,虽然这条感恩语句他可能看不到。
感谢阅读,我是啊帅和和,一位大数据专业大四学生,祝你快乐。