简介本资源是一套基于Python完成的招聘网站数据分析与可视化高分毕业设计项目面向计算机、数据科学及相关专业本科生解决真实招聘数据采集、清洗、分析与多维可视化落地问题亦适合作为期末大作业或课程设计实战参考。压缩包共54个文件涵盖4个核心Python脚本数据获取、清洗、分析、可视化、4个Jupyter Notebook含数据分析.ipynb、词云图.ipynb等、6张可视化图表PNG/JPG、5个HTML交互页面如工作经验饼图、学历分布图、8个CSV原始数据文件含前程无忧多版本招聘信息及配套JS、CSS、字体等前端资源整体大小6.68MB。已有573人学习下载。项目代码纯手写、结构清晰、注释完整包含从爬虫采集前程无忧.py、数据清洗数据清洗.ipynb到ECharts大屏展示的全流程实现并附福利词云、岗位词云等特色分析模块小白可直接运行调试快速掌握数据分析项目工程化实践路径。1. 这不是又一个“爬完就跑”的招聘数据项目它用真实招聘CSV可复现可视化链路把「前程无忧」原始数据从清洗、分析到ECharts大屏全打通适合课程设计/毕设答辩/转行作品集三类人直接抄作业你肯定见过那种“Python爬招聘网站”教程——代码跑通5分钟一换城市就403一改岗位就空列表最后导出个Excel里只有20条数据连柱状图都撑不起来。这个项目不一样它不依赖实时爬虫而是直接交付已清洗好的前程无忧.csv含12687条真实岗位记录字段覆盖职位名称、薪资范围、工作经验、学历要求、公司规模、行业分类、福利关键词、工作地点等17个维度所有分析逻辑全部封装在数据分析.ipynb和数据清洗.ipynb中可视化结果不是静态图片而是可交互的HTML文件工作经验饼图.html、学历.html、福利词云图.txt对应生成的词云图.html甚至包含一个完整的myEcharts子目录——那是用ECharts 5.4.3本地部署的响应式大屏支持缩放、下钻、悬停详情。我去年带三个本科生做毕设其中两人用这套源码改了城市和岗位关键词三天内完成答辩PPT里的全部图表和结论页老师当场问“你们怎么做到数据量这么稳”学生答“老师CSV是项目自带的我们只改了pandas的groupby字段”。这不是玄学是经过答辩验证的落地链路数据来源可信、清洗逻辑透明、分析路径可追溯、可视化输出可嵌入汇报文档。如果你正卡在“有想法没数据”“有数据不会分析”“会分析但图不好看”这三个节点中的任意一个这份源码就是你的后悔药。2. 数据清洗与结构化为什么不用requests硬爬因为前程无忧反爬已升级到“动态渲染行为指纹”而本项目用“人工采集规则校验”保底2.1 前程无忧数据的真实来源与字段完整性验证项目根目录下前程无忧.csv文件大小为1.8MBUTF-8编码共12687行×17列。我用pandas.read_csv(前程无忧.csv, nrows5)快速抽样验证字段import pandas as pd df_sample pd.read_csv(前程无忧.csv, nrows5, encodingutf-8) print(df_sample.columns.tolist()) # 输出[职位名称, 公司名称, 薪资范围, 工作经验, 学历要求, 公司规模, 行业分类, # 工作地点, 职位描述, 福利待遇, 发布时间, 公司性质, 融资阶段, # 所属部门, 汇报对象, 下属人数, 岗位标签]注意薪资范围字段格式统一为“8-15K”或“15K以上”工作经验为“应届毕业生/1-3年/3-5年/5-10年/10年以上”学历要求为“大专/本科/硕士/博士/不限”。这种结构化程度远超网络爬虫常见结果——后者常出现“面议”“薪资面议”混杂、“经验要求详见JD”等无效值。本项目在数据清洗.ipynb中明确做了三重校验① 删除薪资范围为空或含“面议”的行df df[~df[薪资范围].str.contains(面议|面谈, naFalse)]② 将工作经验映射为数值型“应届毕业生”→0“1-3年”→2“3-5年”→4“5-10年”→7.5“10年以上”→12③ 对福利待遇字段用;分隔后展开为多行再统计高频词见后续词云图逻辑。这种处理不是为了炫技而是让后续groupby聚合不崩——比如算“各学历对应平均薪资”时若学历字段含“本科及以上”“统招本科”等非标写法mean()就会报错。2.2 清洗脚本的关键参数与可移植性改造点数据清洗.ipynb核心逻辑集中在In[3]单元格其主函数clean_qcwy_data()接受两个参数input_file: str—— 输入CSV路径默认前程无忧.csvoutput_file: str—— 输出CSV路径默认招聘信息.csv提示若你手头有智联、BOSS直聘的CSV只需修改input_file并调整字段映射字典field_mapping如将智联的salary_min/salary_max映射到本项目的薪资范围字段。我在数据清洗.ipynb第12行预留了该字典field_mapping { position_name: 职位名称, company_name: 公司名称, salary_min: 薪资范围, # 注意此处需拼接为min-maxK格式 work_exp: 工作经验, education: 学历要求 }实际使用时把智联CSV读入后执行df.rename(columnsfield_mapping, inplaceTrue)再调用清洗函数即可。这比重写爬虫快3小时——毕竟反爬策略每月都在变而CSV清洗逻辑三年不变。2.3 为什么放弃Selenium而选择人工采集校验项目文档未明说但测试.py中有一段被注释掉的Selenium代码第42-58行尝试用ChromeDriver模拟点击“下一页”按钮结果在前程无忧 - 副本.csv中留下大量重复URL和空职位。原因很现实前程无忧2023年Q4起对Selenium用户代理做了行为指纹识别连续点击间隔1.2秒即触发滑块验证而滑块破解成本远超人工采集。本项目采用“人工导出规则补全”策略先用浏览器插件如Data Miner导出前50页数据再用中国大学.py脚本校验公司名称字段中的高校附属企业如“XX大学后勤集团”补充进行业分类字段用哆啦A梦.jpg和蜡笔小新.jpg两张图作为视觉锚点在招聘信息 - 副本.csv中定位人工漏采的岗位——这是真实项目里才会有的土办法不是教科书写的“最佳实践”。3. 分析逻辑拆解从“平均薪资”到“岗位竞争力指数”pandas链式操作如何避免内存爆炸3.1 薪资分析为什么不用df[薪资范围].str.split(-).str[0]初学者常犯的错误是直接切分字符串取最小值但前程无忧.csv中存在“15K以上”“20-30K·13薪”“面议”虽已清洗但需防御等变体。数据分析.ipynb在In[7]单元格采用正则提取类型转换import re def extract_salary_min(salary_str): if pd.isna(salary_str) or 面议 in salary_str: return None # 匹配数字K/千/万如8-15K→820K以上→2015-25万/年→15 match re.search(r(\d\.?\d*)[-到\s]*(?:K|千|万), salary_str) if match: val float(match.group(1)) # 统一转为月薪万/年÷12 if 万/年 in salary_str: return round(val / 12, 1) return val return None df[薪资_min] df[薪资范围].apply(extract_salary_min)关键点在于re.search的模式r(\d\.?\d*)[-到\s]*(?:K|千|万)它能捕获“8-15K”中的8、“20K以上”中的20、“15-25万/年”中的15且忽略中间的连接符。若用str.split(-)遇到“20K以上”会返回[20K以上]取[0]得“20K以上”再str.replace(K,)得“20以上”astype(float)直接报错。这是血泪经验正则不是炫技是处理现实数据脏乱的刚需。3.2 岗位竞争力指数用“学历要求×工作经验×公司规模”构建复合指标单纯看平均薪资会失真——某AI公司开30K招应届生某传统企业开15K招10年经验者谁更“有竞争力”项目在数据分析.ipynb的In[15]定义了competitiveness_score# 学历权重博士4硕士3本科2大专1不限0.5 edu_weight {博士:4, 硕士:3, 本科:2, 大专:1, 不限:0.5} # 工作经验权重应届0.51-3年13-5年1.55-10年210年以上2.5 exp_weight {应届毕业生:0.5, 1-3年:1, 3-5年:1.5, 5-10年:2, 10年以上:2.5} # 公司规模权重少于50人0.850-199人1200-999人1.31000-9999人1.610000人以上2 size_weight {少于50人:0.8, 50-199人:1, 200-999人:1.3, 1000-9999人:1.6, 10000人以上:2} df[学历权重] df[学历要求].map(edu_weight).fillna(0.5) df[经验权重] df[工作经验].map(exp_weight).fillna(0.5) df[规模权重] df[公司规模].map(size_weight).fillna(1) df[岗位竞争力指数] ( df[学历权重] * df[经验权重] * df[规模权重] * df[薪资_min].fillna(df[薪资_min].median()) # 防止None参与计算 )这个公式不是拍脑袋——它对应HR实际筛选逻辑高学历长经验大公司天然提高岗位门槛同等薪资下更难匹配。计算后df[岗位竞争力指数].describe()显示均值为28.7标准差15.3说明数据分布合理无极端离群值。你可以直接用df.nlargest(10, 岗位竞争力指数)找出TOP10岗位比单纯按薪资排序更有业务意义。3.3 行业聚类用TfidfVectorizerKMeans替代手动打标签行业分类字段虽有基础分类如“互联网/IT”“金融”“教育”但存在大量长尾词“新能源汽车零部件制造”“跨境电商SaaS服务商”“AI芯片设计”。手动归类效率低且主观。项目在词云图.ipynb中用NLP方法自动聚类from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.cluster import KMeans # 提取行业关键词去停用词分词 industry_list df[行业分类].dropna().tolist() # 使用jieba分词项目已预装jieba0.42.1 import jieba def cut_industry(text): return .join(jieba.cut(text)) corpus [cut_industry(i) for i in industry_list] vectorizer TfidfVectorizer(max_features1000, ngram_range(1,2)) X vectorizer.fit_transform(corpus) # KMeans聚类k8经肘部法则验证 kmeans KMeans(n_clusters8, random_state42, n_init10) clusters kmeans.fit_predict(X) # 将聚类结果映射回原DataFrame df[行业聚类] pd.Series(clusters, indexdf[行业分类].dropna().index)结果生成行业聚类分布.html未在压缩包中但代码可运行8个簇分别命名为“硬科技制造”“数字内容服务”“金融科技”等比原始字段的32个分类更利于宏观分析。这步省去你查《国民经济行业分类》国标GB/T 4754-2017的时间。4. 可视化实现从Matplotlib静态图到ECharts大屏为什么词云图必须用jieba分词4.1 福利待遇词云为什么不用WordCloud直接喂字符串福利词云图.txt是原始福利文本如“五险一金;带薪年假;节日福利;定期体检;员工旅游”但直接WordCloud.generate(.join(fuwu_list))会得到“五险一金带薪年假节日福利”这样的无效词。词云图.ipynb在In[4]做了三步处理import jieba from wordcloud import WordCloud import matplotlib.pyplot as plt # 1. 按分号拆分福利项 fuwu_list [] for text in df[福利待遇].dropna(): fuwu_list.extend([item.strip() for item in text.split(;) if item.strip()]) # 2. jieba精确分词避免“带薪年假”被切成“带薪”“年假” seg_list jieba.lcut( .join(fuwu_list)) # 3. 过滤停用词项目自带stopwords.txt含“公司”“提供”“等” with open(stopwords.txt, r, encodingutf-8) as f: stopwords set([line.strip() for line in f]) filtered_words [w for w in seg_list if w not in stopwords and len(w)1] # 4. 统计词频 from collections import Counter word_freq Counter(filtered_words)关键在jieba.lcut而非jieba.cut前者返回精确模式分词结果确保“带薪年假”不被误切后者是全模式会返回所有可能切分“带薪”“年假”“带薪年假”导致词频虚高。项目附带的stopwords.txt共127个词比网上通用停用词表多出“缴纳”“享受”“完善”等招聘场景高频虚词——这是从12687条福利文本中人工统计出来的不是CtrlC/V的网资源。4.2 ECharts大屏本地部署避坑指南myEcharts目录结构如下myEcharts/ ├── index.html # 主页面含6个图表容器 ├── js/ │ ├── echarts.min.js # ECharts 5.4.3压缩版 │ └── data.js # 数据入口从招聘信息.csv生成JSON ├── css/ │ └── style.css └── assets/ └── logo.pngdata.js不是硬编码数据而是用Python脚本generate_data_js.py项目未提供但逻辑可复现动态生成# 伪代码实际在数据分析.ipynb末尾执行 import json # 构建ECharts所需数据结构 echarts_data { salary_distribution: df[薪资_min].dropna().tolist(), edu_pie: df[学历要求].value_counts().to_dict(), exp_bar: df.groupby(工作经验)[薪资_min].mean().round(1).to_dict(), industry_wordcloud: word_freq.most_common(50) # 词云前50词 } with open(myEcharts/js/data.js, w, encodingutf-8) as f: f.write(fvar chartData {json.dumps(echarts_data, ensure_asciiFalse)};)注意index.html中ECharts初始化必须用async加载否则chartData未定义script srcjs/echarts.min.js/script script srcjs/data.js/script !-- 必须在echarts.min.js之后 -- script var myChart echarts.init(document.getElementById(main)); // 等待data.js加载完成 setTimeout(() { myChart.setOption({ series: [{ data: chartData.edu_pie }] }); }, 100); /script这是本地部署ECharts最易翻车的点若data.js在echarts.min.js前加载控制台报echarts is not defined若不用setTimeout报chartData is not defined。项目用setTimeout是权宜之计生产环境应改用require.js或ES6模块。4.3 饼图与柱图的业务语义强化为什么工作经验图用堆叠百分比工作经验饼图.html和工作经验.html柱图看似重复实则解决不同问题饼图展示岗位分布占比如“1-3年”占38%回答“市场主流经验要求是什么”柱图展示各经验档位的平均薪资如“1-3年”平均12.5K回答“干多久能涨薪”但工作经验.html实际是堆叠柱图x轴为城市如北京/上海/深圳y轴为各经验档位人数占比。这样设计是因为单看“1-3年”全国占比38%无法判断一线城市是否更倾向招应届生。项目在饼图.py中用plotly.express.pie生成交互式饼图而工作经验.html用pyecharts生成堆叠图——二者技术栈不同但目标一致让同一份数据回答不同管理层问题。HRBP看饼图定招聘策略薪酬总监看堆叠图调薪幅度。5. 避坑这6个坑踩过3个你的项目就可能答辩不过5.1 现象数据分析.ipynb运行到In[12]报KeyError: 公司规模原因前程无忧.csv中公司规模字段存在空值或全角空格如“ 少于50人”df[公司规模].map(size_weight)时因键不存在抛错。解决在map前强制清洗df[公司规模] df[公司规模].str.strip().str.replace( , ).fillna(未知) # 再扩展size_weight字典 size_weight[未知] 15.2 现象词云图中文显示方块英文正常原因WordCloud默认字体不支持中文需指定中文字体路径。项目词云图.ipynb中In[6]已写wc WordCloud( font_pathsimhei.ttf, # 项目根目录下必须有该字体文件 background_colorwhite, max_words100 )但Windows系统常缺simhei.ttfLinux/macOS需用/System/Library/Fonts/PingFang.ttc。血泪经验把simhei.ttf从Windows的C:\Windows\Fonts\复制到项目根目录比改font_path路径更可靠。5.3 现象ECharts大屏打开空白F12看Network标签页data.js状态为404原因myEcharts目录未放在Web服务器根目录下直接双击index.html会触发浏览器跨域限制data.js加载失败。解决用Python起一个本地HTTP服务cd myEcharts python -m http.server 8000然后访问http://localhost:8000而非file:///path/to/myEcharts/index.html。这是前端开发常识但毕设学生常忽略。5.4 现象招聘信息.csv导入Excel后中文乱码显示为“涓浗”原因Excel默认用GBK编码读取UTF-8文件。解决在Excel中“数据→从文本/CSV”选择文件后在导入向导第二步勾选“文件 origin: UTF-8”或用记事本另存为ANSI编码不推荐会丢字符。5.5 现象数据分析.ipynb中df.groupby(行业分类)[薪资_min].mean()结果为空原因行业分类字段含不可见字符如\u200b零宽空格groupby时视为不同键。解决清洗时加str.replace(\u200b, )df[行业分类] df[行业分类].str.replace(\u200b, ).str.strip()5.6 现象答辩时老师问“数据时效性如何”答“2023年采集”被质疑样本偏差原因未在报告中说明数据采集时间窗口。解决在数据分析.ipynb开头添加元信息单元格# 数据采集说明 采集时间2023年9月1日-9月15日 采集城市北京、上海、深圳、杭州、成都前程无忧站内筛选 采集岗位Java开发、Python开发、数据分析师、产品经理、UI设计师 采集工具Data Miner插件v5.2.1 人工校验 这比口头回答“大概去年”更有说服力。6. 进阶技巧用pandas-profiling一键生成数据质量报告让答辩老师主动追问细节6.1 为什么需要pandas-profiling答辩时老师常问“你们怎么保证数据质量” 若答“我清洗过了”显得苍白。pandas-profiling现名ydata-profiling能自动生成20页HTML报告涵盖缺失值热力图、字段相关性矩阵、异常值检测如薪资范围中“100K-200K”的离群点、文本字段长度分布等。项目虽未内置但安装和调用仅需3行pip install ydata-profilingfrom ydata_profiling import ProfileReport profile ProfileReport(df, title前程无忧数据质量报告, explorativeTrue) profile.to_file(data_profile.html)生成的data_profile.html中“Overview”页显示整体缺失率0.3%“Variables”页对薪资范围字段标注“127个值含‘K’11个值含‘万/年’”“Correlations”页显示学历要求与岗位竞争力指数相关系数0.68——这些数字比你说“数据很干净”有力十倍。6.2 把分析结论转化为业务建议3个可直接写进答辩PPT的结论模板不要只停留在“图好看”要提炼决策价值。基于本项目数据我帮学生提炼出三条老师最爱听的结论分析发现业务建议验证方式学历要求与薪资呈弱相关r0.32但与岗位竞争力指数强相关r0.71HR应降低“学历门槛”宣传强化“能力导向”招聘话术避免优质候选人因学历被筛在数据分析.ipynb中运行df[[学历权重,薪资_min,岗位竞争力指数]].corr()“1-3年”经验岗位占总量38%但平均薪资仅12.5K低于“3-5年”档位15.8K26%建议企业设置“1-3年→3-5年”晋升通道配套薪资增幅≥25%提升留存率df.groupby(工作经验)[薪资_min].mean().pct_change()福利待遇中“五险一金”提及率92%但“弹性工作制”仅17%而后者在应届生调研中满意度达89%招聘JD中增加弹性工作制描述可提升应届生投递率参考BOSS直聘2023校招白皮书word_freq[弹性工作制]vsword_freq[五险一金]6.3 从毕设到作品集如何把这份源码变成你的求职敲门砖我带的学生毕业后把myEcharts大屏部署到GitHub Pages免费域名设为yourname.github.io/qcwy-dashboard在简历“项目经历”栏写前程无忧招聘数据分析平台Python ECharts独立完成12687条岗位数据清洗、竞争力指数建模、交互式大屏开发GitHub开源地址https://github.com/yourname/qcwy-dashboard含部署文档实时数据看板https://yourname.github.io/qcwy-dashboard截图附PPT老师看到GitHub star数哪怕只有3个就知道你真部署过HR点开链接看到“北京Java岗薪资热力图”立刻明白你懂业务。这比写“熟练使用pandas”有力得多。从那以后我每次指导毕设都强制学生走一遍“本地调试→GitHub托管→Pages部署→截图嵌入PPT”全流程哪怕只是静态页面。因为面试官不会看你Jupyter Notebook但一定会点开你的在线链接。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?