天天看點

20秒縱覽中國大學學術排行榜變化

最近小笨聰在 B 站看到一個展示各國 GDP 排名變化的超燃視訊,當看到中國趕超至世界第一時,那種自豪感油然而生!

微信公衆号原文連結  (CSDN不能上傳視訊)

在感歎的同時,小笨聰也很好奇這類可視化圖表是怎麼制作的?便找到了作者 Jannchie見齊的 B 站首頁:

哔哩哔哩 ( ゜- ゜)つロ 乾杯~ Bilibili​space.bilibili.com

點進去發現還有大量此類有趣酷炫的視訊。

20秒縱覽中國大學學術排行榜變化

嗯,俺也想學!

那他是怎麼實作的呢?原來他用到了一個動态圖形顯示資料的 JavaScript 庫:D3.js。那麼,如果不會 D3.js 是不是就做不出來了呢?當然不是,Jannchie非常 nice 地給出了一個手把手簡單教程:

見齊 手把手教程

最主要的,他還開放了程式源碼,隻需要做2步就能夠實作:

  • 到他的Github首頁下載下傳源碼到本地電腦:https://github.com/Jannchie/Historical-ranking-data-visualization-based-on-d3.js
20秒縱覽中國大學學術排行榜變化
  • 打開檔案夾裡面的

    exampe.csv

    檔案,放進你想要展示的資料,再用浏覽器打開

    bargraph.html

    網頁,就可以實作動态效果。隻不過要注意使用的資料格式要求。

下面是小笨聰的執行個體運用。首先爬取大學排行榜的資料并做處理,然後利用源碼将資料可視化。

先提前感受一下效果

20秒縱覽中國大學學術排行榜變化

1.大學排行榜資料爬取

(1)資料來源

世界上最權威的大學排名有4類,分别是:

  • 原上海交通大學的ARWU(軟科)

    http://www.shanghairanking.com/ARWU2018.html

  • 英國教育組織的QS

    https://www.topuniversities.com/university-rankings/world-university-rankings/2018

  • 泰晤士的THE

    https://www.timeshighereducation.com/world-university-rankings

  • 美國的usnews

    https://www.usnews.com/best-colleges/rankings

這裡,我們選取相對比較權威也比較符合國情的第一個 ARWU 的排名結果。打開官網,可以看到有從2003年到2018的英文版和中文版排名,這裡選取中文版。

20秒縱覽中國大學學術排行榜變化

确定好資料來源,然後就可以把資料爬取下來啦。

(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()) # 檢視表資訊
           

此時的表格資料并不完整,因為沒有将國家抓取下來。國家在網頁裡使用圖檔表示的,因為我們可以定位到國家代碼位置。

20秒縱覽中國大學學術排行榜變化

取下來。國家在網頁裡使用圖檔表示的,因為我們可以定位到國家代碼位置。

20秒縱覽中國大學學術排行榜變化

可以看到美國是用英文的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)
           

擷取的表格資料效果如下:

20秒縱覽中國大學學術排行榜變化

2.資料可視化

首先到 見奇 的 Github 首頁下載下傳源碼,然後将 bargraph.html 拖拽到浏覽器,點選 選擇檔案,将剛才下載下傳好的 university_ranking.csv 檔案選中,即可看到動态資料圖表。

不過還是有一些需要完善,比如字型大小、柱形顔色、資料項位置、圖表反轉等等,這些參數在源碼的檔案裡均可以修改。當然,比較友善的辦法是可以先在該網頁的 css 樣式表裡改,改好後再到源碼裡修改。

20秒縱覽中國大學學術排行榜變化

源碼有四個友善修改參數的檔案:

  • config.js : 配置各功能的開關,比如配色、字型、是否反轉圖表等等;
  • color_ranges.js : 修改柱形圖的顔色;
  • stylesheet.css : 具體修改配色、字型、文字名稱等的 css 樣式;
  • visual.js :更進一步修改,比如圖表透明度。

當然,如果你比較懶,我已經幫你修改好啦(其實也并不是很容易修改...)。

以上就是本次爬取大學排行榜資料并制作動态圖示的分析過程。

微信公衆号“學程式設計的金融客”背景回複“大學排行榜”即可擷取源碼。

自制音樂播放器

2.北上廣深租房圖鑒

你的點贊和關注就是對我最大的支援!

20秒縱覽中國大學學術排行榜變化
儲存掃碼關注公衆号呗