资讯动态

Python爬虫+数据分析实战:从招聘网站获取就业数据,解析城市薪资与学历要求

发布时间:2026/9/7 9:22:03 来源:尧图企业网站定制
简介这是一份基于Python爬虫与数据分析的完整实战项目包面向想掌握Scrapy框架、数据清洗及可视化全流程的初学者或课程设计者。项目以重庆大学毕业生就业信息网为数据源覆盖爬虫构建、数据提取、Pandas/NumPy清洗统计以及Matplotlib绘制饼图、折线图等图表能够帮助读者快速复现从网络抓取到就业去向分布、薪酬对比、宣讲会热度的分析链路。压缩包共23个文件以16个Python脚本为主配套3张可视化结果PNG、依赖说明txt、Scrapy配置cfg及README文档整体仅116KB轻量易部署。该资源已被634人学习下载内容包含完整项目源码、统计脚本和结果图适合直接参考或二次开发也可作为毕业设计、数据采集课程的实用范本。1. 项目背景与技术选型为什么用Python做就业数据爬取与分析1.1 毕业生就业数据从哪来、能解决什么问题每年毕业季“就业”都是绕不开的话题。但如果你手上没有真实数据聊薪资、聊行业趋势基本靠感觉。这个项目的出发点很简单把招聘网站上毕业生相关的岗位数据批量抓下来用Python做一轮完整的“采集—清洗—分析—可视化”用数据回答几个最实际的问题——哪些城市对毕业生需求最大、哪些岗位薪资中位数最高、学历和经验要求到底卡在哪一档。数据源的选取上我优先考虑的是公开招聘网站的搜索页比如智联招聘、BOSS直聘这类平台。它们有公开的职位搜索入口数据量大、字段丰富岗位名称、公司、薪资、学历要求、工作经验、城市、发布时间等非常适合做统计。另一个优势是这些网站的前端结构相对稳定短时期内不会大刀阔斧改版适合跑一轮完整的爬虫项目。这个项目的价值在于它不只是一次爬虫练习而是一条完整的“数据流水线”。爬虫只占三分之一的工作量后面还有清洗、归一化、聚合分析和可视化呈现。如果你正在学Python数据分析或者准备做毕设、求职作品集这个项目能一次性练到requests、pandas、matplotlib、pyecharts这几个核心库比零散刷教程有效得多。1.2 技术栈与选型逻辑requests pandas echarts组合技术选型不是越新越好而是越稳越好。我的选择是requests BeautifulSoup数据量不大、不需要登录态的场景用这两个库最省事。requests处理HTTP请求BeautifulSoup解析HTML结构。相比Scrapy少了学习成本和框架配置适合快速验证想法。pandas清洗和聚合的绝对主力。DataFrame做筛选、去重、分组统计、透视表都是几行代码的事。matplotlib pyechartsmatplotlib适合快速出静态图适合写论文那种严肃风格pyecharts生成的是交互式HTML图表鼠标悬停能看到数值适合做展示和汇报。SQLite如果抓上万条数据直接存CSV后面清洗时会很痛苦。先存进SQLite用SQL做初步筛选再导出到pandas做精细处理流程更可控。这里有个经验千万不要一上来就追求分布式爬虫或Scrapy Redis那种重型架构。个人项目的数据量级通常在几千到几万条单线程 适当延时完全够用。架构太重反而会分散精力让你陷进“环境配置”而不是“数据分析”本身。2. 数据采集从URL分析到字段设计爬虫的完整拆解2.1 锁定目标页面结构设计爬取字段以智联招聘的搜索页为例URL里一般包含关键词、城市和页码参数。比如搜索“应届毕业生”岗位请求参数会带着kw应届毕业生和cityCode。第一步要做的不是盲目写代码而是打开浏览器开发者工具进入Network面板观察页面加载时实际发出了哪些请求。你会发现职位列表的数据往往是接口直接返回JSON而不是写死在HTML里。这时候用requests模拟请求拿到JSON解析效率比BeautifulSoup解析HTML高得多。如果页面是服务端渲染的HTML里直接有数据那就用BeautifulSoup定位职位卡片节点。我实际用的数据结构如下核心字段字段说明举例job_title岗位名称Java开发工程师company_name公司名称XX科技有限公司salary_min薪资下限K/月8salary_max薪资上限K/月15city工作城市北京education学历要求本科experience经验要求经验不限industry所属行业互联网/电子商务publish_time发布时间2025-06-10薪资字段我拆成两个数值列来存后面分析时可以直接算中位数和平均值比存“8-15K”这种字符串要灵活得多。这一步属于“设计先行”不要在数据落地之后才想着拆分。2.2 请求头、翻页逻辑与反爬应对写爬虫最容易遇到的坑就是请求头不全导致被403拒绝。浏览器在正常访问时会携带User-Agent、Referer、Accept-Language等请求头用requests裸请求很容易被服务器的风控识别。我的做法是构造一个完整的请求头字典headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36, Referer: https://www.zhaopin.com/, Accept: application/json, text/plain, */*, Accept-Language: zh-CN,zh;q0.9,en;q0.8, }翻页逻辑上多数招聘网站的页码参数是pageIndex或pageNum从1开始递增。但这里有个隐藏坑页面显示的总页数和实际接口可返回的最大页数是两回事。很多网站为了防止抓取接口层会把最大可访问页数限制在10页或20页以内。设计爬虫时应该以“接口实际返回的数据条数”作为循环终止条件而不是以页面显示的页码数。每抓完一页加一个1-2秒的随机延时避免短时间内请求频率过快。如果遇到需要登录才能查看更多数据的情况优先考虑两个方向一是检查是否存在免登录的移动端接口如m站、APP的H5页面这类接口往往鉴权较弱二是给请求加上Cookie从浏览器复制登录后的Cookie即可。对于验证码和滑块这种强验证不建议死磕破解直接换个数据源更实际。3. 数据清洗与预处理分析结果准不准全看这步3.1 去重、空值与类型转换爬下来的数据远远达不到“拿来就能分析”的标准。最常见的三类脏数据是完全重复的记录、薪资字段缺失或格式混乱、城市字段取名不统一比如“北京”和“北京市”并存。清洗这一步的核心代码如下import pandas as pd df pd.read_csv(jobs.csv) # 去除完全重复的记录 df df.drop_duplicates(subset[job_title, company_name, city, salary_min, salary_max]) # 过滤掉关键字段缺失的行 df df.dropna(subset[salary_min, salary_max, city]) # 统一城市名称去掉市后缀 df[city] df[city].str.replace(市, )这里要重点提醒一个细节薪资字段务必先转成数值类型再做运算。如果你的薪资字段是“8-15K”这种字符串用pandas读取后会被识别为object类型直接求均值会报错。所以我建议在爬虫阶段就分开存储salary_min和salary_max两个数值列。如果你的原始数据已经是字符串格式可以用str.extract把数字提取出来# 从 8-15K 中提取两个数值 df[salary_min] df[salary].str.extract(r(\d)-(\d))[0].astype(int) df[salary_max] df[salary].str.extract(r(\d)-(\d))[1].astype(int)3.2 构造分析字段把文本变成可统计的维度原始数据里有“学历要求”“经验要求”这种分类字段但它们往往是不标准的比如“本科”、“统招本科”、“本科及以上”同时存在。为了让后续聚合统计有意义需要做归一化映射edu_map { 学历不限: 不限, 中专/中技: 专科及以下, 大专: 专科及以下, 大专及以上: 专科及以下, 本科: 本科, 统招本科: 本科, 本科及以上: 本科, 硕士: 硕士及以上, 硕士及以上: 硕士及以上, } df[edu_level] df[education].map(edu_map)经验字段的处理同样如此——“经验不限”“应届生”“1年以内”都可以归为“应届/1年内”“1-3年”归为“1-3年”“3-5年”归为“3-5年”“5年以上”归为“5年”。归一化做完之后用df.groupby()聚合就非常顺手了。另外我建议生成一个mid_salary字段薪资中位数 (下限上限)/2后续画箱线图、算城市平均薪资时可以直接用这个字段比分别看上下限更直观。这一小步能让后续分析代码简单很多。4. 数据分析维度与可视化从图表到结论的完整链路4.1 四个分析维度城市、行业、学历、经验拿到干净数据之后我确定了四个核心分析维度每个维度回答一个具体问题维度一城市供需分布。统计每个城市的岗位发布数量画柱状图直观看出哪些城市对毕业生的需求量大。通常北上广深杭是TOP5但二线城市的数据会给你惊喜比如成都、武汉、南京的毕业生岗位数量逐年增长。维度二薪资水平对比。按城市分组计算mid_salary的中位数用箱线图展示薪资分布。注意这里要用中位数而不是平均值因为少数高薪岗位会把平均值拉高中位数更能反映普通毕业生能拿到的薪资水平。维度三学历门槛分析。统计各学历层次对应的岗位数量占比用饼图或环形图展示。结合薪资数据做透视表看看学历提升到底能带来多少薪资溢价。维度四经验要求分布。统计“经验不限”类岗位在所有岗位中的占比这是毕业生最关心的数据。再结合岗位名称做分词生成热门岗位词云看看市场上到底缺什么人。4.2 可视化图表的选择与实现要点图表不能为了炫技而做每一张图都要对应一个具体的结论或洞察。以城市薪资分析为例import matplotlib.pyplot as plt # 按城市求薪资中位数 city_salary df.groupby(city)[mid_salary].median().sort_values(ascendingFalse).head(10) plt.figure(figsize(12, 6)) city_salary.plot(kindbar, color#4C72B0) plt.title(各城市毕业生岗位薪资中位数 TOP10 (K/月)) plt.xlabel(城市) plt.ylabel(薪资中位数) plt.xticks(rotation45) plt.tight_layout() plt.savefig(city_salary.png, dpi300)这里有个细节matplotlib默认字体不包含中文字符直接画图会出现方块乱码。必须显式指定字体plt.rcParams[font.sans-serif] [SimHei] # 或用 Microsoft YaHei plt.rcParams[axes.unicode_minus] False # 解决负号显示异常如果做交互式展示我强烈推荐pyecharts。它生成的HTML图表自带悬浮提示、图例控制和缩放功能汇报时打开浏览器直接看效果比静态图片强得多。比如制作一个城市岗位需求分布的地图热力图pyecharts的Map类型几行代码就能搞定。做可视化大屏时pyecharts的Tab、Grid组件可以把多个图表拼在同一个页面里滚动切换效果不输商业BI工具。5. 从数据到报告如何把图表转化成可用结论5.1 数据交叉分析实践单维度分析只能描述现象交叉分析才能发现规律。我建议大家至少做两个交叉分析交叉分析一学历 vs 薪资。用pivot_table生成透视表行是学历等级列是城市等级一线/新一线/二线值是薪资中位数。pivot pd.pivot_table( df, valuesmid_salary, indexedu_level, columnscity_level, aggfuncmedian ) print(pivot)这个透视表能同时回答两个问题一线城市是否在每个学历层都给出更高薪资学历溢价在不同线城市的表现差异有多大我实测的结论是一线城市中“本科 vs 硕士”的薪资差距约12%左右而在新一线城市差距缩小到8%以下。这类洞察才是数据分析项目的灵魂。交叉分析二行业热度 vs 专业背景。如果数据里有行业字段可以把行业分成互联网、金融、制造业、教育、医疗等类别再按岗位名称提取关键词统计不同行业的岗位技能需求频率。比如互联网行业“Java”“Python”“前端”出现频次极高制造业则是“机械设计”“自动化”频次高。5.2 把分析结果整理成叙事线图表做完最后要写成一篇有逻辑的分析报告。我的报告结构通常是先说明数据来源和数据量增强可信度然后是一个全局概览比如总岗位数、覆盖城市数、平均薪资接着按“城市—行业—学历—经验”四个维度逐层展开每个小节给结论再配图表最后做交叉分析给出一段有洞察的总结段这一步很多人会忽略但它恰恰是面试官或导师最看重的部分——数据本身没有价值从数据中得出的结论才值钱。6. 常见问题与避坑实录6.1 爬虫阶段的高频问题问题1请求返回403或验证码页面。排查思路先检查请求头是否完整特别是User-Agent和Referer再检查请求频率如果已经连续抓取多页建议暂停30-60秒再继续。If还是不行检查IP是否被封最简单的方法是换一个网络环境比如手机热点再跑一次。问题2翻页抓取后数据量没有增长。排查思路很多招聘网站的搜索结果接口日访问超过一定次数后虽然返回200状态码但JSON数据里是空数组或错误提示。建议每次请求后打印返回数据的长度及时发现异常并把该页数据重新抓取一次。问题3页面改版后旧选择器失效。排查思路爬虫代码里尽量用稳定的属性选择器如style="width:16px;margin-left:4px;vertical-align:text-bottom;cursor:text;" />

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价