【python大作业/爬虫实战】——爬取前程无忧(51job)数据+可视化(附完整代码)

📅 2026/7/22 16:38:18
【python大作业/爬虫实战】——爬取前程无忧(51job)数据+可视化(附完整代码)
在当今数字化时代网络爬虫技术已成为数据获取的重要手段之一。本文将通过一个实际案例——采集51job招聘信息详细介绍如何使用Python和Selenium框架实现数据采集。我们将从环境准备、网页结构分析、采集字段说明到爬虫实现步骤等方面展开帮助读者快速掌握相关技术。 本文章中所有内容仅供学习交流使用不用于其他任何目的严禁用于商业用途和非法用途否则由此产生的一切后果均与作者无关本篇文章使用的是seleniunm接管已经打开的浏览器进行数据采集原理不懂的可以看之前的技术博客 (selenium接管已经打开的浏览器)更新时间2026-7-21一、项目背景51job是中国知名的招聘网站提供了海量的职位信息。这些信息对于求职者和招聘者都具有重要价值。通过采集51job的招聘信息我们可以进行数据分析、市场调研或为求职者提供决策支持。本文的目标是实现一个自动化采集程序获取51job上特定关键词如“大数据”的职位信息并将其保存为CSV文件。二、环境准备在开始项目之前我们需要准备以下开发环境和工具Python环境确保已安装Python推荐3.8及以上版本。可以通过以下命令安装必要的Python库pip install selenium pyautoguiSelenium WebDriverSelenium是一个用于自动化Web操作的工具支持多种浏览器。本文使用Chrome浏览器因此需要下载与浏览器版本匹配的ChromeDriver。下载地址ChromeDriver - WebDriver for Chrome。下载后将chromedriver.exe放置在系统路径中或指定路径。浏览器配置为了方便调试我们使用Selenium的远程调试功能。在启动Chrome浏览器时添加以下启动参数chrome.exe --remote-debugging-port9527这样Selenium可以通过该端口连接到浏览器。其他工具Pyautogui用于模拟鼠标操作处理滑块验证码。CSV用于存储采集到的数据。三、采集字段说明在爬取51job的招聘信息时我们主要关注以下字段岗位名称招聘职位的名称。岗位薪资该职位的薪资范围。岗位地区工作地点。岗位标签与该职位相关的标签如“五险一金”、“带薪年假”等。公司名字招聘公司的名称。公司行业公司所属的行业。公司规模公司的员工规模。公司类型公司的类型如“民营公司”、“外资公司”等。HR活跃程度HR的活跃程度如“刚刚活跃”、“3天前活跃”等。四、采集方式优缺点对比以下是通过表格形式对Selenium 接管已打开的浏览器采集、Requests 抓包采集需要逆向 sign 和 cookies以及直接使用 Selenium 采集的优缺点进行详细对比特性/方法Selenium 接管浏览器采集Requests 抓包采集逆向 sign 和 cookies直接使用 Selenium 采集启动速度快无需重新启动浏览器极快无需启动浏览器较慢需启动浏览器实例资源消耗低复用已有浏览器极低仅发起 HTTP 请求高需模拟用户操作动态页面支持强支持 JavaScript 渲染强动静态数据强支持 JavaScript 渲染反爬能力中可绕过简单验证高需逆向工程高可处理复杂验证调试效率高保留状态无需重复登录中需逆向分析低每次运行需重新启动安全性低可能涉及用户敏感信息高无浏览器状态中需注意反爬机制代码复杂度中需配置调试端口高需逆向工程中需模拟用户操作适用场景需保留登录状态或调试效率高的场景静态网页或 API 数据采集动态页面、复杂交互操作维护成本低复用已有浏览器高需定期更新逆向逻辑高需更新 WebDriver 和代码易用性中需熟悉 Selenium 和调试模式高代码简洁低需熟悉 Selenium 操作五、网页结构分析在编写爬虫之前我们需要对51job的网页结构进行分析以便准确提取所需信息。职位列表页面职位搜索结果页面的URL格式为https://we.51job.com/pc/search?keyword关键词例如搜索“大数据”相关职位时URL为https://we.51job.com/pc/search?keyword大数据职位信息的HTML结构每个职位信息以div classjoblist-item的形式展示。以下是关键字段的HTML结构分析岗位名称div classjoblist-item-top下的span标签。岗位薪资span classsal shrink-0。岗位地区div classarea。岗位标签div classtag下的多个span标签。公司名字a classcname text-cut。公司行业、类型、规模div classbl下的多个span标签。HR活跃程度div classtip shrink-0。分页结构51job的职位搜索结果支持分页每页显示一定数量的职位。翻页按钮的HTML结构为button classbtn-next下一页/button验证码处理51job可能会在某些情况下弹出滑块验证码(采用接管的浏览器可以登录避免经常出现验证码)。为了应对这种情况我们使用pyautogui库模拟鼠标操作完成滑块验证。六、结果展示七、完整代码一数据采集爬虫部分如果您对源码爬虫可视化感兴趣不白嫖迪迦可以在评论区留言主页 \/伪善我会根据需求提供指导和帮助二可视化部分1.岗位地域分布from pyecharts import options as opts from pyecharts.charts import Map map_data df[省份].value_counts().reset_index().values.tolist() map_chart ( Map() .add( series_name, data_pairmap_data, maptypechina, is_map_symbol_showFalse, # 禁用标记点 label_optsopts.LabelOpts(is_showTrue, font_size8), # 调整省份字体大小 ) .set_global_opts( title_optsopts.TitleOpts(title岗位地域分布地图), visualmap_optsopts.VisualMapOpts( is_piecewiseTrue, # 分段显示 pieces[ {min: 100, label: 100, color: #CD5C5C}, {min: 50, max: 99, label: 50-99, color: #F08080}, {min: 1, max: 49, label: 1-49, color: #FFA07A}, {min: 0, max: 0, label: 0, color: #FFFFFF}, ], ), ) ) map_chart.render_notebook()2.企业规模占比分布size_counts df[公司规模1].value_counts() sns.set_theme(stylewhitegrid,rc{ font.sans-serif: [SimHei], # 设置字体为黑体 axes.unicode_minus: False, # 正确显示负号 font.family: sans-serif # 设置字体族为 sans-serif }) plt.figure(figsize(8, 8)) plt.pie( size_counts, labelssize_counts.index, autopct%1.1f%%, startangle90, colorssns.color_palette(pastel), wedgeprops{edgecolor: white, linewidth: 1.5}, textprops{fontsize: 12, color: black} ) plt.title(企业规模占比分布, fontsize16, fontweightbold, pad20) plt.show()3.企业类型占比分布size_counts df[公司类型].value_counts() size_percentage size_counts / size_counts.sum() * 100 # 找出占比小于 2% 的类别 small_categories size_percentage[size_percentage 2].index # 将占比小于 2% 的类别合并为“其他” size_counts[其他] size_counts[small_categories].sum() size_counts size_counts.drop(small_categories) sns.set_theme(stylewhitegrid, rc{ font.sans-serif: [SimHei], # 设置字体为黑体 axes.unicode_minus: False, # 正确显示负号 font.family: sans-serif # 设置字体族为 sans-serif }) plt.figure(figsize(15, 10)) plt.pie( size_counts, labelssize_counts.index, autopct%1.1f%%, # 显示百分比 startangle90, # 起始角度 colorssns.color_palette(pastel), wedgeprops{edgecolor: white, linewidth: 1.5}, textprops{fontsize: 12, color: black} ) plt.title(企业类型占比分布, fontsize16, fontweightbold, pad20) plt.show()4.HR活跃程度统计分析value_counts df[hr活跃程度1].value_counts() plt.figure(figsize(8, 6)) # 设置图形大小 sns.barplot(xvalue_counts.index, yvalue_counts.values, paletteviridis) plt.title(HR活跃程度统计分析, fontsize16) plt.xlabel() plt.ylabel() plt.show()5.企业数量Top 7top_7 df[公司名字].value_counts().head(7) plt.figure(figsize(15, 6)) sns.barplot(xtop_7.values, ytop_7.index, paletteviridis) plt.title(企业数量Top 7, fontsize16) plt.xlabel(,) plt.ylabel(,) # plt.yticks(rotation15, fontsize12) plt.show()6.岗位标签词云from wordcloud import WordCloud import jieba df[岗位标签1] df[岗位标签].apply(lambda x: .join(eval(x))) all_text .join(df[岗位标签1]) # 使用 jieba 进行分词 words jieba.lcut(all_text) all_text .join(words) # 创建词云对象 wordcloud WordCloud( font_pathsimhei.ttf, # 设置字体路径支持中文 width800, height600, background_colorwhite, # 设置背景颜色 max_words100, # 设置最多显示的词数 min_font_size10, # 设置最小字体大小 max_font_size100, # 设置最大字体大小 random_state42 # 设置随机种子 ).generate(all_text) plt.figure(figsize(10, 8)) plt.imshow(wordcloud, interpolationbilinear) plt.axis(off) # 关闭坐标轴 plt.title(, fontsize16) plt.show()