简介这是一份面向Python初学者与数据分析入门者的综合实战资料围绕拉勾网Python职位信息展开覆盖网络爬虫、数据清洗、统计分析与可视化呈现的完整链路适合用作课程大作业、毕业设计选题或自学练手项目。压缩包共22个文件约330KB包含12张png可视化图表、8个csv数据文件、1个py爬虫脚本和1份md说明文档图表与数据按上海、深圳、福州等城市分类便于对照分析。目前已有5226人学习下载热度较高。通过这份资料读者可以拿到可直接运行的爬虫脚本、多城市职位原始数据与清洗结果以及公司分布、学历要求、薪资水平等维度的成图同时理解requests请求、Pandas处理、Matplotlib与Seaborn绘图、异常处理及反爬应对等关键知识点快速搭建属于自己的招聘市场分析小项目。1. 从一份拉勾 Python 岗位数据包说起它到底能跑出什么结果如果你手头正好有一份Python爬虫数据可视化分析大作业.zip打开后看到lagou_spider.py、lagou.csv、lagou_finall.csv还有上海、深圳、福州三地的薪资、学历、公司分布 PNG那这基本就是一个已经跑完的招聘数据采集与分析闭环。它解决的不是怎么装 Python这种入门问题而是把 requests 抓取、pandas 清洗、matplotlib 出图串成一条能复现的链路。适合正在做大作业、课程设计或者想拿真实岗位数据练手数据清洗与可视化的人。下面我按能跑起来 → 看懂每步 → 避开坑的顺序拆一遍。2. 拆开压缩包先看结构文件命名里藏着整条数据流2.1 从文件名反推处理链路拿到一个别人打包好的项目我第一件事不是急着运行而是先看文件命名规律。这份资源里的文件名其实已经把处理流程写清楚了文件作用所处阶段lagou_spider.py爬虫主脚本数据采集lagou.csv原始抓取结果采集输出lagou_finall.csv清洗合并后的总表数据清洗上海_python_lagou.csv按城市切分的原始数据分城市采集上海_python_lagou_finall.csv分城市清洗结果分城市清洗上海_python_薪资.png薪资分布图可视化输出上海_python_学历要求.png学历要求分布可视化输出上海_python_公司分布.png公司类型分布可视化输出从命名能看出作者是按城市 关键词 阶段三层来组织文件的。上海、深圳、福州三个城市各有一套原始 CSV、清洗后 CSV 和三张图最后再汇总成lagou_finall.csv。这种结构的好处是每个城市可以独立跑、独立验证出问题不会污染全局数据。2.2 环境依赖与目录约定在动手之前先把依赖装齐。这份项目用到的库不算多但版本差异会直接影响爬取和绘图结果# 建议在虚拟环境里操作避免污染全局 python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate # 核心依赖 pip install requests pandas matplotlib seaborn numpy pip install beautifulsoup4 lxml这里有几个点值得说清楚。requests负责发 HTTP 请求拿页面beautifulsoup4配合lxml解析 HTMLpandas做数据清洗和 CSV 读写matplotlib和seaborn负责出图。numpy虽然不直接调用但 pandas 的很多统计操作底层依赖它装上省心。提示如果你的 Python 是 3.8 及以上上面这些库直接 pip 装最新版基本没问题。但 seaborn 在部分老版本 matplotlib 上会报样式冲突遇到就把 matplotlib 升到 3.5 以上。目录上我一般会把脚本、数据、图片分开放但这份资源是平铺的。平铺的好处是路径简单pd.read_csv(lagou.csv)直接能跑坏处是文件一多就乱。如果你要在此基础上扩展建议改成data/、scripts/、output/三个目录后面维护会轻松很多。2.3 先跑通再优化最小验证路径不要一上来就改代码。先确认原始数据能读、图能出这是判断资源可用性的最快方式import pandas as pd import matplotlib.pyplot as plt # 先读一份分城市数据确认编码和列名 df pd.read_csv(上海_python_lagou_finall.csv, encodingutf-8) print(df.columns.tolist()) print(df.shape) print(df.head(3))这段代码的作用是探路。encodingutf-8是常见编码但如果报UnicodeDecodeError大概率是gbk或utf-8-sig换成这两个再试。df.columns.tolist()打印列名你能立刻知道薪资、学历、公司这些字段叫什么后面画图才不会因为列名对不上而翻车。df.shape看数据量如果只有几行说明爬取阶段就没抓全得回头查爬虫。3. 爬虫脚本怎么读requests 抓取与字段提取的关键参数3.1 请求构造与反爬基础处理lagou_spider.py的核心逻辑无非是构造请求 → 拿响应 → 解析 → 存字段。但招聘网站对请求头很敏感直接裸奔大概率拿不到数据。常见做法是带上 User-Agent 和 Refererimport requests import time import random 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.lagou.com/, Accept-Language: zh-CN,zh;q0.9, } def fetch_page(url, retry3): for i in range(retry): try: resp requests.get(url, headersheaders, timeout10) if resp.status_code 200: return resp.text # 状态码异常时退避重试 time.sleep(random.uniform(2, 5)) except requests.RequestException as e: print(f第{i1}次请求失败: {e}) time.sleep(random.uniform(3, 6)) return Noneheaders里 User-Agent 伪装成正常浏览器Referer 告诉服务器请求来源。fetch_page做了三件事设置超时防止卡死、状态码非 200 时退避重试、捕获网络异常。random.uniform(2, 5)是随机延迟比固定time.sleep(2)更不容易被识别为机器行为。retry3是重试次数一般三次拿不到就说明这个 URL 或当前策略有问题继续重试意义不大。3.2 字段提取与数据落盘拿到 HTML 后用 BeautifulSoup 定位职位卡片逐条提取字段。不同时期页面结构会变所以选择器要以实际页面为准下面给的是常见结构from bs4 import BeautifulSoup import csv def parse_jobs(html): soup BeautifulSoup(html, lxml) rows [] # 职位列表通常在一个统一的容器里逐条遍历 for item in soup.select(.con_list_item): job { 职位名称: item.select_one(.position_link).get_text(stripTrue) if item.select_one(.position_link) else , 公司: item.select_one(.company_name).get_text(stripTrue) if item.select_one(.company_name) else , 薪资: item.select_one(.money).get_text(stripTrue) if item.select_one(.money) else , 城市: item.select_one(.add).get_text(stripTrue) if item.select_one(.add) else , 学历: item.select_one(.li_b_l).get_text(stripTrue) if item.select_one(.li_b_l) else , } rows.append(job) return rows def save_csv(rows, path): if not rows: print(无数据可写) return with open(path, w, newline, encodingutf-8-sig) as f: writer csv.DictWriter(f, fieldnamesrows[0].keys()) writer.writeheader() writer.writerows(rows)parse_jobs里每个字段都做了空值判断这是血泪经验——页面里总有几条缺薪资或缺学历的记录不判断就会AttributeError直接崩。save_csv用utf-8-sig编码这样 Excel 打开不会乱码比纯utf-8更省事。newline是 Windows 下防止多出空行的标准写法。3.3 分城市采集的参数差异资源里上海、深圳、福州各有一套数据说明脚本支持按城市参数化。常见做法是把城市名和对应的 URL 拼在一起循环采集cities [上海, 深圳, 福州] base_url https://www.lagou.com/zhaopin/Python/{}/ for city in cities: # 实际 URL 需按网站当前规则调整这里示意参数化思路 url base_url.format(city) html fetch_page(url) if html: rows parse_jobs(html) save_csv(rows, f{city}_python_lagou.csv) print(f{city} 采集完成共 {len(rows)} 条) time.sleep(random.uniform(5, 10)) # 城市之间拉长间隔城市之间sleep拉到 5 到 10 秒是因为连续快速请求不同城市页面更容易触发限制。f{city}_python_lagou.csv的命名和资源里的文件名对上了说明作者就是这么组织的。如果你只关心一个城市把cities改成单元素列表即可不用动其他逻辑。4. 数据清洗与可视化从 CSV 到三张图的完整操作4.1 薪资字段清洗把15k-25k变成可计算的数字原始薪资是字符串直接画图没有意义。必须先拆成最低和最高两个数值列import pandas as pd import re df pd.read_csv(上海_python_lagou_finall.csv, encodingutf-8) def parse_salary(s): if pd.isna(s): return pd.Series([None, None]) # 匹配 15k-25k、15-25K、15k以上 等常见格式 nums re.findall(r(\d), str(s).lower()) if len(nums) 2: return pd.Series([int(nums[0]), int(nums[1])]) elif len(nums) 1: return pd.Series([int(nums[0]), int(nums[0])]) return pd.Series([None, None]) df[[薪资下限, 薪资上限]] df[薪资].apply(parse_salary) df[平均薪资] (df[薪资下限] df[薪资上限]) / 2 df df.dropna(subset[平均薪资]) # 丢掉无法解析的行re.findall(r(\d), ...)把所有数字抠出来两个就是区间一个就当作固定值。apply(parse_salary)返回的是 Series所以用df[[薪资下限, 薪资上限]] ...一次接两列。dropna把解析失败的记录去掉避免后面统计被 NaN 干扰。这一步做完薪资才真正变成能算平均值、画分布图的数据。4.2 学历与公司分布统计学历和公司类型是分类字段统计逻辑简单但要注意去重和排序# 学历分布 edu_counts df[学历].value_counts() # 公司分布取前 10 避免图太挤 company_counts df[公司].value_counts().head(10) print(edu_counts) print(company_counts)value_counts()默认按数量降序直接就能拿去画条形图。公司取前 10 是因为招聘数据里公司名很分散全画出来横坐标会密到看不清——这也是热搜里python画图横坐标太密集的典型场景。取 Top 10 既保留主要信息又让图可读。4.3 三张图的绘制与保存资源里每个城市都有薪资、学历、公司三张图下面用 seaborn 统一风格import matplotlib.pyplot as plt import seaborn as sns plt.rcParams[font.sans-serif] [SimHei] # 中文显示 plt.rcParams[axes.unicode_minus] False # 薪资分布直方图 plt.figure(figsize(8, 5)) sns.histplot(df[平均薪资], bins15, kdeTrue) plt.title(上海 Python 岗位薪资分布) plt.xlabel(平均薪资 (k)) plt.ylabel(岗位数量) plt.tight_layout() plt.savefig(上海_python_薪资.png, dpi150) plt.close() # 学历要求条形图 plt.figure(figsize(8, 5)) sns.barplot(xedu_counts.index, yedu_counts.values) plt.title(上海 Python 岗位学历要求) plt.xticks(rotation30) plt.tight_layout() plt.savefig(上海_python_学历要求.png, dpi150) plt.close()SimHei是 Windows 自带中文字体Linux 或 Mac 上可能没有换成Arial Unicode MS或WenQuanYi Micro Hei。axes.unicode_minus False解决负号显示成方块的问题。dpi150让保存的图清晰度够用又不至于文件太大。plt.close()很重要不关的话循环画多个城市时会内存堆积。注意如果SimHei报字体找不到图里中文会全变方块。这不是代码错是环境缺字体换一个系统里有的中文字体名即可。5. 避坑与排查这份资源最容易翻车的五个地方5.1 页面结构变了选择器全部失效现象脚本能跑但parse_jobs返回空列表CSV 里一条数据都没有。原因招聘网站前端改版.con_list_item、.position_link这些 class 名已经不存在。解决打开目标页面F12 看实际 DOM 结构把选择器换成当前有效的。这类项目最大的不确定性就在这选择器不是一劳永逸的。5.2 请求被限制返回空页面或验证页现象resp.status_code是 200但resp.text里没有职位数据而是一段验证提示。原因请求频率过高或请求头不完整被识别为异常流量。解决补全 headers拉大sleep间隔必要时降低单次采集量。不要试图用极端高频去压只会更快被封。5.3 薪资解析出负数或异常值现象平均薪资里出现 0 或者几百这种明显不合理的数。原因薪资字段里混入了薪资面议或15k以上这类非标准格式正则抠出的数字不对。解决在parse_salary里加范围过滤比如低于 1k 或高于 200k 的直接置为 None再dropna。5.4 CSV 用 Excel 打开乱码现象pandas 读没问题Excel 打开中文全是乱码。原因保存时用了纯utf-8Excel 默认按 GBK 解析。解决保存时统一用encodingutf-8-sig这个 BOM 头能让 Excel 正确识别编码。5.5 画图时中文字体缺失现象图能出但标题和坐标轴中文全是方块。原因当前环境没有SimHei字体或 matplotlib 没找到。解决先import matplotlib.font_manager查可用字体选一个支持中文的设进去。Linux 服务器上通常需要手动装中文字体包。6. 进阶玩法把三城数据合并做横向对比跑通单城市之后最有价值的扩展是把上海、深圳、福州三份_finall.csv合并做城市间薪资对比。这一步能直接产出比单城图更有说服力的结论import pandas as pd import matplotlib.pyplot as plt import seaborn as sns cities [上海, 深圳, 福州] frames [] for city in cities: tmp pd.read_csv(f{city}_python_lagou_finall.csv, encodingutf-8) tmp[城市] city frames.append(tmp) all_df pd.concat(frames, ignore_indexTrue) # 各城市平均薪资对比 city_salary all_df.groupby(城市)[平均薪资].mean().sort_values(ascendingFalse) print(city_salary) plt.figure(figsize(8, 5)) sns.barplot(xcity_salary.index, ycity_salary.values) plt.title(三城 Python 岗位平均薪资对比) plt.ylabel(平均薪资 (k)) plt.tight_layout() plt.savefig(三城薪资对比.png, dpi150) plt.close()pd.concat(frames, ignore_indexTrue)把三份数据纵向堆叠ignore_index重置索引避免重复。groupby(城市)[平均薪资].mean()一行算出各城均值sort_values让柱子从高到低排。这个对比图比单城分布图更能支撑哪个城市 Python 岗位更值钱的判断。再进一步可以做薪资与学历的交叉分析# 不同学历在各城市的薪资表现 pivot all_df.pivot_table( values平均薪资, index学历, columns城市, aggfuncmean ) print(pivot.round(1))pivot_table把学历做行、城市做列、平均薪资做值一张表就能看出本科在上海和本科在福州差多少。round(1)保留一位小数输出更干净。这种交叉表在写大作业报告时特别有用比单纯堆图更有分析深度。我自己的习惯是每次拿到一份别人打包的数据项目先不改代码而是按读数据 → 跑通图 → 再动爬虫的顺序走一遍。因为爬虫受外部影响最大而数据和绘图是纯本地的先确认本地链路没问题再去排查网络环节能省掉大量来回折腾的时间。这份资源的价值不在于代码多复杂而在于它把采集、清洗、可视化三个环节的真实产物都留下来了你可以对着 CSV 和 PNG 反推每一步做了什么这比只看脚本更容易理解整条链路。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?