ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

基于Python的Boss直聘数据分析:爬虫采集到可视化完整实战

基于Python的Boss直聘数据分析:爬虫采集到可视化完整实战 简介基于boss直聘网数据的Python数据分析与可视化项目完整覆盖数据清洗、字段重塑、plotly交互绘图与flaskbootstrap网页展示适合数据分析初学者、高校学生完成期末大作业或入门Flask可视化开发。资源共60个文件包含16个HTML网页展示模板、3个Jupyter notebook分析脚本、2个CSV原始数据以及JPG/PNG图表和CSS等辅助文件压缩包仅6.15MB目录结构清晰。已有1389人学习使用。项目亮点在于对职位、城市、学历、工作经验、行业标签等分类字段和最低/最高/平均薪资等数值字段做了系统性分析生成多类可视化图表呈现数据岗位人才需求、薪资分布与发展前景能够帮助读者快速掌握从数据到图表再到网页的可视化流程也可作为期末作品的直接参考。1. 项目概述与选题背景1.1 为什么选“Boss直聘数据分析”作为期末项目去年带学生做期末大作业有个选题让我印象很深就是用Python爬Boss直聘的岗位数据然后做一轮完整的数据分析和可视化。这句话说出来轻飘飘的真做起来涉及的东西可不少爬虫策略、请求头伪装、IP代理池、数据清洗、字段抽取、中文分词、薪资区间处理、可视化大屏一路串下来基本把Python数据分析的主流技能点全过了一遍。所以这个选题特别适合期末大作业或者简历里的实战项目——技术栈完整、结果可见性强、面试有的聊。选择Boss直聘作为数据源有它的天然优势岗位关键词可以自由组合地域可以切换薪资范围、经验要求、学历要求这些结构化字段非常干净特别适合做横向对比分析。更重要的是招聘数据背后反映的是行业人才需求的真实走向分析出来的结论有实际参考价值不是那种为了交作业硬凑出来的空壳项目。1.2 项目技术栈与整体架构这个项目我用的是Python 3.9 Requests Pandas Matplotlib PyECharts的组合。Requests负责数据采集Pandas做数据清洗和聚合分析Matplotlib用于快速出基础图表验证数据PyECharts用来做交互式可视化大屏。这里没有上Scrapy因为期末项目追求的是逻辑清晰、单文件可运行框架化反而增加了理解成本。如果你是想做简历项目建议也保持这个思路——先跑通再优化。整体流程分五步数据采集 - 数据清洗 - 存储落盘 - 分析建模 - 可视化呈现。整个过程用Jupyter Notebook串联每个阶段独立一个单元格区块方便做过程记录和结果展示。这也符合期末大作业“需要展示分析过程”的评分要求。2. 数据采集方案设计2.1 请求分析与接口定位Boss直聘的网页端数据是通过Ajax接口动态加载的直接请求HTML页面拿不到列表数据。这里需要打开浏览器的开发者工具F12切到Network面板点击“下一页”或者“搜索”按钮找到返回JSON数据的XHR请求。以“数据分析师”岗位、城市选北京为例核心请求接口是https://www.zhipin.com/wapi/zpgeek/search/joblist.json?scene1query数据分析师city100010000page1pageSize30接口返回的是标准JSON结构里边的zpData.jobList字段就是岗位列表。每个岗位包含字段很多但真正用得上的核心字段有这些jobName岗位名称比如“数据分析师”“高级数据分析师”salaryDesc薪资描述原始文本“20-40K·15薪”jobExperience经验要求jobDegree学历要求brandName公司名称brandStageName公司融资阶段比如“C轮”“已上市”brandScaleName公司规模cityName城市jobLabels岗位标签包含“弹性工作”“年终奖”等这里要特别注意实际爬取时接口可能返回加密参数或需要携带Cookie。我的处理方案是先手动在浏览器中完成一次搜索把请求头中的Cookie和User-Agent完整复制到代码的Header中模拟真实浏览器请求。这种方法对期末项目完全够用也最稳妥。2.2 请求频率控制与反爬规避反爬是数据采集绕不开的话题。我在这个项目里采用了三层防护策略请求间隔每请求一页随机sleep(2~5秒)避免固定频率触发频率限制。这个用random.uniform(2, 5)实现。请求头伪装除了User-Agent随机切换外还需要带上Referer字段指向搜索页面因为Boss直聘的接口会校验Referer是否合法。异常重试请求失败时采用指数退避策略重试最多重试3次import requests import time import random headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36, Cookie: 你的Cookie, Referer: https://www.zhipin.com/web/geek/job?query数据分析师city100010000 } def fetch_page(url, retries3): for i in range(retries): try: resp requests.get(url, headersheaders, timeout10) if resp.status_code 200: return resp.json() elif resp.status_code 403: print(f被拒绝访问第{i1}次重试) time.sleep(5 * (i 1)) except Exception as e: print(f请求异常: {e}) time.sleep(3 * (i 1)) return None这里还有一条特别重要的经验只采集搜索结果的列表页数据不要点击进入岗位详情页更不要批量请求简历相关接口。详情页的反爬力度比列表页高一个量级而且从期末作业的角度来说列表页的字段已经足够支撑后续所有分析了。2.3 数据落盘与格式设计数据采集完成后我用Pandas直接转成DataFrame然后存成CSV文件。这里有个小细节salaryDesc字段是文本格式后续分析需要拆分成最低薪资和最高薪资所以我把原始文本单独留一份列方便清洗阶段做解析。import pandas as pd data_list [] # 循环请求多个页面解析jobList中的字段 # ... df pd.DataFrame(data_list) df.to_csv(./jobs_raw.csv, indexFalse, encodingutf-8-sig) print(f共采集 {len(df)} 条岗位数据)存成utf-8-sig编码是为了防止Excel打开时出现中文乱码这个坑很多人踩过我直接把解法放在这里了。3. 数据清洗与预处理3.1 薪资字段的拆分与量化原始数据里salaryDesc长这样“20-40K·15薪”或“25-50K·14薪”还有“200-300元/天”这种日薪形式的实习生岗位。清洗阶段第一步就是把混合格式拆出来。我的处理逻辑是写一个薪资解析函数import re import numpy as np def parse_salary(salary_str): 解析薪资文本返回(最低月薪万/月, 最高月薪万/月, 月薪系数) if not isinstance(salary_str, str): return np.nan, np.nan, np.nan # 提取数字范围 nums re.findall(r(\d\.?\d*), salary_str) if len(nums) 2: return np.nan, np.nan, np.nan min_salary float(nums[0]) max_salary float(nums[1]) # 判断单位K / 万 / 元每天 if 万 in salary_str: min_salary * 10000 max_salary * 10000 elif 元/天 in salary_str or 元 in salary_str: # 日薪按21.75个工作日折算成月薪 min_salary min_salary * 21.75 max_salary max_salary * 21.75 else: min_salary * 1000 max_salary * 1000 # 计算月薪系数15薪、14薪等 month_match re.search(r(\d)薪, salary_str) month_factor int(month_match.group(1)) / 12 if month_match else 1 return min_salary / 10000, max_salary / 10000, month_factor解析完成后再生成两个辅助列avg_salary平均月薪单位万元和year_salary年薪考虑月薪系数。后续所有薪资维度的分析都基于这两列。这里有个细节值得注意日薪的折算方式。我是按21.75个工作日折算的这是国家规定的月平均计薪天数。如果你按22天折数据会有一点偏差但影响不大关键是要在作业中说明折算规则体现你思考过这个问题的严谨性。3.2 重复值与缺失值处理采集下来的数据往往存在重复记录原因是同一岗位可能会在翻页时重复出现或者同一家公司多个招聘者在发同一个岗位。我的处理策略是完全重复行直接用drop_duplicates()删除同公司同岗位同薪资判定为近似重复保留第一条缺失字段jobDegree、jobExperience为空时直接删除该行这两个字段是后续分析的关键维度缺失无法补齐df df.drop_duplicates(subset[brandName, jobName, salaryDesc], keepfirst) df df.dropna(subset[jobDegree, jobExperience]) df.reset_index(dropTrue, inplaceTrue)清洗完之后要重新看一眼数据总量和字段完整性。如果清洗后数据量低于原始数据的60%就要考虑是不是采集环节出了漏数据的问题回去补采。3.3 文本类字段的规整化公司融资阶段brandStageName这个字段看起来是规范的实际会有“不需要融资”“已上市”“A轮”“500-999人”之类的描述清洗时要把公司规模这个数字范围摘出来单独存一列方便分析公司规模与薪资的关系。岗位名称也需要做模糊归类因为“数据分析师”“资深数据分析师”“数据分析专家”“BI数据分析师”本质上属于同一类岗位。我用str.contains()做关键词匹配归为“初级”“中级”“高级专家”三档这是后边分析经验要求和薪资关系的基础。4. 数据分析核心环节4.1 单维度分布分析数据清洗干净后先做单维度分析把数据的基本盘摸清楚。这个环节我通常会做四个维度的统计岗位数量TOP10城市用value_counts()看哪座城市的岗位需求最多。学历要求分布饼图展示“本科”“硕士”“大专”“不限”的占比这个结果通常能看出行业对学历的基本要求。经验要求分布Bar图展示“1-3年”“3-5年”“5-10年”“在校/应届”的岗位数量。薪资水平分布直方图展示avg_salary的分布形态。这里有个需要处理的点少数高薪岗位会把薪资拉到很右侧直方图的箱宽要适当调整或者用np.percentile截断掉极端值再画图。这些单维度分析的价值是帮助建立对数据集的整体感知也为后续交叉分析选好维度组合。4.2 多维交叉分析交叉分析是期末作业的加分项也是面试中能体现你分析能力的地方。我做了三组关键的交叉分析城市×平均薪资每个城市岗位的平均月薪排序能做出一张横向条形图结合城市岗位数量判断哪些城市“钱多机会多”哪些是“机会多但薪资一般”。经验要求×薪资这个分析最能说明问题。通常结果呈现明显的递增趋势但如果出现“1-3年经验组平均薪资高于3-5年组”就要去看数据样本量是否足够避免小样本导致误判。我在这个环节遇到过数据量不足100条的子集结论直接不可信最后把子集样本量低于50的类别做了合并处理。学历×薪资学历与薪资的关系分组求均值后画图。通常硕士学历的平均薪资会高于本科但差距幅度因城市而异这是可以展开论述的发现。交叉分析的结论一定要结合业务背景解读不能用简单的“谁高谁低”来总结。比如“北京数据分析师平均薪资15000元”这个结论要补充说明北京岗位中对3年以上经验要求的占比更高这是薪资拉高的结构性原因。4.3 岗位技能关键词提取招聘JD里的jobLabels字段包含了岗位技能标签用collections.Counter做词频统计能快速得出热门技能TOP10。这个分析可以帮助求职者知道当前市场最看重什么技能比如“SQL”“Python”“Excel”“Tableau”“机器学习”这些词的频次排名。进阶做法是对jobDescription做中文分词并生成词云这个过程需要引入jieba库。代码不长import jieba from collections import Counter text .join(df[jobLabels].dropna()) words jieba.lcut(text) words [w for w in words if len(w) 1 and w not in stopwords] result Counter(words).most_common(30)停用词表要手动补几个广告性质的词比如“五险一金”“弹性工作”“节日福利”这类词的频次会干扰分析结果剔除后关键词分布才更贴近实际技能需求。5. 可视化呈现与报告整合5.1 用PyECharts制作交互式图表Matplotlib适合快速出图验证数据但做期末大作业的展示效果PyECharts的交互能力明显更强图表可以悬浮显示数据、支持缩放、支持数据区域选择观感上比静态图高一个档次。我整理好分析结果后用PyECharts统一渲染from pyecharts.charts import Bar, Pie, Line, Map from pyecharts import options as opts city_salary df.groupby(cityName)[avg_salary].mean().sort_values(ascendingFalse) bar ( Bar(init_optsopts.InitOpts(width900px, height500px)) .add_xaxis(city_salary.index.tolist()[:10]) .add_yaxis(平均薪资(万/月), city_salary.values[:10].round(2).tolist()) .set_global_opts(title_optsopts.TitleOpts(title各城市数据分析师平均薪资TOP10), xaxis_optsopts.AxisOpts(axislabel_optsopts.LabelOpts(rotate30))) ) bar.render(./output/城市薪资对比.html)在这个环节有一个实用建议把生成的HTML文件按图表类型统一放在output文件夹里命名是“分析维度图表类型”这样在做期末答辩时找一个文件清晰明了也方便后续整合到网页大屏里。5.2 组合大屏与报告输出期末作业的最终产出通常是“数据分析报告(PDF/Word) 可交互HTML大屏 整理好的CSV数据”三件套。这个大作业项目的可视化大屏我用的是Flex布局做一个Dashboard页面把6张图表通过iframe标签嵌入到同一个HTML页面里实现联动的展示效果。大屏布局可以参考这个框架顶部项目标题 数据采集时间范围左侧岗位数量TOP10城市柱状图 学历要求占比环形图中部薪资分布直方图 薪资与经验交叉分析折线图右侧热门技能词云 公司规模与薪资关系散点图布局的核心原则是“左上角是最重要的信息右下角是次要信息”阅读者的视线是Z字型移动的。城市岗位分布和薪资概览放在左上方让老师一眼看到核心结论。5.3 报告撰写注意点期末大作业的报告部分我的经验是“重分析轻技术”不要大篇幅贴代码要让分析结论成为主角。每一张图表都必须配一段文字说明内容包括这张图看到了什么数据现象、为什么会有这个现象、这个现象反映出的行业规律是什么。比如学历与薪资分析那部分合适的写法是“根据样本数据显示硕士学历的数据分析师平均月薪为1.8万元较本科学历高出23%。这个薪资差距在一线城市尤为明显北京硕士平均薪资达到2.3万元。这表明在数据岗位中高学历仍然是获取薪资溢价的重要因子这既与企业校招时的学历门槛有关也与硕士群体更多进入金融、大厂等高薪行业有关。”这种写法既展示了数据分析能力也展示了业务理解力比单纯堆图表更容易拿高分。6. 常见问题与排查技巧实录6.1 爬虫阶段的高频问题问题1请求被403拦截。排查思路是先确认Cookie是否过期Boss直聘的Cookie有效期很短常常隔天就失效了。解决方式是重新在浏览器手动搜索一次复制最新Cookie替换。如果换了Cookie还是403就是请求频率太快触发了IP限流把sleep时间拉长到8秒以上等10分钟再继续。问题2返回数据量与实际不符。比如搜索“数据分析师”显示有300个岗位但只翻到3页就不再返回新数据。这通常是因为未登录状态下只能看到搜索结果的首页数据。解决办法是使用登录后的Cookie请求或者通过cityCode参数切换城市批量采集不同城市的数据来扩大数据量。问题3JSON解析报KeyError。Boss直聘会把某些字段放在嵌套结构里或者某个岗位压根没有该字段。稳妥的写法是用data.get(field, )替代data[field]避免单个脏数据导致整个解析流程崩溃。6.2 数据清洗与可视化阶段的问题清洗阶段最常见的坑是薪资单位不统一“15-20K”“1.5-2万”“200元/天”混在同一列必须通过函数一次性处理不能手动改。可视化阶段最常见的问题是中文显示成方块这是因为Matplotlib默认字体不包含中文字符。解决方式import matplotlib.pyplot as plt plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False如果用的不是Windows系统SimHei字体不存在要换成WenQuanYi Micro Hei或Arial Unicode MS。6.3 经验总结与避坑清单根据我自己做这个项目的经验和带学生的反馈整理几条关键建议数据量是分析可信度的基础。期末作业分析出的结论要有说服力至少需要有效样本在1000条以上。我在采集时通常会设置3个关键词数据分析师、数据分析、数据运营× 3个城市北京、上海、广州交叉采集一组数据下来差不多有2500到3000条清洗完剩余2000条出头分析结论就比较扎实了。数据合规不可忽视。爬虫采集数据务必要控制频率、只采集公开信息、不绕过登录机制获取非公开数据。这一点在期末答辩时老师会关注也是从业者必须守住的原则。我个人建议在报告中写清楚“只采集了公开页面的列表数据采集频率保持在合理范围严格遵守目标网站的访问协议”既体现了你的合规意识也避免了一些不必要的麻烦。代码规范要一致。很多人写期末项目时函数命名一会儿用下划线一会儿用驼峰注释也是想到哪写到哪。我强烈建议统一使用snake_case命名风格关键函数加一行文档字符串说明入参和返回值。这份代码大概率会出现在你的面试项目介绍中面试官对代码质量的关注度甚至比功能本身还高。个人体会是这个项目的工作量非常适合期末大作业的时间预算——数据采集半天、清洗和数据分析两天、可视化和报告两天一周之内能完成得比较从容。而且选题自带“数据和招聘”两个热点分析出来的结论无论是对自己未来的求职方向还是对班级同学做就业参考都很有实际价值。如果打算用这个项目去找工作做完之后建议再把分析维度扩展一层比如加入“行业对公司规模与薪资的影响”“不同岗位方向数据产品、数据分析、数据仓库的薪资对比”这些更深层次的分析面试时能有更多可以聊的细节。本文还有配套的精品资源点击获取
返回列表