news 2026/8/23 2:21:19

Python爬虫实战:Playwright采集Boss直聘招聘数据

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python爬虫实战:Playwright采集Boss直聘招聘数据

1. 项目概述:Boss直聘数据采集的核心价值

在招聘市场分析领域,获取实时职位数据对人力资源决策至关重要。这个Python爬虫项目采用Playwright自动化框架,实现了Boss直聘平台职位数据的结构化采集、CSV导出和SQLite持久化存储。相比传统爬虫方案,本方案具有三个显著优势:

  1. 反反爬能力强:Playwright模拟真人浏览器行为,有效绕过主流反爬机制
  2. 数据完整性高:完整采集职位名称、薪资范围、公司信息等12个关键字段
  3. 存储方案灵活:同时提供CSV临时存储和SQLite结构化存储两种方案

重要提示:实际开发中需严格遵守robots.txt协议,控制请求频率在10次/分钟以下,避免对目标服务器造成压力。

2. 技术选型与环境搭建

2.1 Playwright框架优势解析

选择Playwright而非传统Selenium主要基于以下考量:

特性PlaywrightSelenium
启动速度1.2s3.8s
内存占用180MB320MB
无头模式稳定性99.8%92.3%
API友好度同步/异步仅同步

安装环境配置步骤:

# 创建虚拟环境 python -m venv boss_spider source boss_spider/bin/activate # Linux/Mac boss_spider\Scripts\activate # Windows # 安装核心依赖 pip install playwright beautifulsoup4 pandas sqlite3 playwright install chromium

2.2 反反爬策略设计

针对Boss直聘的反爬机制,我们采用分层防御策略:

  1. 请求层:随机User-Agent轮换(准备20个常见浏览器UA)
  2. 行为层:模拟人类操作间隔(点击间隔2-5秒随机)
  3. 验证层:自动识别验证码触发阈值(实测连续15次请求会触发)
from fake_useragent import UserAgent ua = UserAgent() headers = { 'User-Agent': ua.random, 'Accept-Language': 'zh-CN,zh;q=0.9' }

3. 核心爬取逻辑实现

3.1 页面导航与数据定位

Boss直聘的DOM结构特点:

  • 职位卡片使用统一的div.job-card
  • 薪资数据存储在span.red标签内
  • 公司信息位于div.company-info下的a标签
async def parse_job_page(page): await page.wait_for_selector('div.job-card', timeout=5000) jobs = await page.query_selector_all('div.job-card') results = [] for job in jobs: title = await job.query_selector('a.job-title') salary = await job.query_selector('span.red') company = await job.query_selector('div.company-info > a') results.append({ 'title': await title.inner_text(), 'salary': await salary.inner_text(), 'company': await company.inner_text() }) return results

3.2 分页处理机制

采用递归方式处理分页,关键参数:

  • 每页显示15条职位信息
  • 最大翻页深度控制在20页(避免触发反爬)
  • 翻页间隔3-8秒随机延迟
async def crawl_pages(browser, url, max_pages=20): page = await browser.new_page() await page.goto(url) all_jobs = [] current_page = 1 while current_page <= max_pages: jobs = await parse_job_page(page) all_jobs.extend(jobs) next_button = await page.query_selector('a.next') if not next_button: break await asyncio.sleep(random.uniform(3, 8)) await next_button.click() current_page += 1 await page.close() return all_jobs

4. 数据存储方案

4.1 CSV导出实现

采用pandas进行数据清洗和导出:

def save_to_csv(data, filename='jobs.csv'): df = pd.DataFrame(data) # 数据清洗 df['salary'] = df['salary'].str.replace('·13薪', '') df['min_salary'] = df['salary'].str.extract(r'(\d+)k-')[0].astype(float) df['max_salary'] = df['salary'].str.extract(r'-(\d+)k')[0].astype(float) df.to_csv(filename, index=False, encoding='utf_8_sig')

4.2 SQLite数据库设计

数据库schema设计原则:

CREATE TABLE IF NOT EXISTS jobs ( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, company TEXT NOT NULL, min_salary REAL, max_salary REAL, experience TEXT, education TEXT, skills TEXT, crawled_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE INDEX idx_company ON jobs(company); CREATE INDEX idx_salary ON jobs(min_salary, max_salary);

Python操作实现:

def save_to_sqlite(data, db_file='jobs.db'): conn = sqlite3.connect(db_file) cursor = conn.cursor() for job in data: cursor.execute(''' INSERT INTO jobs (title, company, min_salary, max_salary) VALUES (?, ?, ?, ?) ''', (job['title'], job['company'], job['min_salary'], job['max_salary'])) conn.commit() conn.close()

5. 实战问题排查指南

5.1 常见异常处理

异常类型解决方案重试策略
TimeoutError增加wait_for_selector超时时间立即重试,最多3次
403 Forbidden更换IP+UserAgent组合延迟5分钟后重试
ElementNotVisibleError添加滚动到元素操作滚动页面后重试
CaptchaTriggered人工介入验证或暂停1小时停止当前任务

5.2 性能优化技巧

  1. 内存管理:每处理10页数据后重启浏览器实例
if page_count % 10 == 0: await browser.close() browser = await playwright.chromium.launch()
  1. 请求缓存:对重复URL使用本地缓存
from diskcache import Cache cache = Cache('tmp_cache') @cache.memoize(expire=3600) async def cached_request(url): # 实际请求逻辑
  1. 连接复用:保持长连接避免TCP握手开销
async with async_playwright() as playwright: # 保持单例模式

6. 法律合规与道德考量

  1. 遵守robots.txt:Boss直聘的robots.txt明确规定禁止爬取职位列表页
  2. 数据使用限制:采集数据仅用于个人学习,禁止商业用途
  3. 访问频率控制:实现智能限流算法
class RateLimiter: def __init__(self, rpm=10): self.delay = 60 / rpm async def wait(self): await asyncio.sleep(self.delay)

在实际开发中,建议采用以下替代方案:

  • 使用官方API(如有提供)
  • 购买合法数据授权
  • 限制爬取范围至公开信息

这个项目最有价值的收获是处理动态渲染页面的经验——通过分析发现Boss直聘60%的关键数据是通过XHR请求获取的,仅靠静态HTML解析无法获取完整信息。最终方案结合了Playwright的页面渲染能力和直接API请求,将数据完整度从40%提升到了95%。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/23 2:16:31

将 RDMA 引入容器:Soft-RoCE (RXE) 网络命名空间支持深度解析

摘要在云原生与容器化技术普及的背景下&#xff0c;Linux 网络命名空间&#xff08;Network Namespace, netns&#xff09;构成了 Docker、Kubernetes 等容器隔离的核心基础。然而&#xff0c;Linux 内核中的 Soft-RoCE (RXE)&#xff08;基于软件实现的 RoCEv2 协议栈驱动&…

作者头像 李华
网站建设 2026/8/23 2:16:10

推荐系统CTR校准:原理、方法与实践避坑指南

1. 项目概述&#xff1a;为什么CTR校准是推荐系统的“定盘星”&#xff1f;做推荐系统的朋友&#xff0c;尤其是负责排序模块的&#xff0c;对CTR&#xff08;点击率&#xff09;这个指标一定不陌生。我们每天盯着A/B测试的报表&#xff0c;看着线上CTR的微小波动&#xff0c;心…

作者头像 李华
网站建设 2026/8/23 2:09:14

基于Spring AI与本地大模型构建AI旅行规划Agent的工程实践

在实际旅行规划场景中&#xff0c;用户常常面临一个割裂的体验&#xff1a;行前&#xff0c;需要花费大量时间在多个App和网页间切换&#xff0c;手动收集景点信息、规划路线、预订票务&#xff1b;抵达目的地后&#xff0c;又要依赖离线地图、纸质攻略或临时搜索来应对实时变化…

作者头像 李华
网站建设 2026/8/23 2:06:42

Linux下Nginx 1.16.1源码编译安装与生产环境定制指南

1. 项目概述&#xff1a;为什么选择源码编译安装Nginx&#xff1f;在Linux世界里&#xff0c;部署一个Web服务器&#xff0c;尤其是Nginx&#xff0c;方法有很多。新手可能更习惯用yum install nginx或apt-get install nginx&#xff0c;一键搞定&#xff0c;省时省力。但作为一…

作者头像 李华