在当今数字化时代,数据采集已成为获取有价值信息的关键手段之一。本篇文章将带你深入了解如何利用Python进行优志愿大学数据的采集,帮助你快速掌握爬虫技术,同时为你在教育领域的数据分析或相关业务拓展提供有力支持。
更新时间:2025-6-29 可用
一、项目背景
随着高考的临近,考生和家长对大学的选择越来越重视。优志愿作为一个提供高考志愿填报辅助的平台,拥有丰富的大学数据,包括学校名称、难易度指数、热度等重要信息。这些数据对于考生选择合适的大学具有重要参考价值。然而,这些数据分散在网页中,手动收集耗时费力。因此,开发一个自动化的数据采集工具,能够高效地获取这些数据,对于需要这些数据进行研究、分析或商业应用的人来说具有重要意义。
二、项目意义
-
为考生和家长提供便利:通过采集和整理这些数据,可以为考生和家长提供一个更全面、更直观的大学信息汇总,帮助他们更快地了解不同大学的特点,从而做出更明智的选择。
-
助力教育研究:这些数据可以为教育研究者提供丰富的素材,用于分析不同地区、不同类别大学的发展趋势、录取难度变化等,为教育政策的制定和优化提供参考依据。
-
商业应用价值:对于教育培训机构、高考志愿填报咨询公司等商业机构来说,这些数据可以作为他们业务拓展的重要资源,帮助他们更好地了解市场需求,制定更精准的营销策略。
三、环境准备
请确保你已安装以下 Python 库:
pip install requests execjs
四、采集字段说明
以下是本项目采集的字段,采集结果会以 CSV 格式保存。
字段名 | |
---|---|
学校名称 | 大学的全称,是识别大学的关键信息。 |
难易度指数 | 表示该大学的录取难度,数值越高表示录取难度越大。 |
热度 | 表示该大学的受欢迎程度,数值越高表示越受考生和家长关注。 |
所属 | 表示该大学的所属单位,如教育部、地方等。 |
学校类别 | 表示大学的类型,如综合、理工、师范等。 |
学校特征 | 表示大学的特色,如211、985、双一流等。 |
省份 | 大学所在的省份。 |
城市 | 大学所在的城市。 |
详情页 | 该大学在优志愿平台上的详细信息页面链接,方便进一步查看详细信息。 |
五、爬虫思路解析
(一)网页结构分析
官网地址 :优志愿大学信息
数据返回为下滑异步加载,其中请求体有个sign加密参数 挺简单的直接扣;然后请求体主要的就是翻页参数pageIndex 可以采用递归 如果页数小于最大页数就+1
(二)反爬机制突破
该网站采用了签名验证机制,关键点在于u-sign
参数的生成。先进行js逆向,通过python调用js解密函数进行解密
def get_sign(data):
result = execjs.compile(js_code).call('get_usign',data)
return result
(三)基本思路
-
分析目标网站:首先,我们需要对优志愿网站的大学数据页面进行分析,了解数据的加载方式、请求参数、响应格式等。通过浏览器的开发者工具,我们可以发现大学数据是通过发送POST请求到特定的API接口获取的,并且请求需要携带一些参数和签名。
-
获取签名:由于网站对请求进行了加密签名验证,我们需要使用
execjs
库来执行网站提供的JavaScript代码,生成合法的签名。这样,我们的请求才能被服务器接受。 -
发送请求:使用
requests
库发送POST请求,将采集到的数据以JSON格式发送到API接口,并在请求头中添加必要的参数和签名。 -
解析响应:服务器返回的数据是JSON格式的,我们可以通过
json
库将其解析为Python字典,然后提取我们需要的字段。 -
保存数据:将提取到的数据保存为CSV格式,方便后续查看和分析。我们使用
csv
库来实现数据的保存。 -
分页采集:大学数据是分页显示的,我们需要通过循环逐页采集数据,直到采集完所有页面。在采集过程中,为了避免对服务器造成过大压力,我们使用
time.sleep
函数控制请求间隔,并使用random.uniform
函数生成随机的间隔时间。
六、结果展示
七、完整代码
(一)数据采集(爬虫)部分
如果你对这个项目感兴趣,想要获取完整可运行的源代码,欢迎在评论区留言或私信(主页 \/)zzxcrq1234 伪善。
(二)可视化
1.中国大学数量区域分布
from pyecharts.charts import Map
from pyecharts import options as opts
df_province = df['省份'].value_counts().reset_index()
df_province.columns = ['省份','数量']
data_pair = [(row['省份'], row['数量']) for index, row in df_province.iterrows()]
map_chart = (
Map()
.add("", data_pair, maptype="china", is_map_symbol_show=False) # 不显示标记点
.set_series_opts(label_opts=opts.LabelOpts(font_size=7)) # 调节省份字体大小
.set_global_opts(
title_opts=opts.TitleOpts(title="中国大学数量区域分布图"),
visualmap_opts=opts.VisualMapOpts(
is_piecewise=True, # 分段映射
pieces=[
{"max": 50, "label": "50以下", "color": "#E0FFFF"},
{"min": 50, "max": 100, "label": "50-100", "color": "#ADFF2F"},
{"min": 100, "max": 150, "label": "100-150", "color": "#32CD32"},
{"min": 150, "label": "150以上", "color": "#006400"}
]
)
)
)
map_chart.render('./可视化结果/中国大学数量区域分布图.html')
map_chart.render_notebook()
2.大学类别数量柱状图
dic = {}
for i in df['学校类别']:
if len(eval(i)) == 0:
continue
for j in eval(i):
if j.strip() == '其它':
j='其他'
if j not in dic:
dic[j] = 0
else:
dic[j] += 1
df_category = pd.DataFrame(list(dic.items()), columns=['类别', '数量'])
df_category = df_category.sort_values('数量',ascending=False)
# df_category['类别'] = df_category['类别'].map({'其它':'其他'}).fillna(df_category['类别'])
plt.figure(figsize=(12, 8))
barplot = sns.barplot(data=df_category,x='类别',y='数量',palette='viridis')
for bar in barplot.patches:
yval = bar.get_height()
barplot.text(bar.get_x() + bar.get_width() / 2, yval, int(yval), ha='center', va='bottom', fontsize=10)
plt.title('大学类别数量柱状图',fontsize=15)
plt.xlabel('')
plt.ylabel('')
plt.savefig('./可视化结果/大学类别数量柱状图.jpg')
plt.show()
3.985、211和双一流大学数量排行榜top7
features_dic = {}
for i in range(len(df)):
province = df.iloc[i]['省份']
features = eval(df.iloc[i]['学校特征'])
for j in features:
if j in '985':
features_dic[province] = features_dic.get(province,0) + 1
break
elif j == '211':
features_dic[province] = features_dic.get(province,0) + 1
break
elif j == '双一流':
features_dic[province] = features_dic.get(province,0) + 1
break
df_good = pd.DataFrame(list(features_dic.items()), columns=['省份', '数量']).sort_values('数量',ascending=False)
plt.figure(figsize=(12, 8))
sns.barplot(data=df_good[:7],x='数量',y='省份',palette='viridis')
plt.title('985、211和双一流大学排行榜top7',fontsize=15)
plt.xlabel('')
plt.ylabel('')
plt.savefig('./可视化结果/985_211和双一流大学排行榜top7.jpg')
plt.show()
4.大学难易度指数分布直方图
import numpy as np
plt.figure(figsize=(8,8))
sns.distplot(df['难易度指数'], bins=np.arange(1, 100, 1), kde=False,color='g')
plt.title('大学难易度指数分布直方图',fontsize=15)
plt.xlabel('')
plt.ylabel('')
plt.savefig('./可视化结果/大学难易度指数分布直方图.jpg')
plt.show()