最近小笨聰在 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 樣式表裏改,改好後再到源碼裏修改。
源碼有四個方便修改參數的文件:
固然,若是你比較懶,我已經幫你修改好啦(其實也並非很容易修改...)。
以上就是本次爬取大學排行榜數據並製做動態圖標的分析過程。
微信公衆號「學編程的金融客」後臺回覆「大學排行榜」便可獲取源碼。