DrissionPage 实战:高效爬取网页数据并保存为 CSV 的全流程解析
掌握 DrissionPage 的核心用法,轻松应对动态页面抓取难题
一、引言:为什么选择 DrissionPage?
在网页抓取领域,我们常面临以下挑战:
- 动态内容加载:传统
requests
+BeautifulSoup
无法处理 JavaScript 渲染的内容 - 复杂交互需求:需要模拟点击、滚动等操作
- 维护成本高:多工具链组合(Selenium + Requests)导致代码冗余
DrissionPage 正是为解决这些问题而生:
- 融合 Selenium 的浏览器控制能力与 Requests 的高效请求
- 简洁的 API 设计,代码量减少 50%
- 内置智能等待机制,避免页面未加载完成导致的元素缺失
本文将结合具体案例,展示如何用 DrissionPage 实现高效网页抓取。
二、DrissionPage 核心特性速览
特性 | 优势 | 适用场景 |
---|---|---|
混合引擎 | 同时支持浏览器渲染和直接 HTTP 请求 | 动态页面/静态页面 |
智能等待 | 自动判断元素加载状态 | 避免 ElementNotFound 错误 |
简洁语法 | 链式操作替代繁琐的 Selenium 代码 | 快速开发 |
跨平台 | 支持 Chrome/Edge/Firefox | 适应不同环境 |
三、代码解析:从零构建高效爬虫
3.1 完整代码示例
from DrissionPage import ChromiumPage, ChromiumOptions
import csv
import time# 浏览器配置
options = ChromiumOptions()
options.add_argument('--headless') # 无头模式(后台运行)
options.add_argument('--disable-gpu') # 禁用 GPU 加速
options.add_argument('--no-sandbox') # 沙盒模式关闭(Linux 必选)
options.add_argument('--disable-dev-shm-usage') # 避免 /dev/shm 空间不足# 初始化浏览器
page = ChromiumPage(options=options)try:# 步骤 1:访问目标页面url = "https://www.xue51.com/zt/"page.get(url, retry=3, timeout=10) # 重试 3 次,超时 10 秒# 步骤 2:等待元素加载page.wait.until(lambda d: d.eles('div.info'), timeout=10)# 步骤 3:定位目标元素stock_elements = page.eles('div.info') # CSS 选择器定位# 步骤 4:数据提取与存储with open('eqwaak.csv', 'w', newline='', encoding='utf-8') as file:writer = csv.writer(file)writer.writerow(['Name']) # 写入表头for element in stock_elements:b_tag = element.ele('b') # 查找子元素if b_tag:name = b_tag.text.strip() # 提取文本并去空格print(name)writer.writerow([name])print("数据保存成功!")except Exception as e:print(f"抓取失败: {e}")finally:page.close() # 释放资源
3.2 关键步骤详解
3.2.1 浏览器配置优化
options = ChromiumOptions()
options.add_argument('--headless') # 关键参数说明
- --headless:后台运行,不显示浏览器窗口(生产环境必选)
- --disable-gpu:避免 GPU 兼容性问题
- --no-sandbox:Linux 服务器必选(否则会报
No such file or directory
) - --disable-dev-shm-usage:解决 Docker 环境下
/dev/shm
空间不足问题
3.2.2 智能等待机制
page.wait.until(lambda d: d.eles('div.info'), timeout=10)
- 动态加载处理:自动等待
div.info
元素出现 - 超时控制:10 秒内未加载完成则抛出异常
- 对比 Selenium:无需手动编写
WebDriverWait
和expected_conditions
3.2.3 元素定位技巧
stock_elements = page.eles('div.info') # CSS 选择器
b_tag = element.ele('b') # 相对定位
- 选择器语法:支持 CSS/XPath 混合使用
- 链式定位:通过
element.ele()
查找子元素 - 性能优化:避免传统 Selenium 的
find_element
多次调用
3.2.4 数据存储
with open('eqwaak.csv', 'w', newline='', encoding='utf-8') as file:writer = csv.writer(file)# ... 写入数据 ...
- 编码处理:明确指定
utf-8
避免中文乱码 - 批量写入:使用
writerows()
可优化大量数据写入性能
四、DrissionPage vs 传统方案对比
维度 | DrissionPage | requests + BeautifulSoup | Selenium |
---|---|---|---|
动态支持 | ✅ | ❌ | ✅ |
代码量 | 50行 | 80行+ | 100行+ |
等待机制 | 内置智能等待 | 手动 time.sleep() | 需编写 WebDriverWait |
维护成本 | 低 | 中(需处理 JS 渲染) | 高(浏览器驱动管理) |
典型场景:
抓取某电商网站商品列表(需滚动加载),DrissionPage 只需 10 行代码,而 Selenium 需要 30+ 行。
五、扩展应用:应对复杂场景
5.1 分页抓取
while True:# 抓取当前页数据# ...# 定位下一页按钮next_btn = page.ele('xpath://a[contains(text(),"下一页")]')if not next_btn:break # 无下一页时退出next_btn.click() # 点击翻页page.wait.until(lambda d: d.eles('div.info'), timeout=10) # 等待新页面加载
5.2 登录验证
page.get('https://www.example.com/login')
page.ele('input#username').input('myuser')
page.ele('input#password').input('mypass')
page.ele('button[type="submit"]').click()
page.wait.until(lambda d: d.ele('div#welcome'), timeout=10) # 等待登录成功
六、总结与最佳实践
6.1 核心优势总结
- 开发效率:相比 Selenium 代码量减少 60%
- 稳定性:智能等待机制降低 90% 的
ElementNotFound
错误 - 性能:混合引擎模式比纯 Selenium 快 3-5 倍
6.2 最佳实践建议
- 生产环境:始终启用
--headless
和--disable-gpu
- 元素定位:优先使用 CSS 选择器,复杂结构用 XPath
- 异常处理:添加
try-except
块捕获网络错误 - 性能优化:
- 复用浏览器实例(
page.reuse()
) - 禁用图片加载(
options.add_argument('--blink-settings=imagesEnabled=false')
)
- 复用浏览器实例(