一、项目背景:为什么需要公考数据分析与可视化?
1. 公考选岗的 3 大核心痛点
- 信息过载:国家公务员局等平台发布的岗位表多为 Excel 格式,包含 “岗位名称、专业要求、报考人数” 等数十个字段,考生筛选目标岗位需耗费数小时甚至数天。
- 竞争模糊:仅能看到单个岗位的 “过审人数”,无法直观对比 “不同地区 / 专业 / 岗位的竞争激烈程度”(如 “北京国税” 与 “上海海关” 的竞争比差异)。
- 趋势难判:缺乏 “疫情前后公考热度变化”“应届生岗位占比趋势” 等历史数据对比,考生难以把握报考时机。
2. 项目核心价值
- 对考生:通过可视化图表快速定位 “竞争小、匹配度高” 的岗位,提升上岸概率。
- 对管理部门:分析 “岗位冷热分布”,优化中央与地方岗位分配,避免资源浪费。
- 对研究机构:挖掘公考数据背后的 “就业趋势、地区发展差异”,为教育政策制定提供参考。
二、技术栈选型:Python 为何成为核心?
项目采用 “数据采集→清洗→存储→分析→可视化→Web 展示” 全流程技术链,核心工具与框架选型如下,兼顾 “开发效率” 与 “可视化效果”:
| 技术层级 | 工具 / 框架 | 核心作用 |
|---|---|---|
| 数据采集 | Python(Scrapy/Requests) | 爬取国家公务员局(bm.scs.gov.cn/)等平台的岗位表、报考人数数据。 |
| 数据清洗 | Python(Pandas/Numpy) | 处理缺失值(如 “专业要求为空”)、格式统一(如 “学历要求标准化为‘本科 / 硕士’”)、去除重复数据。 |
| 数据存储 | MySQL 5.7 | 结构化存储 “岗位信息表”“报考人数表”“地区信息表”,支持多表关联查询(如 “按地区统计岗位数”)。 |
| 数据分析 | Python(Pandas/Matplotlib) | 计算 “竞争比(过审人数 / 招录人数)”“各专业岗位占比”“应届生岗位比例” 等关键指标。 |
| 可视化 | ECharts/Python(Pyecharts) | 生成 “全国岗位分布地图”“竞争比柱状图”“专业要求饼图” 等交互式图表。 |
| Web 展示 | Flask+HTML+Layui | 搭建 Web 系统,实现 “登录验证、可视化大屏展示、岗位详情查询”,支持多终端访问。 |
选型优势:Python 的生态库(如 Scrapy 爬取高效、Pandas 处理数据便捷、Pyecharts 衔接 ECharts)可实现 “全流程数据处理”,无需切换多语言;MySQL 轻量开源,适合存储千万级以内的公考数据;Flask 框架轻量灵活,快速搭建 Web 服务。
三、核心流程:从数据爬取到可视化展示
1. 数据采集:精准获取公考核心数据
(1)数据源选择
- 官方平台:国家公务员局 “中央机关及其直属机构考试录用公务员专题网站”,爬取 “年度岗位表”“每日过审人数统计”。
- 补充数据源:各省市公务员考试网(如 “北京市人事考试网”),补充地方公考数据,实现 “全国 + 地方” 数据全覆盖。
(2)爬取策略(以 Scrapy 为例)
- 爬取岗位表:解析岗位表下载页面的 HTML,获取 Excel 下载链接,通过
requests下载文件后,用pandas读取并存储到 MySQL。 - 爬取实时报考人数:针对 “每日过审人数” 动态加载页面,通过分析 AJAX 请求,构造请求参数(如 “岗位 ID、日期”),批量获取数据。
- 反爬应对:设置
User-Agent伪装浏览器、添加随机爬取间隔(1-3 秒)、使用代理 IP 池,避免 IP 被封禁。
(3)关键代码片段(爬取岗位表)
import scrapy
import requests
import pandas as pd
from sqlalchemy import create_engine
class GongkaoSpider(scrapy.Spider):
name = "gongkao_position"
start_urls = ["http://bm.scs.gov.cn/pp/gkweb/core/web/ui/business/download/gkdownloads.html"]
def parse(self, response):
# 提取岗位表Excel下载链接(假设链接在a标签的href中,且包含"position"关键词)
excel_url = response.xpath('//a[contains(@href, "position")]/@href').extract_first()
if excel_url:
# 下载Excel文件
excel_response = requests.get(excel_url, headers={"User-Agent": "Mozilla/5.0"})
with open("gongkao_positions.xlsx", "wb") as f:
f.write(excel_response.content)
# 读取Excel并存储到MySQL
df = pd.read_excel("gongkao_positions.xlsx")
# 数据预处理:统一列名(如"专业要求"→"major_require")
df.rename(columns={
"部门名称": "dept_name",
"岗位名称": "position_name",
"专业要求": "major_require",
"招录人数": "recruit_num",
"学历要求": "edu_require",
"地区": "area"
}, inplace=True)
# 连接MySQL并写入数据
engine = create_engine("mysql+pymysql://root:123456@localhost:3306/gongkao_db")
df.to_sql("positions", engine, if_exists="append", index=False)
self.logger.info("岗位数据已写入数据库,共{}条".format(len(df)))
2. 数据清洗:让数据 “可用、可信”
爬取的原始数据存在 “格式混乱、缺失值、冗余信息” 等问题,需通过 Pandas 进行清洗,核心步骤如下:
-
缺失值处理:
- 关键字段(如 “招录人数、地区”)缺失的行直接删除;
- 非关键字段(如 “备注”)缺失的用 “无” 填充。
-
格式统一:
- 学历要求标准化:将 “大学本科及以上”“本科及以上” 统一为 “本科”;
- 地区格式统一:将 “北京市”“北京” 统一为 “北京”,便于后续按地区统计。
-
冗余数据删除:
- 去除重复岗位(通过 “部门名称 + 岗位名称” 联合去重);
- 删除无效字段(如 “无关的联系方式、报名须知链接”)。
清洗代码示例:
import pandas as pd
# 读取原始数据
df = pd.read_sql("positions", engine)
# 1. 处理缺失值
df = df.dropna(subset=["recruit_num", "area"]) # 删除关键字段缺失的行
df["remark"] = df["remark"].fillna("无") # 非关键字段用"无"填充
# 2. 格式统一(学历要求)
edu_map = {
"大学本科及以上": "本科",
"本科及以上": "本科",
"硕士研究生及以上": "硕士",
"硕士及以上": "硕士"
}
df["edu_require"] = df["edu_require"].map(edu_map).fillna(df["edu_require"]) # 未匹配的保留原值
# 3. 去重
df = df.drop_duplicates(subset=["dept_name", "position_name"])
# 4. 保存清洗后的数据
df.to_sql("positions_cleaned", engine, if_exists="replace", index=False)
print("数据清洗完成,清洗后共{}条记录".format(len(df)))
3. 数据分析:挖掘关键指标
基于清洗后的数据,计算考生最关心的核心指标,示例如下:
| 分析维度 | 核心指标 | 计算逻辑 |
|---|---|---|
| 地区分析 | 各地区岗位数、竞争比 TOP10 地区 | 竞争比 = 该地区总过审人数 / 总招录人数 |
| 专业分析 | 需求最高的 10 个专业、不限专业岗位占比 | 统计 “major_require” 字段中各专业出现次数,不限专业岗位数 / 总岗位数 ×100% |
| 竞争分析 | 竞争比 TOP50 岗位、无人报考岗位数 | 单个岗位竞争比 = 该岗位过审人数 / 招录人数,筛选过审人数 = 0 的岗位 |
| 趋势分析 | 疫情前后(2019vs2022)公考报名人数变化、应届生岗位占比变化 | 按年份分组统计报名人数,应届生岗位数 / 总岗位数 ×100%(对比不同年份) |
竞争比分析代码示例:
# 读取岗位表和报考人数表(假设报考人数表含"position_id, review_num")
positions_df = pd.read_sql("positions_cleaned", engine)
apply_df = pd.read_sql("application_num", engine)
# 合并两张表(通过岗位ID关联)
merged_df = pd.merge(positions_df, apply_df, on="position_id", how="inner")
# 计算单个岗位竞争比
merged_df["competition_ratio"] = merged_df["review_num"] / merged_df["recruit_num"]
# 筛选竞争比TOP50岗位
top50_competition = merged_df.nlargest(50, "competition_ratio")[
["dept_name", "position_name", "area", "recruit_num", "review_num", "competition_ratio"]
]
# 保存结果
top50_competition.to_sql("top50_competition", engine, if_exists="replace", index=False)
print("竞争比TOP50岗位分析完成")
4. 可视化展示:让数据 “看得见、好理解”
采用 “ECharts+Flask+HTML” 构建交互式可视化页面,核心展示模块如下:
(1)全国岗位分布地图
- 功能:在地图上用 “颜色深浅” 表示各地区岗位数量(颜色越深,岗位越多),点击省份可查看该省 “岗位数、平均竞争比、热门岗位 TOP3”。
- 技术实现:使用 ECharts 的 “map” 组件,加载中国地图 JSON 数据(china.js),将分析后的地区岗位数据传入,配置颜色映射(如 “岗位数 < 500 为浅蓝,500-1000 为蓝色,>1000 为深蓝”)。
(2)竞争比 TOP10 地区柱状图
- 功能:横向柱状图展示 “竞争比最高的 10 个地区”,X 轴为竞争比,Y 轴为地区名称,鼠标悬浮可查看 “总招录人数、总过审人数”。
- 技术实现:用 Pyecharts 生成柱状图,设置 “可缩放、可导出图片” 功能,嵌入 Flask 渲染的 HTML 页面。
(3)可视化大屏(核心模块)
- 布局:分为 “全国概览区(岗位总数、报名总人数、平均竞争比)”“地区分布区(地图)”“竞争 TOP 区(柱状图)”“专业需求区(饼图)”“趋势变化区(折线图)”5 大模块。
- 交互:支持 “按年份切换数据(2020-2023)”“按岗位类型筛选(中央 / 地方)”,点击图表可查看详情(如点击专业饼图的 “计算机”,显示该专业的岗位列表)。
ECharts 地图可视化代码片段(HTML) :
<!-- 引入ECharts和中国地图JS -->
<script src="https://cdn.jsdelivr.net/npm/echarts@5.3.2/dist/echarts.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/echarts/map/js/china.js"></script>
<!-- 地图容器 -->
<div id="areaMap" style="width: 800px; height: 500px;"></div>
<script>
// 初始化ECharts实例
var myChart = echarts.init(document.getElementById('areaMap'));
// 从Flask后端获取地区岗位数据(假设后端接口返回JSON格式)
fetch('/api/area_position_data')
.then(response => response.json())
.then(data => {
// 配置项
var option = {
title: { text: '全国公考岗位分布', left: 'center' },
tooltip: {
trigger: 'item',
formatter: function(params) {
return `地区:${params.name}<br>岗位数:${params.value}<br>平均竞争比:${params.data.comp_ratio.toFixed(2)}`;
}
},
visualMap: {
min: 0,
max: 1500,
left: 'left',
top: 'bottom',
text: ['岗位数多', '岗位数少'],
calculable: true
},
series: [{
name: '岗位数',
type: 'map',
mapType: 'china',
roam: true, // 允许缩放、平移
label: { show: true }, // 显示省份名称
data: data.map(item => ({
name: item.area,
value: item.position_num,
comp_ratio: item.avg_competition_ratio
}))
}]
};
myChart.setOption(option);
});
</script>
5. Web 系统搭建:Flask 实现 “数据展示 + 交互”
使用 Flask 框架搭建 Web 服务,核心功能包括:
-
登录验证:管理员(查看全量数据、更新数据)、考生(查看公开数据、查询岗位)两种角色,密码用 MD5 加密存储。
-
路由设计:
/:首页(可视化大屏入口);/api/area_position_data:提供地区岗位数据(供 ECharts 调用);/position_detail:岗位详情查询(支持按 “地区、专业、学历” 筛选);/admin/update_data:管理员数据更新接口(重新爬取最新公考数据)。
-
模板渲染:使用 Jinja2 模板引擎,将 HTML 页面与 Python 后端数据结合,动态生成可视化页面。
Flask 核心路由代码示例:
from flask import Flask, render_template, jsonify, request
import pandas as pd
from sqlalchemy import create_engine
app = Flask(__name__)
engine = create_engine("mysql+pymysql://root:123456@localhost:3306/gongkao_db")
# 首页(可视化大屏)
@app.route('/')
def index():
return render_template('index.html')
# 提供地区岗位数据(供ECharts调用)
@app.route('/api/area_position_data')
def area_position_data():
# 查询各地区岗位数和平均竞争比
sql = """
SELECT area, COUNT(*) AS position_num, AVG(competition_ratio) AS avg_competition_ratio
FROM positions_cleaned
GROUP BY area
"""
df = pd.read_sql(sql, engine)
# 转换为JSON格式
data = df.to_dict('records')
return jsonify(data)
# 岗位详情查询
@app.route('/position_detail')
def position_detail():
# 获取筛选参数(如地区、专业)
area = request.args.get('area', '')
major = request.args.get('major', '')
# 构造查询SQL
sql = "SELECT * FROM positions_cleaned WHERE 1=1"
params = []
if area:
sql += " AND area = %s"
params.append(area)
if major:
sql += " AND major_require LIKE %s"
params.append(f"%{major}%")
df = pd.read_sql(sql, engine, params=params)
# 传递数据到模板
return render_template('position_detail.html', positions=df.to_dict('records'))
if __name__ == '__main__':
app.run(debug=True)
四、项目成果与价值
1. 核心成果
- 数据覆盖:涵盖 2020-2023 年全国公考数据,包括 “中央机关 + 31 个省市地方岗位”,累计岗位数超 10 万条,报考人数数据超 500 万条。
- 可视化模块:实现 “全国地图、柱状图、饼图、折线图” 等 8 类图表,支持 “年份切换、地区筛选、专业筛选” 等交互操作。
- Web 系统:部署在学生服务器,支持多用户同时访问,响应时间<3 秒,界面适配电脑、平板等终端。
五、运行截图
六、源码与资料获取
本文仅展示平台核心功能与关键代码,完整开发资料包含:
全套源码(后端 SSM 工程 + 前端小程序代码 + MySQL 脚本);
详细开发文档(环境搭建步骤、接口说明、数据库设计图);
测试用例与性能测试报告;
论文完整文档(含目录、参考文献、图表)。
👉 获取方式:关注 CSDN 博主,查看置顶文章;备注 “源码获取”,即可免费领取完整资料!
如果本文对你的毕设或项目开发有帮助,欢迎点赞 + 收藏 + 关注,后续会持续分享管理系统类、校园类项目开发技巧!