网站主体注销,门户网站的建设方案,东莞市建设监督网站首页,企业类网站模板使用Python爬取BOSS直聘职位数据并保存到Excel
在数据分析和挖掘中#xff0c;爬取招聘网站数据是一项常见的任务。本文将详细介绍如何使用Python爬取BOSS直聘上与“测试工程师”相关的职位数据#xff0c;并将其保存到Excel文件中。通过逐步分解代码和添加详细注释#xf…使用Python爬取BOSS直聘职位数据并保存到Excel
在数据分析和挖掘中爬取招聘网站数据是一项常见的任务。本文将详细介绍如何使用Python爬取BOSS直聘上与“测试工程师”相关的职位数据并将其保存到Excel文件中。通过逐步分解代码和添加详细注释我们将深入了解整个实现过程。 项目概述
本项目的功能是爬取BOSS直聘指定条件的职位数据并将数据保存到Excel文件。以下是主要步骤
配置浏览器驱动使用Selenium模拟用户操作。加载网页动态加载职位列表。解析职位信息提取职位的名称、薪资、技能要求等。保存数据数据持久化到Excel文件并为列标题添加注释便于理解。 环境准备
安装依赖库
请确保已安装以下库
pip install selenium pandas openpyxl下载ChromeDriver
根据你的Chrome浏览器版本下载对应的ChromeDriver并将其路径配置到代码中。
我这里是用的chrome浏览器:
先查看浏览器版本
114及更早版本
113及113以后下载
130及以后 详细代码解析
1. 配置Selenium WebDriver
目标通过Selenium启动浏览器模拟用户访问BOSS直聘。
from selenium import webdriver
from selenium.webdriver.chrome.service import Servicedef setup_driver():配置并启动Selenium WebDriver用于模拟浏览器操作。:return: 返回配置完成的Chrome浏览器驱动对象。options webdriver.ChromeOptions()# 添加可选的启动参数# options.add_argument(--headless) # 无头模式隐藏浏览器界面# options.add_argument(--disable-gpu) # 禁用GPU优化性能# options.add_argument(--no-sandbox) # 禁用沙箱模式# options.add_argument(--start-maximized) # 最大化窗口# 创建浏览器驱动服务service Service(D:\\tool\\chromedriver-win64\\chromedriver.exe)# 初始化WebDriverdriver webdriver.Chrome(serviceservice, optionsoptions)return driver重点webdriver.ChromeOptions可以设置浏览器的启动参数如无头模式headless。路径配置Service指定了ChromeDriver的路径。 2. 加载网页并滚动加载
目标加载指定页面并模拟滚动加载更多内容。
import time
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keysdef scrape_jobs(driver, url):爬取BOSS直聘的职位数据。:param driver: 已配置的Selenium WebDriver实例。:param url: BOSS直聘的目标页面URL。:return: 返回包含职位信息的列表。driver.get(url) # 打开指定页面time.sleep(15) # 等待页面完全加载# 模拟滚动操作加载更多职位信息for _ in range(5): # 假设需要滚动5次加载更多内容driver.find_element(By.TAG_NAME, body).send_keys(Keys.END)time.sleep(2) # 等待页面加载完成# 定位职位列表jobs driver.find_elements(By.CSS_SELECTOR, .job-list-box li) # 找到所有职位块job_data [] # 用于存储职位数据页面滚动通过发送Keys.END键模拟用户滚动操作。延迟加载time.sleep确保页面元素完全加载。 3. 提取职位数据
目标解析页面中每个职位的数据。 for job in jobs:try:# 获取职位信息job_link_element job.find_element(By.CSS_SELECTOR, .job-card-left) # 职位链接所在的元素job_link job_link_element.get_attribute(href) # 获取链接job_name job.find_element(By.CSS_SELECTOR, .job-name).text # 职位名称salary_desc job.find_element(By.CSS_SELECTOR, .salary).text # 薪资描述city_area job.find_element(By.CSS_SELECTOR, .job-area).text.split(·) # 城市和区域city_name city_area[0] # 城市名称area_district city_area[1] if len(city_area) 1 else # 区域名称# 获取技能标签skills [skill.text for skill in job.find_elements(By.CSS_SELECTOR, .job-card-footer .tag-list li)]# 获取经验和学历要求tags job.find_elements(By.CSS_SELECTOR, .job-info .tag-list li)job_experience tags[0].text if len(tags) 0 else # 工作年限要求job_degree tags[1].text if len(tags) 1 else # 学历要求# 获取公司信息brand_name job.find_element(By.CSS_SELECTOR, .company-name).text # 公司名称brand_info [tag.text for tag in job.find_elements(By.CSS_SELECTOR, .company-tag-list li)]brand_industry brand_info[0] if len(brand_info) 0 else # 公司行业brand_stage_name brand_info[1] if len(brand_info) 1 else # 公司发展阶段brand_scale_name brand_info[2] if len(brand_info) 2 else # 公司规模# 保存数据到列表job_data.append({job_name: job_name,salary_desc: salary_desc,skills: ,.join(skills), # 用逗号分隔技能job_experience: job_experience,job_degree: job_degree,city_name: city_name,area_district: area_district,brand_name: brand_name,brand_industry: brand_industry,brand_stage_name: brand_stage_name,brand_scale_name: brand_scale_name,job_link: job_link,})except Exception as e:print(fError processing job: {e})结构化数据将提取的数据存储为字典。错误处理使用try-except捕获解析错误。 4. 保存到Excel并添加注释
目标将数据保存到Excel文件并为每列添加注释。
import pandas as pd
from openpyxl import load_workbook
from openpyxl.comments import Commentdef save_job_to_excel(jobs, filename./jobs.xlsx):保存职位信息到 Excel 文件。:param jobs: 职位信息列表。:param filename: 保存的 Excel 文件路径。columns [职位名称, 薪资描述, 岗位要求, 年限要求, 学历要求, 城市, 区域, 公司名称, 行业类型, 是否上市, 公司规模, 职位链接]comments {职位名称: 职位的名称如“软件测试工程师”。,薪资描述: 职位的薪资范围例如“15-25K”。,岗位要求: 技能要求例如“Python, Java”。,年限要求: 职位所需的工作经验。,学历要求: 职位所需的最低学历。,城市: 职位所在城市例如“深圳”。,区域: 职位所在区域例如“南山区”。,公司名称: 招聘公司名称。,行业类型: 公司所属行业。,是否上市: 公司发展阶段如“上市公司”。,公司规模: 公司的人员规模。,职位链接: 职位的详情链接。}new_data pd.DataFrame(jobs) # 将数据转换为DataFrametry:existing_data pd.read_excel(filename) # 读取已有数据combined_data pd.concat([existing_data, new_data], ignore_indexTrue) # 合并except FileNotFoundError:combined_data new_datacombined_data.to_excel(filename, indexFalse) # 保存到文件add_comments_to_excel(filename, comments)def add_comments_to_excel(filename, comments):为Excel文件的列标题添加注释。:param filename: Excel 文件路径。:param comments: 列注释字典。wb load_workbook(filename)ws wb.activefor col_num, col_name in enumerate(ws[1], start1):col_letter chr(64 col_num) # 获取列的字母if col_name.value in comments:ws[f{col_letter}1].comment Comment(comments[col_name.value], 系统)wb.save(filename)5. 完整代码示例
import json
import os
import timeimport pandas as pd
from openpyxl import load_workbook
from openpyxl.comments import Comment
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys# 配置 WebDriver
def setup_driver():options webdriver.ChromeOptions()# options.add_argument(--headless) # 隐藏浏览器界面# options.add_argument(--disable-gpu)# options.add_argument(--no-sandbox)# options.add_argument(--start-maximized)service Service(D:\\tool\\chromedriver-win64\\chromedriver.exe)driver webdriver.Chrome(serviceservice, optionsoptions)return driver# 爬取页面数据
def scrape_jobs(driver, url):driver.get(url)time.sleep(15) # 等待页面加载# 滚动页面加载更多内容若有分页for _ in range(5):driver.find_element(By.TAG_NAME, body).send_keys(Keys.END)time.sleep(2)# 解析所有 job-list-box 下的 lijobs driver.find_elements(By.CSS_SELECTOR, .job-list-box li)job_data []for job in jobs:try:# 定位到职位链接的 a 标签job_link_element job.find_element(By.CSS_SELECTOR, .job-card-left)# 获取职位详情链接job_link job_link_element.get_attribute(href)job_name job.find_element(By.CSS_SELECTOR, .job-name).textsalary_desc job.find_element(By.CSS_SELECTOR, .salary).textcity_area job.find_element(By.CSS_SELECTOR, .job-area).text.split(·)city_name city_area[0]area_district city_area[1] if len(city_area) 1 else # 获取技能skills [skill.text for skill in job.find_elements(By.CSS_SELECTOR, .job-card-footer .tag-list li)]# 获取经验和学历tags job.find_elements(By.CSS_SELECTOR, .job-info .tag-list li)job_experience tags[0].text if len(tags) 0 else job_degree tags[1].text if len(tags) 1 else # 公司信息brand_name job.find_element(By.CSS_SELECTOR, .company-name).textbrand_info [tag.text for tag in job.find_elements(By.CSS_SELECTOR, .company-tag-list li)]brand_industry brand_info[0] if len(brand_info) 0 else brand_stage_name brand_info[1] if len(brand_info) 1 else brand_scale_name brand_info[2] if len(brand_info) 2 else # 保存数据job_data.append({job_name: job_name,salary_desc: salary_desc,skills: ,.join(skills),job_experience: job_experience,job_degree: job_degree,city_name: city_name,area_district: area_district,brand_name: brand_name,brand_industry: brand_industry,brand_stage_name: brand_stage_name,brand_scale_name: brand_scale_name,job_link: job_link,})except Exception as e:print(fError processing job: {e})return job_data# 保存数据到Excel
def save_job_to_excel(jobs, filename./jobs.xlsx):保存职位信息到 Excel 文件中如果文件不存在则创建新文件。:param jobs: 职位信息列表每个元素为包含职位字段的字典。:param filename: 保存的 Excel 文件路径。# 定义列名和中文注释columns [职位名称, 薪资描述, 岗位要求, 年限要求, 学历要求, 城市,区域, 公司名称, 行业类型, 是否上市, 公司规模, 任职要求, 职位链接]comments {职位名称: 职位的名称如“软件测试工程师”。,薪资描述: 职位的薪资区间如“12-20K”。,岗位要求: 职位要求的技能通常是一个列表如“Python, Java”等。,年限要求: 职位要求的工作经验年限。,学历要求: 职位要求的最低学历。,城市: 职位所在的城市如“深圳”。,区域: 职位所在的区域如“光明区”。,公司名称: 招聘公司的名称。,行业类型: 招聘公司所属的行业类型。,是否上市: 公司是否上市如“已上市”。,公司规模: 招聘公司的人数规模如“1000-9999人”。,任职要求: 职位的详细任职要求来自职位详情页面。,职位链接: 职位详情的跳转链接可直接点击查看职位详情。}# 尝试读取已有数据try:existing_df pd.read_excel(filename)except FileNotFoundError:existing_df pd.DataFrame(columnscolumns)# 准备新数据new_data [{职位名称: job_data[job_name],薪资描述: job_data[salary_desc],岗位要求: job_data[skills], # 将列表转换为字符串年限要求: job_data[job_experience],学历要求: job_data[job_degree],城市: job_data[city_name],区域: job_data[area_district],公司名称: job_data[brand_name],行业类型: job_data[brand_industry],是否上市: job_data[brand_stage_name],公司规模: job_data[brand_scale_name],任职要求: job_data.get(job_requirements, ),职位链接: job_data.get(job_link, ) # 添加职位链接默认为空}for job_data in jobs]new_df pd.DataFrame(new_data)# 合并数据combined_df pd.concat([existing_df, new_df], ignore_indexTrue)# 保存到 Excel 文件combined_df.to_excel(filename, indexFalse)# 添加注释到 Excel 文件add_comments_to_excel(filename, comments)def add_comments_to_excel(filename, comments):为 Excel 文件的列标题添加注释。:param filename: Excel 文件路径。:param comments: 列注释字典键为列名值为注释内容。wb load_workbook(filename)ws wb.activefor col_num, col_name in enumerate(ws[1], start1): # 遍历第一行的列col_letter chr(64 col_num) # 将列索引转为字母例如 1 - Aif col_name.value in comments:comment Comment(comments[col_name.value], 系统)ws[f{col_letter}1].comment commentwb.save(filename)print(f职位信息保存到 {filename} 并添加了注释。)if __name__ __main__:for page in range(1, 1):url fhttps://www.zhipin.com/web/geek/job?query测试工程师city101280600page{page}driver setup_driver()try:jobs scrape_jobs(driver, url)save_job_to_excel(jobs)print(fScraped {len(jobs)} jobs.)finally:driver.quit()总结
通过以上步骤您可以爬取BOSS直聘的职位数据并存储为结构化的Excel文件。以下是本项目的特点
自动化操作Selenium模拟用户操作。全面的数据保存包括职位详情和公司信息。注释增强可读性通过Excel注释标注列含义。
您可以根据需求调整代码实现更灵活的爬取和存储功能
后续目标
在爬取职位列表数据的基础上我们计划实现以下功能
爬取职位详情页面 职位列表中通常只提供部分信息如职位名称、薪资范围、公司信息等。而更多详细信息如岗位职责、任职要求存储在职位的详情页面中。下一步将实现爬取职位详情页面的功能。数据清洗与存储 在爬取到更多字段后我们需要进行数据清洗包括去除重复项、处理缺失值、统一数据格式等。清洗后的数据将更适合训练机器学习模型。训练机器学习模型 使用爬取到的数据构建模型尝试解决以下问题 薪资预测基于职位要求预测合理薪资。职位分类通过岗位职责将职位分类到不同的技术方向如“测试”、“开发”、“运维”等。城市分析分析不同城市的职位需求分布和薪资水平。