爬取中国各地区大学排名变化数据与可视化分析
一、选题背景
高考作为中国学生生涯中最为重要的事,在高考之后,选择一所好的大学则是接下的人生的一块的敲门砖,选择有着好的大学,和有着良好教育氛围的城市以及所选择的大学近年来的变化是很重要的事,在以前,想要了解这些需要翻阅查找大量的资料,而现在我们可以通过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的则能够相对轻松的得到。