![[实战]Python爬取全国考研数据与可视化(附源码)](http://pic.xiahunao.cn/yaotu/[实战]Python爬取全国考研数据与可视化(附源码))
很多考研同学都会关注院校招生人数、专业分数线等信息手动整理效率极低。本篇用 Python 完成接 口爬虫 数据存储 可视化分析全流程实战从考研网站抓取院校专业数据再通过图表直观分析数据适合爬虫、数据分析入门学习。一、项目的环境准备pip install requests pandas pyecharts二、整体开发思路整体项目分分为两大模块:数据爬虫和数据可视化。数据爬虫: 通过三层接口请求依次获取院校、专业、分数线最终保存为CSV文件;数据可视化: 读取CSV数据, 清洗数据, 使用pyecharts绘制多类图表并整合展示。第一部分: 数据爬虫(分段拆解)爬虫采用的是三层 POST 接口请求,下面按功能拆分, 逐个讲解。1.1 导入依赖 初始化全局变量先导入需要的库, 并定义列表用于存放最终爬取到的数据。import random import requests import time import pandas # 定义请求网址发送3次请求 # 定义一个空列表。来装每个学校的专业数据 alldata []1.2 配置请求头(模拟浏览器, 防止拦截)网络接口会校验访问的来源, 配置请求头伪装成正常的浏览器访问。# 请求头 headers { user-agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36, referer:https://www.kaoyan.cn/ }1.3 第一层请求: 获取北京区域院校列表调用接口拿到院校名称、学校唯一 ID province_id11 代表北京市。# 1.第一个请求网址 以北京城市的大学数据为例子 school_api https://api.kaoyan.cn/pc/school/schoolList # 传递的信息 school_params { page:1, limit:20, province_id:11, type:, feature:, school_name: } # 发请求 post请求单独传递的参数复制给data res_school requests.post(urlschool_api,headersheaders,dataschool_params) school_list res_school.json()[data][data] # 直接调用json()1.4 遍历院校 第二层请求获取院校专业信息循环每一所学校根据学校 ID调用接口获取该学校下所有专业信息。# 遍历每一所学校 for school in school_list: school_name school[school_name] school_id school[school_id] print(f正在爬取{school_name}) # 专业接口 请求参数 major_api https://api.kaoyan.cn/pc/school/planListV2 major_params {limit: 5, school_id: school_id} # 请求专业数据 res_major requests.post(major_api, headersheaders, datamajor_params) major_list res_major.json()[data][data]1.5 遍历专业 第三层请求: 查询专业分数线循环每个专业根据专业 ID查询分数线增加异常捕获处理无分数的情况。 承接上一段循环在内部继续编写# 遍历当前学校下的所有专业 for major in major_list: major_name major[special_name] recruit_num major[recruit_number] study_type major[recruit_type_name] depart major[depart_name] plan_id major[plan_id] # 分数线接口 参数 score_api https://api.kaoyan.cn/pc/school/planDetailV2 score_params {is_apply: 2, plan_id: plan_id} # 请求分数线数据 res_score requests.post(score_api, headersheaders, datascore_params) # 异常捕获部分专业暂无分数线避免程序报错崩溃 try: min_score res_score.json()[data][min_score] except: min_score 暂无1.6 整合数据 延时爬取防反爬把单条数据整理成字典存入列表设置随机休眠降低请求频率。# 组装单条完整数据 row { 学校: school_name, 专业: major_name, 院系: depart, 招生数: recruit_num, 学习方式: study_type, 分数线: min_score } all_data.append(row) # 随机延时 1~3 秒简单规避反爬 time.sleep(random.randint(1, 3))1.7 数据本地持久化保存为 CSV 文件所有数据爬取完成后使用 pandas 导出为本地表格文件。# 转为DataFrame并保存CSV df pandas.DataFrame(all_data) df.to_csv(mnt/北京考研数据.csv, indexFalse, encodingutf-8-sig) print(数据爬取完成已保存)数据爬虫的完整代码import random import requests import time import pandas # 定义请求网址发送3次请求 # 定义一个空列表。来装每个学校的专业数据 alldata [] # 请求头 headers { user-agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36, referer:https://www.kaoyan.cn/ } # 1.第一个请求网址 以北京城市的大学数据为例子 school_api https://api.kaoyan.cn/pc/school/schoolList # 传递的信息 school_params { page:1, limit:20, province_id:11, type:, feature:, school_name: } # 发请求 post请求单独传递的参数复制给data res_school requests.post(urlschool_api,headersheaders,dataschool_params) school_list res_school.json()[data][data] # 直接调用json() # 遍历每一所学校 for school in school_list: school_name school[school_name] school_id school[school_id] print(f正在爬取{school_name}) # 专业接口 请求参数 major_api https://api.kaoyan.cn/pc/school/planListV2 major_params {limit: 5, school_id: school_id} # 请求专业数据 res_major requests.post(major_api, headersheaders, datamajor_params) major_list res_major.json()[data][data] # 遍历当前学校下的所有专业 for major in major_list: major_name major[special_name] recruit_num major[recruit_number] study_type major[recruit_type_name] depart major[depart_name] plan_id major[plan_id] # 分数线接口 参数 score_api https://api.kaoyan.cn/pc/school/planDetailV2 score_params {is_apply: 2, plan_id: plan_id} # 请求分数线数据 res_score requests.post(score_api, headersheaders, datascore_params) # 异常捕获部分专业暂无分数线避免程序报错崩溃 try: min_score res_score.json()[data][min_score] except: min_score 暂无 # 组装单条完整数据 row { 学校: school_name, 专业: major_name, 院系: depart, 招生数: recruit_num, 学习方式: study_type, 分数线: min_score } all_data.append(row) # 随机延时 1~3 秒简单规避反爬 time.sleep(random.randint(1, 3)) # 转为DataFrame并保存CSV df pandas.DataFrame(all_data) df.to_csv(mnt/北京考研数据.csv, indexFalse, encodingutf-8-sig) print(数据爬取完成已保存)第二部分数据可视化读取上面生成的 CSV 数据做数据清洗 多图表绘制依旧按功能拆分代码2.1 导入可视化相关库import pandas as pd from pyecharts.charts import Page, Bar, Line from pyecharts import options as opts2.2 读取数据 数据清洗过滤无效数据筛选出985 院校、全日制的有效数据并转换字段类型# 读取本地CSV文件 df pd.read_csv(mnt/全国考研数据.csv) # 数据清洗过滤无效值、筛选目标数据 df_clean df[df[招生人数] ! --] # 剔除招生人数为空的数据 df_clean df_clean[df_clean[学习方式] 全日制] # 只保留全日制 df_clean df_clean[df_clean[985] 是] # 只保留985院校 df_clean[招生人数] df_clean[招生人数].astype(int) # 转为数值类型2.3 模块一绘制专业招生人数 TOP15 柱状图统计热门专业招生总数取前 15 名绘制柱状图并优化 X 轴文字展示。# 分组统计各专业招生总人数倒序取前15 top15_major df_clean.groupby(专业)[招生人数].sum()\ .sort_values(ascendingFalse).head(15)\ .reset_index(name招生总人数) # 创建柱状图对象 bar1 Bar() bar1.add_xaxis(top15_major[专业].tolist()) bar1.add_yaxis(专业招生总人数, top15_major[招生总人数].tolist(), colorred) # 配置X轴文字倾斜、完整展示名称 bar1.set_global_opts( xaxis_optsopts.AxisOpts(axislabel_opts{interval: 0, rotate: 30}) )2.4 模块二筛选金融专业数据单独提取金融专业数据按学校分组统计招生数与最低分数线。# 筛选金融专业所有数据 df_finance df_clean[df_clean[专业] 金融] # 按学校分组聚合计算招生总数、最低分数线 finance_school df_finance.groupby(学校名称).agg( 总招生数(招生人数, sum), 最低分数(分数线, min) ).reset_index().sort_values(最低分数).head(10)2.5 模块三绘制分数线折线图基于上一步处理好的数据绘制院校分数线折线图。# 创建折线图 line Line() line.add_xaxis(finance_school[学校名称].tolist()) line.add_yaxis( 最低分数线, finance_school[最低分数].tolist(), linestyle_optsopts.LineStyleOpts(color#E53E3E) ) # X轴样式优化 line.set_global_opts( xaxis_optsopts.AxisOpts(axislabel_opts{interval: 0, rotate: 30}) )2.6 模块四绘制招生人数柱状图 图表叠加绘制金融专业招生人数柱状图并将折线图叠加在柱状图上实现组合图表# 创建柱状图招生人数 bar2 Bar() bar2.add_xaxis(finance_school[学校名称].tolist()) bar2.add_yaxis(金融专业招生数, finance_school[总招生数].tolist(), colordata) bar2.set_global_opts( xaxis_optsopts.AxisOpts(axislabel_opts{interval: 0, rotate: 30}) ) # 折线图叠加到柱状图中 bar2.overlap(line)2.7 模块五整合所有图表生成 HTML 文件使用 Page 容器把多张图表放在同一个页面最终渲染出网页文件# 创建页面容器 page Page(layoutPage.SimplePageLayout) # 加入所有图表 page.add(bar1, bar2) # 渲染为本地HTML浏览器可直接打开 page.render(考研数据可视化.html) print(图表绘制完成)数据可视化的完整代码import pandas as pd from pyecharts.charts import Page, Bar, Line from pyecharts import options as opts # 读取本地CSV文件 df pd.read_csv(mnt/全国考研数据.csv) # 数据清洗过滤无效值、筛选目标数据 df_clean df[df[招生人数] ! --] # 剔除招生人数为空的数据 df_clean df_clean[df_clean[学习方式] 全日制] # 只保留全日制 df_clean df_clean[df_clean[985] 是] # 只保留985院校 df_clean[招生人数] df_clean[招生人数].astype(int) # 转为数值类型 # 分组统计各专业招生总人数倒序取前15 top15_major df_clean.groupby(专业)[招生人数].sum()\ .sort_values(ascendingFalse).head(15)\ .reset_index(name招生总人数) # 创建柱状图对象 bar1 Bar() bar1.add_xaxis(top15_major[专业].tolist()) bar1.add_yaxis(专业招生总人数, top15_major[招生总人数].tolist(), colorred) # 配置X轴文字倾斜、完整展示名称 bar1.set_global_opts( xaxis_optsopts.AxisOpts(axislabel_opts{interval: 0, rotate: 30}) ) # 筛选金融专业所有数据 df_finance df_clean[df_clean[专业] 金融] # 按学校分组聚合计算招生总数、最低分数线 finance_school df_finance.groupby(学校名称).agg( 总招生数(招生人数, sum), 最低分数(分数线, min) ).reset_index().sort_values(最低分数).head(10) # 创建折线图 line Line() line.add_xaxis(finance_school[学校名称].tolist()) line.add_yaxis( 最低分数线, finance_school[最低分数].tolist(), linestyle_optsopts.LineStyleOpts(color#E53E3E) ) # X轴样式优化 line.set_global_opts( xaxis_optsopts.AxisOpts(axislabel_opts{interval: 0, rotate: 30}) ) # 创建柱状图招生人数 bar2 Bar() bar2.add_xaxis(finance_school[学校名称].tolist()) bar2.add_yaxis(金融专业招生数, finance_school[总招生数].tolist(), colordata) bar2.set_global_opts( xaxis_optsopts.AxisOpts(axislabel_opts{interval: 0, rotate: 30}) ) # 折线图叠加到柱状图中 bar2.overlap(line) # 创建页面容器 page Page(layoutPage.SimplePageLayout) # 加入所有图表 page.add(bar1, bar2) # 渲染为本地HTML浏览器可直接打开 page.render(考研数据可视化.html) print(图表绘制完成)三、项目总结爬虫部分采用接口直爬方式分三层请求数据搭配请求头、延时、异常捕获应对基础反爬最终落 地为 CSV 表格。可视化部分先清洗脏数据再分别绘制柱状图、折线图支持图表叠加与多图合并可视化结果直观 易懂。三层接口对应关系步骤接口用途入参出参第一层/pc/school/schoolList获取院校列表province_idschool_id第二层/pc/school/planListV2获取专业列表school_idplan_id第三层/pc/school/planDetailV2获取专业分数线plan_idmin_score拓展方向: 修改省份ID爬取全国数据, 增加分页逻辑, 新增饼图 / 散点图丰富分析温度本期内容就分享到这里啦如果你在实践过程中遇到任何问题或者想获取文中提到的完整源码、配置 文件模板以及更多进阶玩法可扫码领取完整爬虫可视化源码、2000条北京考研数据可直接用 于分析、省份ID对照表一键切换爬全国无套路纯分享。