欢迎光临
我们一直在努力

# 【实战】Python爬取全国考研数据与可视化(附源码)

很多考研同学都会关注院校招生人数、专业分数线等信息,手动整理效率极低。本篇用 Python 完成接口爬虫 + 数据存储 + 可视化分析全流程实战,从考研网站抓取院校专业数据,再通过图表直观分析数据,适合爬虫、数据分析入门学习。

一、项目的环境准备

pip install requests pandas pyecharts

上述代码在pycharm的终端内输入,目的是下载requests,pandas和pyecharts的库

二、整体开发思路

整个项目分为两大模块:数据爬虫和数据可视化。

  • 爬虫模块:通过三层接口请求,依次获取院校、专业、分数线,最终保存为 CSV 文件;
  • 可视化模块:读取 CSV 数据、清洗数据,使用 pyecharts 绘制多类图表并整合展示。

  • 第一部分:数据爬取(分段拆解)

    爬虫采用三层 POST 接口请求,下面按功能拆分模块,逐个讲解。

    1.1 导入依赖 + 初始化全局变量

    先导入需要的库,并定义列表用来存放最终爬取的数据。

    import random
    import requests
    import time
    import pandas

    # 定义一个空列表,装整体数据
    add_data = []

    1.2 配置请求头(模拟浏览器,防拦截)

    网站接口会校验访问来源,配置请求头伪装成正常浏览器访问(进入浏览器按F12启用管理者权限,在网络内找到自己电脑的请求头)。

    # 请求头
    h = {
    "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_id=11 代表北京市。

    # 院校接口地址与请求参数
    school_api = "https://api.kaoyan.cn/pc/school/schoolList"
    school_params = {
    "page": 1, "limit": 20, "province_id": "11",
    "type": "", "feature": "", "school_name": ""
    }

    # 发送POST请求,解析返回的JSON数据
    res_school = requests.post(school_api, headers=headers, data=school_params)
    school_list = res_school.json()["data"]["data"]

    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, headers=headers, data=major_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, headers=headers, data=score_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 = pd.DataFrame(all_data)
    df.to_csv("mnt/北京考研数据.csv", index=False, encoding="utf-8-sig")
    print("数据爬取完成,已保存!")

    爬虫的完整代码

    import random
    import requests
    import time
    import pandas

    # 定义请求网址:发送3次请求
    # 定义一个空列表。来装每个学校的专业数据
    alldata = []

    # 1.第一个请求网址 以北京城市的大学数据为例子
    xxurl = "https://api.kaoyan.cn/pc/school/schoolList"

    # 请求头
    h = {
    "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/"
    }

    # 传递的信息
    xxdata = {
    "page": 1,
    "limit": 20,
    "province_id": "11",
    "type": "",
    "feature": "",
    "school_name": ""
    }

    # 发请求 post请求单独传递的参数,复制给data
    xxres = requests.post(url=xxurl, headers=h, data=xxdata)
    xxlist = xxres.json()["data"]["data"] # 直接调用json()

    '''
    需要从学校信息里面获取每个学校名称和唯一id值,
    '''
    for xx in xxlist:
    xname = xx["school_name"]
    print(f"开始爬取{xname}的专业")
    xid = xx["school_id"]

    # 携带这个id向该学校的详情页发请求,获取对应学校专业
    zyurl = "https://api.kaoyan.cn/pc/school/planListV2"

    # 专业需要携带的请求,发请求
    zydata = {"limit": 5, "school_id": xid} # 带上每个学校不同的id号,获取对应的专业

    # 获取专业发请求 第二次请求:
    zyres = requests.post(url=zyurl, headers=h, data=zydata)

    '''
    需要从专业信息里面提取什么,和下一步关联是什么?
    专业,招生数,学习方式,院系
    '''
    zylist = zyres.json()["data"]["data"]

    # 循环每一个专业,提取四个内容,找分数线的关键数据
    for zy in zylist:
    zyname = zy["special_name"]
    num = zy["recruit_number"]
    stype = zy["recruit_type_name"]
    departName = zy["depart_name"]

    # 从当前每个专业数据里面获取对应专业唯一的id,携带id发送第三次请求,拿到每个专业的分数线
    pid = zy["plan_id"]

    '''
    准备发第三次请求,携带专业id,拿分数线
    '''
    fsurl = "https://api.kaoyan.cn/pc/school/planDetailV2"

    # 准备传递的数据
    fsdata = {"is_apply": 2, "plan_id": pid}

    # 发请求
    fsres = requests.post(url=fsurl, headers=h, data=fsdata)

    # 获取专业分数。某些专业没有分数数据,找不到会报错,程序崩溃。try捕获报错
    try:
    score = fsres.json()["data"]["min_score"]
    except Exception as e:
    print(f"该专业暂无分数{e}")
    score = "暂无"

    # 整合数据,6个内容
    info = {
    "学校": xname,
    "专业": zyname,
    "院系": departName,
    "招生数": num,
    "学习方式": stype,
    "分数线": score,
    }
    alldata.append(info)

    # 加一个等待时间,避免短时间爬取太快
    time.sleep(random.randint(1, 3))

    # 存为本地的csv数据 用pandas转数据为表格数据类型
    df = pandas.DataFrame(alldata)
    df.to_csv("北京考研数据.csv", index=False)
    print("保存成功")

    第二部分:数据可视化

    读取上面生成的 CSV 数据,做数据清洗 + 多图表绘制,依旧按功能拆分代码。

    2.1 导入可视化相关库

    import pandas as pd
    from pyecharts.charts import Page, Bar, Line
    from pyecharts import options as opts

    2.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"] == "是"]
    df_clean["招生人数"] = df_clean["招生人数"].astype(int)

    2.3 模块一:绘制专业招生人数 TOP15 柱状图

    统计热门专业招生总数,取前 15 名绘制柱状图,并优化 X 轴文字展示。

    # 分组统计各专业招生总人数,倒序取前15
    top15_major = df_clean.groupby("专业")["招生人数"].sum()\\
    .sort_values(ascending=False).head(15)\\
    .reset_index(name="招生总人数")

    # 创建柱状图对象
    bar1 = Bar()
    bar1.add_xaxis(top15_major["专业"].tolist())
    bar1.add_yaxis("专业招生总人数", top15_major["招生总人数"].tolist(), color="red")

    # 配置X轴:文字倾斜、完整展示名称
    bar1.set_global_opts(
    xaxis_opts=opts.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_opts=opts.LineStyleOpts(color="#E53E3E")
    )

    # X轴样式优化
    line.set_global_opts(
    xaxis_opts=opts.AxisOpts(axislabel_opts={"interval": 0, "rotate": 30})
    )

    2.6 模块四:绘制招生人数柱状图 + 图表叠加

    绘制金融专业招生人数柱状图,并将折线图叠加在柱状图上,实现组合图表。

    # 创建柱状图(招生人数)
    bar2 = Bar()
    bar2.add_xaxis(finance_school["学校名称"].tolist())
    bar2.add_yaxis("金融专业招生数", finance_school["总招生数"].tolist(), color="data")
    bar2.set_global_opts(
    xaxis_opts=opts.AxisOpts(axislabel_opts={"interval": 0, "rotate": 30})
    )

    # 折线图叠加到柱状图中
    bar2.overlap(line)

    2.7 模块五:整合所有图表,生成 HTML 文件

    使用 Page 容器把多张图表放在同一个页面,最终渲染出网页文件。

    # 创建页面容器
    page = Page(layout=Page.SimplePageLayout)

    # 加入所有图表
    page.add(bar1, bar2)

    # 渲染为本地HTML,浏览器可直接打开
    page.render("考研数据可视化.html")
    print("图表绘制完成!")

    完整数据可视化代码

    # 从绘图的库中引入柱状图和折线图
    from pyecharts.charts import Page, Bar, Line # 需要安装:pip install pyecharts
    from pyecharts import options as opts
    import pandas

    # 读取、清除脏数据、过滤需要的数据
    dfData = pandas.read_csv("全国考研数据.csv")

    # 招生人数清洗
    newdf = dfData[dfData["招生人数"] != "–"]
    newdf = newdf[newdf["学习方式"] == "全日制"]
    newdf = newdf[newdf["985"] == "是"]

    # 转换类型
    newdf["招生人数"] = newdf["招生人数"].astype(int)

    # 分组统计不同专业的招生数,从高到低取前15个
    zydata = newdf.groupby("专业")["招生人数"].sum().sort_values(
    ascending=False
    ).head(15).reset_index(name="招生总人数")

    # 创建柱状图
    bar = Bar()
    x_data = zydata["专业"].tolist()
    y_data = zydata["招生总人数"].tolist()
    bar.add_xaxis(x_data)
    bar.add_yaxis("各专业招生总数", y_data, color="red")

    # 优化X轴,让名称完整显示并倾斜30度
    bar.set_global_opts(
    xaxis_opts=opts.AxisOpts(
    axislabel_opts={
    "interval": 0,
    "rotate": 30
    }
    )
    )

    # 查看金融专业的招生情况
    major = newdf[newdf["专业"] == "金融"]

    # 按学校聚合招生总数与最低分数
    majorschool = major.groupby("学校名称").agg(
    总招生数=("招生人数", "sum"),
    最低分数=("分数线", "min")
    ).reset_index()

    # 按最低分数排序,取前10个
    resultdata = majorschool.sort_values(
    by="最低分数", ascending=True
    ).head(10)

    # 绘制各学校金融专业分数线对比折线图
    x_data = resultdata["学校名称"].tolist()
    y_data = resultdata["最低分数"].tolist()
    line = Line()
    line.add_xaxis(x_data)
    line.add_yaxis(
    "各学校金融专业分数线",
    y_data,
    z_level=2,
    linestyle_opts=opts.LineStyleOpts(color="#E53E3E")
    )
    line.set_global_opts(
    xaxis_opts=opts.AxisOpts(
    axislabel_opts={
    "interval": 0,
    "rotate": 30
    }
    )
    )

    # 绘制各学校金融专业招生人数对比柱状图
    y2_data = resultdata["总招生数"].tolist()
    bar2 = Bar()
    bar2.add_xaxis(x_data)
    bar2.add_yaxis("金融专业招生总数对比", y2_data, color="data")
    bar2.set_global_opts(
    xaxis_opts=opts.AxisOpts(
    axislabel_opts={
    "interval": 0,
    "rotate": 30
    }
    )
    )

    # 把折线图合并到柱状图中
    bar2.overlap(line)

    # 创建装所有图表的容器
    page = Page(layout=Page.SimplePageLayout)

    # 把三个图表整合在一个页面里
    page.add(bar, line, bar2)

    # 渲染合成的图表
    page.render("考研数据可视化.html")
    print("绘制结束")

    三、项目总结

  • 爬虫部分:采用接口直爬方式,分三层请求数据,搭配请求头、延时、异常捕获应对基础反爬,最终落地为 CSV 表格;

  • 可视化部分:先清洗脏数据,再分别绘制柱状图、折线图,支持图表叠加与多图合并,可视化结果直观易懂;

  • 拓展方向:修改省份 ID 爬取全国数据、增加分页逻辑、新增饼图 / 散点图丰富分析维度。

  • 本期内容就分享到这里啦!感谢您的观看!

    赞(0)
    未经允许不得转载:171主机测评 » # 【实战】Python爬取全国考研数据与可视化(附源码)
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址