尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

Python数据分析大作业实战:前程无忧岗位爬取、清洗与可视化

发布时间:2026/9/26 8:36:48

资讯中心
01
ARTICLE

Python数据分析大作业实战:前程无忧岗位爬取、清洗与可视化

Python数据分析大作业实战:前程无忧岗位爬取、清洗与可视化
简介面向计算机相关专业正在完成期末大作业或毕业设计的学生这份Python数据分析可视化项目以“前程无忧Python岗位信息”为真实业务对象完整展现了页面爬取、数据清洗、指标提取到可视化呈现的全流程兼具课程设计与实战练习双重用途。项目由导师指导并认可源码经过本地编译和严格调试评审得分98分附带的DOCX项目文档详细记录了数据字段含义、处理思路、分析结论并配合可视化截图说明能有效支撑答辩汇报与毕业设计写作。压缩包共17个文件约14.94MB核心部分包括4个Python脚本分别负责数据爬取、格式转换、统计分析、薪资计算、3个CSV数据表、2个SQL数据库文件、5张PNG可视化结果图如不同学历要求岗位数量分布、各城市岗位数量、真实月薪箱型图、福利待遇关键词词云等另有msyh.ttc字体等辅助资源目录结构明确便于按模块逐项对照学习也方便二次修改和扩展。目前已有283人学习使用项目难度适中且结果完整适合希望系统掌握爬虫与数据分析可视化全流程、并快速生成期末项目成果的学习者。1. 拆解“前程无忧Python岗位分析”大作业从爬虫到箱型图的一整条链路期末交 Python 数据分析可视化大作业前几天最让人头疼的往往不是算法没思路而是链路断在半路爬虫还没跑两页就反爬、CSV 用 Excel 打开全乱码、薪资字段是“1-1.5万/月”这种字符串没法参与计算最后画图时中文全变方块字。这份“前程无忧 Python 岗位信息爬取和分析”项目恰好把这条链路完整走了一遍爬岗位数据、清洗去重、落 SQL 库按学历/城市/工作经验做统计算出“相对真实月薪”并输出词云、柱状图和箱型图还附带一份能直接改写的项目文档报告。资源难度定位在期末大作业和毕设实战之间适合正在赶 Python 课程设计的学生也适合想拿真实招聘数据练图表的人。下面按源码文件逐一拆解讲清楚每个脚本的作用、参数和踩过的坑。2. 数据从哪来一个爬虫脚本加两个 CSV、两个 SQL第一道工序全在这里项目里真正跑数据分析的脚本只有两个其余脚本名字里都带 transition——过渡转换。python.csv 是初始采集结果newPython.csv 和 new_python.csv 是逐级清洗后的版本analyse.sql 和 newanalyse.sql 则是原始数据落库和清洗结果落库的建表脚本。也就是说这份大作业的数据准备阶段分两层第一层把网页变成 CSV第二层把 CSV 变成能直接进 DataFrame 的干净表格。很多同学拿到手习惯直接跑 two-analyse.py结果报错说找不到列名多半就是跳过了清洗层。这里的关键认知是分析脚本并不关心数据是怎么来的只关心 CSV 里那几列的格式对不对。2.1 one-transition.py请求、解析与字段映射前程无忧的页面结构这些年改过好几版经典列表页用的是div classel包裹单条岗位信息字段包括岗位标题、公司名、城市、学历要求、工作经验、薪资范围和福利标签。one-transition.py 做的事情就是用 requests 带上一组常规请求头去抓列表页然后用 lxml 解析出这些字段逐条追加到 CSV 里。注意一个细节前程无忧的页面编码是 GBK如果不手动指定 response.encoding解析出来的中文就是乱码。常见的写法是直接从响应头里拿或者硬编码成 “gbk”后者更稳。import requests from lxml import etree import csv headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36, Referer: https://www.51job.com/ } def fetch_page(url): resp requests.get(url, headersheaders, timeout10) resp.encoding gbk return resp.text def parse_job_list(html): tree etree.HTML(html) items tree.xpath(//div[contains(class,joblist)]//div[contains(class,el)]) rows [] for item in items: title item.xpath(.//span[contains(class,jname)]/text()) company item.xpath(.//span[contains(class,cname)]/text()) city item.xpath(.//span[contains(class,lname)]/text()) salary item.xpath(.//span[contains(class,sal)]/text()) rows.append([title[0] if title else , company[0] if company else , city[0] if city else , salary[0] if salary else ]) return rows这段代码的核心在于把解析目标和结果字段一一对应。requests 部分最容易被忽略的是 Referer前程无忧对直接访问列表页的请求做过基础过滤带上 Referer 后翻车概率会明显下降。lxml 的 xpath 路径取决于页面结构如果你本地复现时发现解析出来全是空列表优先检查 class 名是否因为页面改版变了不要急着怀疑脚本本身。CSV 写入时我一般会用encodingutf-8-sig这是为了让 Excel 打开不乱码下面避坑章节会展开说。这个脚本跑完生成的 python.csv行数基本对应爬到的岗位条数但这时数据还很粗同一家公司可能重复发多个岗位、城市字段带着“深圳-福田区”这种后缀、薪资是“面议”或区间字符串都不能直接做分析。2.2 four-transition.py清洗、归一化与数据库落库four-transition.py 就是把 python.csv 加工成 new_python.csv 的关键脚本。它做的事情可以归纳成四步第一步按“岗位标题 公司 城市”三列去重第二步处理城市字段用 split(-)[0] 把“深圳-福田区”这种拆出地级市第三步构建学历归一字典把“本科及同等学历”“学历不限”这类自由文本统一成“本科”“不限”第四步对薪资字段做初步判断把“面议”单独标记避免后续分析脚本误当成数字解析。以下是我常用的清洗片段import pandas as pd df pd.read_csv(python.csv, encodingutf-8-sig) df df.drop_duplicates(subset[job_title, company, city]) edu_map {本科及以上: 本科, 本科及同等学历: 本科, 学历不限: 不限, 大专及以上: 大专, 硕士及以上: 硕士, 博士及以上: 博士} df[education] df[education].map(lambda x: edu_map.get(str(x).strip(), x)) df[city] df[city].str.split(-).str[0] df df[df[salary] ! 面议].reset_index(dropTrue) df.to_csv(new_python.csv, indexFalse, encodingutf-8-sig)清洗的逻辑是“能合并的合并不能合并的丢弃”。edu_map 里用.get(x, x)这种写法遇到地图里没有的文本就保留原值后面分析脚本里能看到真实分布方便回头补映射关系。df[df[salary] ! 面议]这一步会丢掉一部分样本这在大作业报告里要如实说明不能假装所有岗位都有薪资区间。数据库这块项目里给了 analyse.sql 和 newanalyse.sql。前者建的是原始爬取表字段就是 CSV 里的原始列后者建的是清洗后的表多了一个 real_monthly_salary 数值列。如果只做可视化完全可以跳过 MySQL但文档报告里如果需要贴 SQL 分组统计截图就得把清洗后的 CSV 导入数据库。导入命令不算复杂mysql -u root -p new_python_db newanalyse.sql注意 SQL 文件里的建表语句通常带着 DROP TABLE IF EXISTS多次导入不会重复建表。这层设计比较贴合期末大作业的要求——既能体现爬虫和清洗能力又能展示 SQL 查询功底。项目里还带着 .gitignore说明作者是用 Git 管理这个项目的下载后直接用 IDE 打开也不会有本地缓存文件混进来。3. 分析脚本two-analyse.py 算分布three-analyse-money.py 算薪资统计口径先对齐分析层只有两个脚本但功能分工很明确。two-analyse.py 处理的是“量”的问题不同学历要求下岗位数量是多少各城市地区的岗位数量怎么分布three-analyse-money.py 处理的是“价”的问题不同学历、不同工作经验的人相对真实月薪大概落在什么区间。输入是清洗后的 new_python.csv 或 newanalyse.sql 导出的表输出是可视化截图目录里的那几张 PNG 配图。跑这两个脚本之前最值得先做的一件事是打印 DataFrame 的列名和 dtype确认 education、city、salary 这三列已经被前面的转换脚本处理成规整格式。3.1 two-analyse.py学历分布与城市岗位数量统计岗位数量的统计本质就是 groupby size但实际写起来有几个小坑。学历列虽然已经归一但 DataFrame 默认的 groupby 会按字符串首字母排序结果就是“大专、不限、本科、硕士”乱序。为了让柱状图呈现“不限→大专→本科→硕士→博士”的递进需要先把该列转成有序的 Categorical 类型import pandas as pd import matplotlib.pyplot as plt df pd.read_csv(new_python.csv, encodingutf-8-sig) edu_order [不限, 大专, 本科, 硕士, 博士] df[education] pd.Categorical(df[education], categoriesedu_order, orderedTrue) edu_count df.groupby(education, observedTrue).size().reset_index(namecount) city_count df[city].value_counts().head(15).reset_index() city_count.columns [city, count]observedTrue这个参数在 pandas 2.x 里是必须写的不写会收到 FutureWarning并且在后续绘图时可能出现空类别。城市统计用的是 value_counts().head(15)只取前 15 个城市因为招聘岗位高度集中在一线城市和新一线城市尾部城市样本太少画出来的柱状图尾巴会拉得很长反而看不出规律。这两组统计最终对应两张可视化截图不同学历要求下岗位数量分布.png 和各城市地区的岗位数量分布.png。柱状图的字体、配色和保存参数我会在下一章专门讲因为那部分才是可视化大作业的得分点。3.2 three-analyse-money.py把“1-1.5万/月”变成可计算的数值这个脚本是整个项目最值钱的部分也是文档报告里评审最看重的设计点。前程无忧的薪资字段大多是“6-8千/月”“1-1.5万/月”“30-50万/年”这种字符串直接 astype(float) 必然报错。作者的思路是把区间字符串转成一个代表“相对真实月薪”的数值取区间下限和上限的中值再统一换算成元/月。所谓“相对”意思是它不等于真实到手工资但能用于横向比较不同城市、学历、经验下的薪资水平。import re def salary_to_monthly(s): if not isinstance(s, str): return None s s.strip() if 面议 in s: return None unit 月 if /年 in s: unit 年 nums re.findall(r[\d.], s) if len(nums) 2: return None low, high float(nums[0]), float(nums[1]) mid (low high) / 2 if 千 in s: mid * 1000 elif 万 in s: mid * 10000 if unit 年: mid / 12 return round(mid, 2) df[real_salary] df[salary].apply(salary_to_monthly)这段解析逻辑的关键在不同单位的权重。字符串“6-8千/月”正则抓出 6 和 8乘 1000 得到 6000 和 8000 的中值 7000“1-1.5万/月”同理得到 12500“30-50万/年”先乘 10000 再除以 12取中值后接近 33333 元/月。下面这张对照表是很多人在文档报告里会贴的能直观说明“相对真实月薪”的设计逻辑原始薪资字符串换算后区间元/月相对真实月薪元/月6-8千/月6000 - 800070001-1.5万/月10000 - 15000125002-2.5万/月20000 - 250002250030-50万/年25000 - 4166733333换算完字段后脚本用 groupby 按学历、工作经验分别聚合再画箱型图。这里选箱型图而不是折线图或均值图是因为招聘薪资是明显右偏的分布少数岗位给出 5 万以上的月薪会把均值拉得很高箱型图却能看到中位数、四分位距和离群点表达“大多数岗位落在什么范围”更诚实。4. 可视化参数还原中文字体、词云、柱状图与箱型图的绘制细节可视化截图是所有评分维度里最直观的一项项目里五张 PNG 基本覆盖了期末大作业要求的三类图表柱状图、箱型图、词云。绘制代码主体在 two-analyse.py 和 three-analyse-money.py 里但有一个公共前置依赖——中文字体。你下载的项目里那个 msyh.ttc 文件就是干这个用的它是微软雅黑的字体文件专门解决 matplotlib 和 wordcloud 在 Linux 或精简版 Windows 系统上中文显示成方块的问题。这是一线实战里最常见的翻车点之一代码和数据都对图一保存全是方块最后只能反工。4.1 msyh.ttc 与 matplotlib、wordcloud 的字体加载matplotlib 默认的字体是 DejaVu Sans不含中文字形。直接设置plt.rcParams[font.sans-serif] [Microsoft YaHei]在多数 Windows 机器上能生效但如果你用的是实验室电脑或云服务器系统里没装微软雅黑这行配置就静默失效。项目里带 msyh.ttc 的原因就是给代码一个“走到哪都能用的字体源”用 font_manager 从文件动态注册from matplotlib import font_manager import matplotlib.pyplot as plt font_path msyh.ttc font_manager.fontManager.addfont(font_path) prop font_manager.FontProperties(fnamefont_path) plt.rcParams[font.sans-serif] [prop.get_name()] plt.rcParams[axes.unicode_minus] Falseaddfont是从 3.4 版本开始支持的方法旧版本需要用FontProperties对象逐图指定 fontproperties 参数。axes.unicode_minus这行很多人都漏它的作用是把坐标轴的负号从 Unicode 字符换成 ASCII 减号否则箱型图离群点坐标轴上会出现一个特别小的方块。词云库 WordCloud 的字体系独立于 matplotlib必须单独传font_pathmsyh.ttc否则词云里所有中文都会变成豆腐块。4.2 词云、柱状图和箱型图的具体参数福利待遇关键词词云.png 是项目里最有“大作业感”的一张图。原始数据里每个岗位有一条福利标签文本可能是“五险一金 带薪年假 弹性工作”这种空格分隔的字符串。绘制前先把所有福利文本拼起来用 jieba 分词再用 collections.Counter 统计词频。这样比直接传一整段文本给 WordCloud 更可控因为能过滤掉“公司提供”“节日福利”这类每个岗位都有的泛词。from wordcloud import WordCloud from collections import Counter # welfare_counter 是福利词频字典例如 {五险一金: 128, 弹性工作: 89, ...} wc WordCloud( font_pathmsyh.ttc, width1600, height900, background_colorwhite, max_words200, colormapviridis ).generate_from_frequencies(welfare_counter) wc.to_file(可视化截图/福利待遇关键词词云.png)WordCloud 的generate_from_frequencies接收字典是重点它允许你提前清洗词频比默认的generate(text)更灵活。colormapviridis用的是 matplotlib 自带的色带比默认的橙色渐变观感好很多。柱状图这部分要注意的是刻度标签旋转城市名横着排会互相压字一般设plt.xticks(rotation45)箱型图则集中在薪资差异对比上plt.figure(figsize(10, 6), dpi120) df.boxplot(columnreal_salary, byeducation, showfliersFalse, gridFalse) plt.title(不同学历要求下相对真实月薪分布) plt.ylabel(相对真实月薪元/月) plt.suptitle() plt.savefig(可视化截图/不同学历要求下相对真实月薪箱型图.png, dpi150, bbox_inchestight)showfliersFalse的作用是隐藏离群点招聘数据里偶尔出现“80-100万/年”的高管岗不隐藏会把图纵向拉得很长中位数反而看不清。但这个参数在报告里要主动说明不然答辩时可能被质疑“是不是把数据丢了”。另外注意plt.suptitle()这是因为 boxplot 的 by 参数会自动生成一个总标题不覆盖的话图上会有重复标题。5. 避坑复现这套代码最容易翻车的五个地方这类由多个脚本串联的数据分析项目最大的问题从来不在于某一行代码不够优雅而在数据在不同脚本之间流动时格式、编码、列名对不上。以下五条踩坑记录是我按“现象 → 原因 → 解决”整理的你复现时如果卡住先对照这份清单排查。1. 现象python.csv 在 Excel 里打开是乱码。原因CSV 用普通 utf-8 写入Excel 默认按 GBK 解码中文。解决所有读取和写入 CSV 的地方统一用encodingutf-8-sig这个参数会写入一个 BOM 头Excel 能正确识别。注意用 pandas 读取时也要保持一致否则第一列列名可能带\ufeff前缀。2. 现象爬虫跑了几十页后请求返回 403 或验证码页面。原因请求频率太高或者同一个 User-Agent 使用时间过长被服务端标记。解决time.sleep(random.uniform(1, 3))做随机延时同时准备一个 User-Agent 列表轮换。更稳妥的做法是脚本支持断点续爬——先读已有 CSV 的最后一条记录从下一页继续而不是从头重爬。3. 现象箱型图坐标轴中文全是方块但程序不报错。原因matplotlib 系统字体里没有中文字形Windows 下常见的 SimHei、Microsoft YaHei 在精简安装里并不存在。解决用font_manager.fontManager.addfont(msyh.ttc)动态注册项目自带的字体文件不要依赖注册表里的系统字体。如果换了机器跑确认脚本路径里的 msyh.ttc 没被移动。4. 现象不同学历要求下岗位数量分布柱状图少一根柱子或多个柱高度异常。原因education 列里混着“本科以上”“本科及同等学历”“硕士学历”这些自由文本groupby 把它们当成不同类别。解决建立学历归一化字典把所有包含“本科”的文本映射成“本科”包含“硕士”的映射成“硕士”这一步做完再画图柱数从十几个变回五个以内。5. 现象分析脚本报 KeyError提示找不到 salary 或 city 列。原因上一个转换脚本生成的 CSV 列名和当前脚本的字段名不一致比如 one-transition.py 写入的列叫 job_title而后面的脚本读取的是 title。解决在分析脚本开头加一行print(df.columns.tolist())和print(df.head(2))跑之前先人工核对列名。这类问题不会因为代码逻辑正确而自动消失列名不一致是脚本组合项目里最常见的隐性翻车点。6. 拿到源码后的第一件事验证复现、替换数据、写进自己的报告这套项目下载下来不要直接从中间某个脚本开始跑。我自己的习惯是先按“one-transition.py → four-transition.py → two-analyse.py → three-analyse-money.py”的顺序完整跑一遍每跑完一步都看一眼输出的行数和前两行内容。CSV 行数如果骤降到零多半是上一步的过滤条件写太狠了如果列名变了就在这一步停下来修正而不是等分析脚本报 KeyError。验证的重点不是跑通而是跑出来的图是不是合理。比如词云里如果出现“薪资”“优厚”这类泛词说明分词时没做停用词过滤箱型图各地区真实月薪的中位数如果集中在 8000 到 15000 之间和招聘市场的直觉吻合那数据就是可信的。把这些截图和项目文档报告里的截图放在一起对比确认统计口径一致后再开始第二步——改数据。这份资源最大的价值在于脚本结构清晰你完全可以把岗位关键词从 Python 换成 Java、前端或者数据分析只需修改爬虫部分的关键词参数和输出文件名整条分析链路不用动。同理城市列表也可以从“北上广深”改成你所在省份的城市只要清洗层的 split 逻辑还成立就行。写着写着就绕不开报告这件事。项目文档.docx 里已经有了完整的章节和示例图表但直接交原报告是行不通的要把每张图替换成自己跑出来的结果把 SQL 查询语句里连接的表名改成实际导入的库名再把文末的不足与展望部分改得不那么模板化。如果答辩时被问到“相对真实月薪代表什么”就诚实回答这是区间中值换算不等于实际到账薪资——这种坦率的说明比遮掩更能加分。从那以后我每次拿到别人发来的数据分析项目源码都会强制自己先按顺序把导入导出脚本跑一遍把列名、编码和单位对清楚了再谈分析。这份资源本身完整度足够值得直接下载走一遍全流程希望帮到你。本文还有配套的精品资源点击获取
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。