一、選題背景
高考作為中國學生生涯中最為重要的事,在高考之后,選擇一所好的大學則是接下的人生的一塊的敲門磚,選擇有着好的大學,和有着良好教育氛圍的城市以及所選擇的大學近年來的變化是很重要的事,在以前,想要了解這些需要翻閱查找大量的資料,而現在我們可以通過python輕易地了解這些。
二、爬蟲方案設計
1.方案名稱:
中國大學年排名變化數據與可視化分析
2.爬取的內容與數據特征分析:
通過網站收錄的中國大學截止到2019年的排名(因為2020到2021年的疫情對排名變化)
3. 方案概述
分析網站頁面結構,找到爬取數據的位置,根據不同的數據制定不同的爬取方法
三、網站頁面結構分析
1.網頁頁面的結構與特性分析
通過瀏覽器“審查元素”查看源代碼及“網絡”反饋
可以看到每一個 tr
里面都有一行數據,這就是所需要的數據,通過 contents
獲取標簽對里面的數據。
四、爬蟲程序設計
1. 數據的爬取
1 import requests 2 from lxml import html 3 def Tree(url): 4 req = requests.get(url) 5 req.encoding ='utf-8-sig' 6 allUniv = [] 7 tree = html.fromstring(req.text) 8 trs = tree.xpath('//tbody/tr') 9 for tr in trs: 10 tds = tr.xpath('td') 11 if tds == 0: 12 continue 13 oneUniv=[] 14 oneUniv.append(tds[0].text) 15 name = tds[1].xpath('div') 16 oneUniv.append(name[0].text) 17 for td in tds[2:]: 18 oneUniv.append(td.text) 19 allUniv.append(oneUniv) 20 return allUniv 21 22 url='http://www.zuihaodaxue.cn/zuihaodaxuepaiming2019.html' 23 tree=Tree(url) 24 print("排名 學校名稱 省市 總分") 25 for i in range(20): 26 print(tree[i][0],tree[i][1],tree[i][2],tree[i][3],sep=' ') 27 28 from bs4 import BeautifulSoup 29 def Req(url): 30 req=requests.get(url) 31 req.encoding='utf-8-sig' 32 allUniv=[] 33 soup=BeautifulSoup(req.text,"html.parser") 34 trs=soup.find_all('tr') 35 for tr in trs: 36 tds=tr.find_all('td') 37 if len(tds)==0: 38 continue 39 oneUniv=[] 40 for td in tds: 41 oneUniv.append(td.string) 42 allUniv.append(oneUniv) 43 return allUniv 44 45 allUniv1=Req(url) 46 print("排名 學校名稱 省市 總分") 47 for i in range(20): 48 print(allUniv1[i][0],allUniv1[i][1],allUniv1[i][2],allUniv1[i][3],sep=' ') 49 50 import matplotlib.pyplot as plt 51 plt.rcParams["font.sans-serif"]=["SimHei"] 52 name=[] 53 sorce=[] 54 for i in range(10): 55 name.append(allUniv1[i][1]) 56 sorce.append(float(allUniv1[i][3])) 57 plt.barh(range(len(sorce)),sorce,tick_label=name) 58 plt.title("2019年排名前十位的大學及其總分") 59 plt.xlabel('分數') 60 plt.show() 61 62 from collections import Counter 63 province=[] 64 for i in range(len(allUniv1)): 65 province.append(allUniv1[i][2]) 66 result=Counter(province) 67 print(result)
2.數據簡單分析且可視化
(1)繪制餅狀圖
1 import matplotlib as mpl 2 mpl.rcParams["font.sans-serif"]=["SimHei"] 3 mpl.rcParams["axes.unicode_minus"]=False 4 plt.pie(result.values(),labels=result.keys(),radius=2) 5 plt.title("各省份大學數量占比餅狀圖") 6 plt.show()
(2)繪制柱狀圖
1 def dataanly1(): 2 df_score = df.sort_values('score',ascending=False) # asc Flase降序 True升序 ; desc 3 4 name1 = df_score.schoolname[:10] # x軸坐標 5 score1 = df_score.score[:10] # y軸坐標 6 7 plt.bar(range(10),score1,tick_label=name1) # 繪制條形圖,用range()能保持x軸順序一致 8 plt.ylim(10,100) 9 plt.title("大學評分最高Top10",color=colors1) 10 plt.xlabel("大學名稱") 11 plt.ylabel("評分") 12 13 # 標記數值 14 for x,y in enumerate(list(score1)): 15 plt.text(x,y+0.5,'%s' %round(y,1),ha='center',color=colors1) 16 pass 17 18 pl.xticks(rotation=270) # 旋轉270° 19 plt.tight_layout() # 去除空白 20 21 plt.show() 22 def DXAnly2(): 23 area_count = df.groupby(by='area').area.count().sort_values(ascending=False) 24 # 繪圖方法1 25 area_count.plot.bar(color='#4652B1') # 設置為藍紫色 26 pl.xticks(rotation=0) # x軸名稱太長重疊,旋轉為縱向 27 for x, y in enumerate(list(area_count.values)): 28 plt.text(x, y + 0.5, '%s' % round(y, 1), ha='center', color=colors1) 29 plt.title('各地區大學數量排名') 30 plt.xlabel('地區') 31 plt.ylabel('數量(所)') 32 plt.show()
1 def dataanly1(): 2 3 df_score = df.sort_values('score',ascending=False) # asc Flase降序 True升序 ; desc 4 5 name1 = df_score.schoolname[:10] # x軸坐標 6 7 score1 = df_score.score[:10] # y軸坐標 8 9 plt.bar(range(10),score1,tick_label=name1) # 繪制條形圖,用range()能保持x軸順序一致 10 plt.ylim(10,100) 11 12 plt.title("大學評分最高Top10",color=colors1) 13 14 plt.xlabel("大學名稱") 15 16 plt.ylabel("評分") 17 18 # 標記數值 19 for x,y in enumerate(list(score1)): 20 plt.text(x,y+0.5,'%s' %round(y,1),ha='center',color=colors1) 21 pass 22 23 pl.xticks(rotation=270) # 旋轉270° 24 25 plt.tight_layout() # 去除空白 26 27 plt.show()
通過所繪制柱狀圖與餅狀圖,我們可以清晰地看出優秀大學在各個省份占比,在選擇大學的時候,可以優先選擇教育資源更加多源,高等教育水平更高的省份城市,
其中前三名的地區是北京、江蘇、上海,經濟水平較為發達的地區,可以簡單的看見高素質教育水平可以影響地區經濟的發展。
(4)繪制折線圖
1 from pyecharts.charts import Line 2 from pyecharts import options as opts 3 4 line = ( 5 Line() 6 .add_xaxis(top10_sum.index.tolist()) 7 .add_yaxis("總分", top10_sum["總分"].astype('int').tolist()) 8 .set_global_opts(title_opts=opts.TitleOpts(title="中國最好大學TOP10(各省份)" ,subtitle="總分")) 9 ) 10 line.render_notebook()
(5)繪制詞雲
1 from PIL import Image 2 from os import path 3 from wordcloud import WordCloud 4 wordcloud=WordCloud( 5 background_color = '#f3f3f3', 6 font_path = 'C:\Windows\Fonts\msyh.ttc', 7 margin=3, 8 max_font_size=60, 9 random_state=50, 10 scale=10, 11 colormap='viridis', 12 13 ) 14 wordcloud.generate_from_frequencies(result) 15 plt.imshow(wordcloud,interpolation = 'bilinear') 16 plt.axis('off') 17 plt.show()
(6)各省市大學數量平均分縱向柱狀圖
1 df1.sort_values(by=['平均分'], ascending=False, inplace=True) 2 d1 = df1.index.tolist() 3 d2 = df1['數量'].values.tolist() 4 d3 = df1['平均分'].values.tolist() 5 6 bar0 = ( 7 Bar() 8 .add_xaxis(d1) 9 .add_yaxis('數量', d2) 10 .add_yaxis('平均分數', d3) 11 .set_global_opts( 12 title_opts=opts.TitleOpts(title='中國大學排名'), 13 yaxis_opts=opts.AxisOpts(name='量'), 14 xaxis_opts=opts.AxisOpts(name='省份'), 15 ) 16 )
(7)各省市大學數量平均分橫向柱狀圖
1 df1.sort_values(by=['平均分'], inplace=True) 2 3 d1 = df1.index.tolist() 4 d2 = df1['數量'].values.tolist() 5 d3 = df1['平均分'].values.tolist() 6 7 bar1 = ( 8 Bar() 9 .add_xaxis(d1) 10 .add_yaxis('數量', d2) 11 .add_yaxis('平均分數', d3) 12 .reversal_axis() 13 .set_series_opts(label_opts=opts.LabelOpts(position='right')) 14 .set_global_opts( 15 title_opts=opts.TitleOpts(title='中國大學排名'), 16 yaxis_opts=opts.AxisOpts(name='省份'), 17 xaxis_opts=opts.AxisOpts(name='量'), 18 ) 19 )
(8)繪制玫瑰圖
1 name = df_counts.index.tolist() 2 3 count = df_counts.values.tolist() 4 5 c0 = ( 6 Pie() 7 .add( 8 '', 9 [list(z) for z in zip(name, count)], 10 radius=['20%', '60%'], 11 center=['50%', '65%'], 12 rosetype="radius", 13 label_opts=opts.LabelOpts(is_show=False), 14 ) 15 .set_series_opts(label_opts=opts.LabelOpts(formatter='{b}: {c}')) 16 )
(9)大學地圖分布
1 name = df0.index.tolist() 2 3 count = df0.values.tolist() 4 5 m = ( 6 Map() 7 .add('', [list(z) for z in zip(name, count)], 'china') 8 .set_global_opts( 9 title_opts=opts.TitleOpts(title='中國大學排名'), 10 visualmap_opts=opts.VisualMapOpts(max_=40, split_number=8, is_piecewise=True), 11 ) 12 )
(10)選定繪制折線圖
選擇一所大學,查看這所大學今年來的排名變化,這里選擇北京郵電大學
1 sorce2=[] 2 for i in range(4): 3 url='http://www.zuihaodaxue.cn/zuihaodaxuepaiming'+str(i+2016)+'.html' 4 allUniv=Req(url) 5 for i in range(len(allUniv)): 6 if allUniv[i][1]=="北京郵電大學": 7 j=i 8 break 9 sorce2.append(float(allUniv[j][3])) 10 print(sorce2) 11 12 years=[2016,2017,2018,2019] 13 plt.subplot(1,1,1) 14 plt.plot(years,sorce2,marker='o') 15 plt.grid(True) 16 plt.title("北京郵電大學2016-2019年評分走勢") 17 plt.xlabel('年') 18 plt.ylabel('分數') 19 plt.show()
五、代碼匯總
1 import requests 2 from lxml import html 3 4 def Tree(url): 5 req = requests.get(url) 6 req.encoding ='utf-8-sig' 7 allUniv = [] 8 9 tree = html.fromstring(req.text) 10 trs = tree.xpath('//tbody/tr') 11 12 for tr in trs: 13 tds = tr.xpath('td') 14 if tds == 0: 15 continue 16 oneUniv=[] 17 oneUniv.append(tds[0].text) 18 name = tds[1].xpath('div') 19 oneUniv.append(name[0].text) 20 21 for td in tds[2:]: 22 oneUniv.append(td.text) 23 allUniv.append(oneUniv) 24 return allUniv 25 26 27 url='http://www.zuihaodaxue.cn/zuihaodaxuepaiming2019.html' 28 tree=Tree(url) 29 print("排名 學校名稱 省市 總分") 30 for i in range(20): 31 print(tree[i][0],tree[i][1],tree[i][2],tree[i][3],sep=' ') 32 33 from bs4 import BeautifulSoup 34 35 def Req(url): 36 req=requests.get(url) 37 req.encoding='utf-8-sig' 38 allUniv=[] 39 soup=BeautifulSoup(req.text,"html.parser") 40 trs=soup.find_all('tr') 41 42 for tr in trs: 43 tds=tr.find_all('td') 44 if len(tds)==0: 45 continue 46 47 oneUniv=[] 48 for td in tds: 49 oneUniv.append(td.string) 50 allUniv.append(oneUniv) 51 52 return allUniv 53 allUniv1=Req(url) 54 print("排名 學校名稱 省市 總分") 55 for i in range(20): 56 print(allUniv1[i][0],allUniv1[i][1],allUniv1[i][2],allUniv1[i][3],sep=' ') 57 58 import csv 59 60 with open('text2019.csv', 'w',newline='') as csvfile: 61 writer = csv.writer(csvfile) 62 writer.writerow(['排名','學校名稱','省市','總分','指標得分','生源質量(新生高考成績得分)','培養結果(畢業生就業率)','社會聲譽(社會捐贈收入·千元)','科研規模(論文數量·篇)','科研質量(論文質量·FWCI)','頂尖成果(高被引論文·篇)','頂尖人才(高被引學者·人)','科技服務(企業科研經費·千元)','成果轉化(技術轉讓收入·千元)']) 63 for row in allUniv1: 64 writer.writerow(row) 65 66 import matplotlib.pyplot as plt 67 68 plt.rcParams["font.sans-serif"]=["SimHei"] 69 name=[] 70 sorce=[] 71 72 for i in range(10): 73 name.append(allUniv1[i][1]) 74 sorce.append(float(allUniv1[i][3])) 75 plt.barh(range(len(sorce)),sorce,tick_label=name) 76 plt.title("2019年排名前十位的大學及其總分") 77 plt.xlabel('分數') 78 plt.show() 79 80 from collections import Counter 81 82 province=[] 83 for i in range(len(allUniv1)): 84 province.append(allUniv1[i][2]) 85 result=Counter(province) 86 print(result) 87 88 import matplotlib as mpl 89 90 mpl.rcParams["font.sans-serif"]=["SimHei"] 91 mpl.rcParams["axes.unicode_minus"]=False 92 plt.pie(result.values(),labels=result.keys(),radius=2) 93 plt.title("各省份大學數量占比餅狀圖") 94 95 from PIL import Image 96 from os import path 97 from wordcloud import WordCloud 98 99 wordcloud=WordCloud( 100 background_color = '#f3f3f3', 101 font_path = 'C:\Windows\Fonts\msyh.ttc', 102 margin=3, 103 max_font_size=60, 104 random_state=50, 105 scale=10, 106 colormap='viridis', 107 108 ) 109 wordcloud.generate_from_frequencies(result) 110 plt.imshow(wordcloud,interpolation = 'bilinear') 111 112 plt.axis('off') 113 plt.show() 114 plt.show() 115 116 def dataanly1(): 117 df_score = df.sort_values('score',ascending=False) # asc Flase降序 True升序 ; desc 118 119 name1 = df_score.schoolname[:10] # x軸坐標 120 score1 = df_score.score[:10] # y軸坐標 121 122 plt.bar(range(10),score1,tick_label=name1) # 繪制條形圖,用range()能保持x軸順序一致 123 plt.ylim(10,100) 124 plt.title("大學評分最高Top10",color=colors1) 125 plt.xlabel("大學名稱") 126 plt.ylabel("評分") 127 128 # 標記數值 129 for x,y in enumerate(list(score1)): 130 plt.text(x,y+0.5,'%s' %round(y,1),ha='center',color=colors1) 131 pass 132 133 pl.xticks(rotation=270) # 旋轉270° 134 plt.tight_layout() # 去除空白 135 136 plt.show() 137 138 def DXAnly2(): 139 area_count = df.groupby(by='area').area.count().sort_values(ascending=False) 140 # 繪圖方法1 141 142 area_count.plot.bar(color='#4652B1') # 設置為藍紫色 143 pl.xticks(rotation=0) # x軸名稱太長重疊,旋轉為縱向 144 for x, y in enumerate(list(area_count.values)): 145 plt.text(x, y + 0.5, '%s' % round(y, 1), ha='center', 146 color=colors1) 147 148 plt.title('各地區大學數量排名') 149 plt.xlabel('地區') 150 plt.ylabel('數量(所)') 151 plt.show() 152 153 from PIL import Image 154 from os import path 155 from wordcloud import WordCloud 156 157 wordcloud=WordCloud( 158 background_color = '#f3f3f3', 159 font_path = 'C:\Windows\Fonts\msyh.ttc', 160 margin=3, 161 max_font_size=60, 162 random_state=50, 163 scale=10, 164 colormap='viridis', 165 166 ) 167 wordcloud.generate_from_frequencies(result) 168 plt.imshow(wordcloud,interpolation = 'bilinear') 169 plt.axis('off') 170 plt.show() 171 172 from pyecharts.charts import Line 173 from pyecharts import options as opts 174 175 line = ( 176 Line() 177 .add_xaxis(top10_sum.index.tolist()) 178 .add_yaxis("總分", top10_sum["總分"].astype('int').tolist()) 179 .set_global_opts(title_opts=opts.TitleOpts(title="中國最好大學TOP10(各省份)" ,subtitle="總分")) 180 ) 181 line.render_notebook() 182 183 df1.sort_values(by=['平均分'], ascending=False, inplace=True) 184 d1 = df1.index.tolist() 185 d2 = df1['數量'].values.tolist() 186 d3 = df1['平均分'].values.tolist() 187 188 bar0 = ( 189 Bar() 190 .add_xaxis(d1) 191 .add_yaxis('數量', d2) 192 .add_yaxis('平均分數', d3) 193 .set_global_opts( 194 title_opts=opts.TitleOpts(title='中國大學排名'), 195 yaxis_opts=opts.AxisOpts(name='量'), 196 xaxis_opts=opts.AxisOpts(name='省份'), 197 ) 198 ) 199 200 df1.sort_values(by=['平均分'], inplace=True) 201 202 d1 = df1.index.tolist() 203 d2 = df1['數量'].values.tolist() 204 d3 = df1['平均分'].values.tolist() 205 206 bar1 = ( 207 Bar() 208 .add_xaxis(d1) 209 .add_yaxis('數量', d2) 210 .add_yaxis('平均分數', d3) 211 .reversal_axis() 212 .set_series_opts(label_opts=opts.LabelOpts(position='right')) 213 .set_global_opts( 214 title_opts=opts.TitleOpts(title='中國大學排名'), 215 yaxis_opts=opts.AxisOpts(name='省份'), 216 xaxis_opts=opts.AxisOpts(name='量'), 217 ) 218 ) 219 220 221 name = df_counts.index.tolist() 222 223 count = df_counts.values.tolist() 224 225 c0 = ( 226 Pie() 227 .add( 228 '', 229 [list(z) for z in zip(name, count)], 230 radius=['20%', '60%'], 231 center=['50%', '65%'], 232 rosetype="radius", 233 label_opts=opts.LabelOpts(is_show=False), 234 ) 235 .set_series_opts(label_opts=opts.LabelOpts(formatter='{b}: {c}')) 236 ) 237 238 239 240 name = df0.index.tolist() 241 242 count = df0.values.tolist() 243 244 m = ( 245 Map() 246 .add('', [list(z) for z in zip(name, count)], 'china') 247 .set_global_opts( 248 title_opts=opts.TitleOpts(title='中國大學排名'), 249 visualmap_opts=opts.VisualMapOpts(max_=40, split_number=8, is_piecewise=True), 250 ) 251 ) 252 253 254 sorce2=[] 255 for i in range(4): 256 url='http://www.zuihaodaxue.cn/zuihaodaxuepaiming'+str(i+2016)+'.html' 257 allUniv=Req(url) 258 for i in range(len(allUniv)): 259 if allUniv[i][1]=="北京郵電大學": 260 j=i 261 break 262 sorce2.append(float(allUniv[j][3])) 263 print(sorce2) 264 265 years=[2016,2017,2018,2019] 266 plt.subplot(1,1,1) 267 plt.plot(years,sorce2,marker='o') 268 plt.grid(True) 269 plt.title("北京郵電大學2016-2019年評分走勢") 270 plt.xlabel('年') 271 plt.ylabel('分數') 272 plt.show()
六、總結
一所好的大學,對人生的影響是非常巨大的,在力所能及的范圍內選擇一所位於教育資源更加多源,高等教育水平更高的省份城市的優秀大學是非常重要的事,作為判斷標准的數據,在以往單單是一所大學的相關資料就需要通過大量、繁瑣的查找與翻閱才能夠得到,若是多所大學的多年的變化則需要更多的時間。而現在通過python的則能夠相對輕松的得到。