最近小笨聪在 B 站看到一个展现各国 GDP 排名变化的超燃视频,当看到中国赶超至世界第一时,那种自豪感油然而生!掘金不能上传视频,你们能够看原文。css
在感叹的同时,小笨聪也很好奇这类可视化图表是怎么制做的?便找到了做者 Jannchie见齐的 B 站主页:space.bilibili.com/1850091/cha…html
点进去发现还有大量此类有趣酷炫的视频。
git
嗯,俺也想学!
github
那他是怎么实现的呢?原来他用到了一个动态图形显示数据的 JavaScript 库:D3.js。那么,若是不会 D3.js 是否是就作不出来了呢?固然不是,Jannchie很是 nice 地给出了一个手把手简单教程:
见齐 手把手教程编程
最主要的,他还开放了程序源码,只须要作2步就可以实现:浏览器
exampe.csv
文件,放进你想要展现的数据,再用浏览器打开bargraph.html
网页,就能够实现动态效果。只不过要注意使用的数据格式要求。下面是小笨聪的实例运用。首先爬取大学排行榜的数据并作处理,而后利用源码将数据可视化。bash
(1)数据来源微信
世界上最权威的大学排名有4类,分别是:app
这里,咱们选取相对比较权威也比较符合国情的第一个 ARWU 的排名结果。打开官网,能够看到有从2003年到2018的英文版和中文版排名,这里选取中文版。函数
肯定好数据来源,而后就能够把数据爬取下来啦。
(2)分析URL获取内容
网页的URL 仍是很简单的,随着年份变化而变化,咱们抓取十年的数据,只需在 main 里构造一下 for 循环,url 格式如代码里所示。另外,须要注意,不一样年份网页采用的编码不一样,返回 response.test 会乱码,返回response.content 则不会。
1 def get_one_page(year):
2 try:
3 headers = {
4 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36'
5 }
6 # 英文版
7 # url = 'http://www.shanghairanking.com/ARWU%s.html' % (str(year))
8 # 中文版
9 url = 'http://www.zuihaodaxue.com/ARWU%s.html' % (str(year))
10 response = requests.get(url,headers = headers)
11 # 2009-2015用'gbk',2016-2018用'utf-8'
12 if response.status_code == 200:
13 return response.content
14 return None
15 except RequestException:
16 print('爬取失败')
复制代码
(3)解析表格
使用read_html 函数抓取表格,并对表格进行必要处理。
1 def parse_one_page(html,i):
2 tb = pd.read_html(html)[0]
3 # 重命名表格列,不须要的列用数字表示
4 tb.columns = ['world rank','university', 2,3, 'score',4]
5 tb.drop([2,3],axis = 1,inplace = True)
6
7 # rank列100名后是区间,需惟一化,增长一列index做为排名
8 tb['index_rank'] = tb.index
9 tb['index_rank'] = tb['index_rank'].astype(int) + 1
10 # 增长一列年份列
11 tb['year'] = i
12 # read_html没有爬取country,需定义函数单独爬取
13 tb['country'] = get_country(html)
14 print(tb) # 测试表格ok
15 return tb
16 print(tb.info()) # 查看表信息
复制代码
此时的表格数据并不完整,由于没有将国家抓取下来。国家在网页里使用图片表示的,由于咱们能够定位到国家代码位置。
能够看到美国是用英文的USA表示的,那么咱们能够单独提取出src属性,而后用正则提取出国家名称就能够了。
1 def get_country(html):
2 soup = BeautifulSoup(html,'lxml')
3 countries = soup.select('td > a > img')
4 lst = []
5 for i in countries:
6 src = i['src']
7 pattern = re.compile('flag.*\/(.*?).png')
8 country = re.findall(pattern,src)[0]
9 lst.append(country)
10 return lst复制代码
world rank university score ... index_rank year country
0 1 哈佛大学 100.0 ... 1 2018 USA
1 2 斯坦福大学 75.6 ... 2 2018 USA
2 3 剑桥大学 71.8 ... 3 2018 UK
3 4 麻省理工学院 69.9 ... 4 2018 USA
4 5 加州大学-伯克利 68.3 ... 5 2018 USA
5 6 普林斯顿大学 61.0 ... 6 2018 USA
6 7 牛津大学 60.0 ... 7 2018 UK
7 8 哥伦比亚大学 58.2 ... 8 2018 USA
8 9 加州理工学院 57.4 ... 9 2018 USA
9 10 芝加哥大学 55.5 ... 10 2018 USA
10 11 加州大学-洛杉矶 51.2 ... 11 2018 USA
11 12 康奈尔大学 50.7 ... 12 2018 USA
12 12 耶鲁大学 50.7 ... 13 2018 USA
13 14 华盛顿大学-西雅图 50.0 ... 14 2018 USA
14 15 加州大学-圣地亚哥 47.8 ... 15 2018 USA
15 16 宾夕法尼亚大学 46.4 ... 16 2018 USA
16 17 伦敦大学学院 46.1 ... 17 2018 UK
17 18 约翰霍普金斯大学 45.4 ... 18 2018 USA
18 19 苏黎世联邦理工学院 43.9 ... 19 2018 Switzerland
19 20 华盛顿大学-圣路易斯 42.1 ... 20 2018 USA
20 21 加州大学-旧金山 41.9 ... 21 2018 USA
21 22 东京大学 41.5 ... 22 2018 Japan
22 23 多伦多大学 40.9 ... 23 2018 Canada
23 24 伦敦帝国学院 40.1 ... 24 2018 UK
24 25 西北大学(埃文斯顿) 39.9 ... 25 2018 USA
25 26 杜克大学 39.7 ... 26 2018 USA
26 27 密歇根大学-安娜堡 39.4 ... 27 2018 USA
27 28 威斯康星大学-麦迪逊 38.9 ... 28 2018 USA
28 29 哥本哈根大学 38.7 ... 29 2018 Denmark
29 30 洛克菲勒大学 37.9 ... 30 2018 USA复制代码
(4)数据处理
将前面生成的 university.csv 文件进一步处理。另外,此次的代码不只能够得到内地大学排名,还能够列出含港澳台的排名和美国大学的排名。小笨聪也定义了一个 topn 函数,可以按年份分别求出各年的前20名大学名单。
1def analysis():
2 df = pd.read_csv('university.csv')
3 # 内地
4 df = df.query("(country == 'China')")[['university','year','index_rank']]
5
6 df['index_rank_score'] = df['index_rank']
7 # 将index_rank列转为整形
8 df['index_rank'] = df['index_rank'].astype(int)
9 # 含港澳台
10 # df = df.query("(country == 'China')|(country == 'China-hk')|(country == 'China-tw')|
# (country == 'China-HongKong')|(country == 'China-Taiwan')|(country == 'Taiwan,China')|(country == 'HongKong,China')")[['university','year','index_rank']]
11 # 美国
12 # df = df.query("(country == 'UnitedStates')|(country == 'USA')")[['university','year','index_rank']]
13 #求topn名
14 def topn(df):
15 top = df.sort_values(['year','index_rank'],ascending = True)
16 return top[:20].reset_index()
17 df = df.groupby(by =['year']).apply(topn)
18 # 更改列顺序
19 df = df[['university','index_rank_score','index_rank','year']]
20 # 重命名列
21 df.rename (columns = {'university':'name','index_rank_score':'type','index_rank':'value','year':'date'},inplace = True)
22 # 输出结果
23 df.to_csv('university_ranking.csv',mode ='w',encoding='utf_8_sig', header=True, index=False)
复制代码
获取的表格数据效果以下:
首先到 见奇 的 Github 主页下载源码,而后将 bargraph.html 拖拽到浏览器,点击 选择文件,将刚才下载好的 university_ranking.csv 文件选中,便可看到动态数据图表。
不过仍是有一些须要完善,好比字体大小、柱形颜色、数据项位置、图表反转等等,这些参数在源码的文件里都可以修改。固然,比较方便的办法是能够先在该网页的 css 样式表里改,改好后再到源码里修改。
源码有四个方便修改参数的文件:
固然,若是你比较懒,我已经帮你修改好啦(其实也并非很容易修改...)。
以上就是本次爬取大学排行榜数据并制做动态图标的分析过程。
微信公众号“学编程的金融客”后台回复“大学排行榜”便可获取源码。