DrissionPage 是什么:一个工具同时搞定 HTTP 与浏览器爬虫
如果你曾在 Python 爬虫项目里同时维护 requests 脚本和 Selenium/Playwright 浏览器脚本,就知道切换两套代码有多痛苦——Cookie 要手动同步、选择器语法不一致、代理配置各写一遍。DrissionPage 正是为解决这个问题而生的 Python 框架:它把 requests 风格的 HTTP 模式和 Chromium CDP 驱动的浏览器模式统一到同一套 API 下,并且能在两种模式之间无缝切换而共享 Cookie、Session 和状态。
对于需要 drissionpage web scraping 的开发者来说,这意味着你可以在简单页面用轻量 HTTP 请求(速度快、成本低),遇到 JS 渲染页面时一键升级到 drissionpage chromium 浏览器模式,无需重新登录或重建会话。结合 ProxyHat 住宅代理,你还能在每个请求或会话级别轮换 IP,绕过地理封锁和反爬机制。
法律与合规提示:本文仅讨论对公开数据的采集。在美国,计算机欺诈和滥用法(CFAA)对未经授权的访问有严格规定;在欧盟,GDPR对个人数据处理有严格要求。请始终遵守目标网站的 robots.txt 和服务条款,优先使用官方 API,控制请求频率,不要采集受版权保护或需登录才能访问的非公开数据。
为什么需要 DrissionPage:传统双工具方案的痛点
典型的爬虫项目会经历这样的演进:先用 requests 快速抓取静态页面,发现目标网站用了 React/Vue 动态渲染后,又引入 Selenium 或 Playwright 处理 JS。于是项目里出现了两套独立的代码:
- HTTP 訡式:速度快(单请求约 200ms),内存占用低(约 30MB),但无法执行 JavaScript。
- 浏览器模式:能渲染完整 DOM、执行 JS、处理复杂交互,但每个浏览器实例占用 200-500MB 内存,启动耗时 1-3 秒。
两套代码之间的 Cookie 同步、代理配置重复、选择器语法差异(CSS vs XPath vs Playwright 定位器),让维护成本翻倍。DrissionPage 的 WebPage 类通过 CDP(Chrome DevTools Protocol)直接控制 Chromium,在同一对象上切换模式,从根本上消除了这些问题。
DrissionPage 的三种页面模型
DrissionPage 提供三个核心页面类,理解它们的区别是掌握 drissionpage tutorial 的基础:
SessionPage — 纯 HTTP 模式
SessionPage 基于 Python requests 库封装,行为类似 requests.Session()。它发送 HTTP 请求、解析 HTML,不启动浏览器。适合抓取静态页面或 API 端点。优势是速度快、资源消耗极低,适合高并发批量采集。
ChromiumPage — 浏览器模式
ChromiumPage 通过 CDP 协议直接控制 Chromium 浏览器(无需 WebDriver),能执行 JavaScript、渲染动态内容、模拟用户交互。相比 Selenium,CDP 方式减少了中间层,通信延迟更低。适合处理 SPA 应用、需要点击/滚动等交互的场景。
WebPage — 混合模式(核心亮点)
WebPage 是 DrissionPage 最强大的类,它同时包含 SessionPage 和 ChromiumPage 的能力,可以在运行时通过 page.change_mode() 在 HTTP 和浏览器模式之间切换。关键点:切换时 Cookie 和 Session 状态自动保留——你在 HTTP 模式下登录获取的 Cookie,切到浏览器模式后依然有效,反之亦然。
这种设计让你能以最低成本完成任务:先用 HTTP 模式快速获取大部分数据,只在必要时升级到浏览器模式,节省 80% 以上的计算资源。
DrissionPage 惯用 API 速览
无论哪种页面模式,DrissionPage 的元素定位 API 是统一的。掌握以下核心方法即可覆盖大部分场景:
ele() 和 eles() — 元素定位
ele() 返回单个元素,eles() 返回元素列表。定位语法支持多种格式:
from DrissionPage import WebPage
page = WebPage()
page.get('https://example.com')
# 通过标签定位
input_box = page.ele('tag:input')
# 通过属性定位(@语法)
submit_btn = page.ele('@class=submit-button')
# XPath 语法
article = page.ele('xpath://div[@id="content"]/article')
# 组合定位
links = page.eles('tag:a@href:contains=product')
# 链式定位
title = page.ele('tag:div@class=card').ele('tag:h2')
这种统一的定位语法意味着你不需要在 HTTP 模式和浏览器模式之间切换选择器写法——同一套 ele() 调用在两种模式下都能工作。
ChromiumOptions — 浏览器配置
ChromiumOptions 用于配置浏览器行为,包括无头模式、代理设置、用户代理、窗口大小等:
from DrissionPage import ChromiumOptions
co = ChromiumOptions()
co.headless(True)
co.set_argument('--no-sandbox')
co.set_argument('--disable-gpu')
co.set_user_agent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...')
co.set_proxy('http://user-country-US:pass@gate.proxyhat.com:8080')
listen.start() — 监听网络数据包
这是 DrissionPage 的杀手级功能之一。listen 模块可以监听浏览器发出的 XHR/Fetch 请求,直接捕获后台 API 返回的 JSON 数据,无需逆向分析接口:
page = ChromiumPage()
page.listen.start('api/products') # 监听包含此关键词的请求
page.get('https://example.com/shop')
# 等待数据包被捕获
packet = page.listen.wait(timeout=10)
if packet:
json_data = packet.response.body # 直接获取 JSON
print(f'捕获到 {len(json_data.get("items", []))} 条商品数据')
这种方法比手动分析 Network 面板高效得多——你只需指定 URL 关键词,DrissionPage 会自动拦截匹配的响应并返回解析后的数据。
配置代理:SessionPage 与 ChromiumPage 的方式
在 drissionpage proxy 配置中,HTTP 模式和浏览器模式的设置方式不同,但都很直接。
SessionPage 设置代理
SessionPage 使用 set.proxies() 方法,与 requests 的 proxies 参数一致:
from DrissionPage import SessionPage
page = SessionPage()
page.set.proxies({
'http': 'http://user-country-US-session-abc123:pass@gate.proxyhat.com:8080',
'https': 'http://user-country-US-session-abc123:pass@gate.proxyhat.com:8080'
})
page.get('https://httpbin.org/ip')
print(page.html)
ChromiumPage 设置代理
浏览器模式通过 ChromiumOptions.set_proxy() 在启动时配置代理。注意:Chromium 的代理在启动时生效,运行时不能直接更改,需要重启浏览器实例:
from DrissionPage import ChromiumPage, ChromiumOptions
co = ChromiumOptions()
co.set_proxy('http://user-country-DE-city-berlin-session-def456:pass@gate.proxyhat.com:8080')
co.headless(True)
page = ChromiumPage(co)
page.get('https://httpbin.org/ip')
print(page.ele('tag:pre').text)
为什么需要住宅代理
对于硬目标网站(如 SERP 搜索引擎、电商价格监控、社交媒体),数据中心 IP 通常会被直接封锁。根据 Google robots.txt 规范,搜索引擎允许公开抓取,但实际访问时数据中心 IP 段容易被识别和限速。住宅代理使用真实 ISP 分配的 IP 地址,请求看起来来自普通家庭用户,成功率可达 95% 以上,而数据中心代理在严格反爬的网站上成功率可能低于 30%。
ProxyHat 提供住宅、移动和数据中心三种代理类型。对于 DrissionPage 爬虫,推荐使用住宅代理处理高难度目标,数据中心代理用于低防护站点以降低成本。详见 ProxyHat 定价方案。
实战示例:WebPage 从 HTTP 升级到浏览器模式
下面是一个完整的可运行示例,展示 WebPage 如何先以 HTTP 模式通过美国住宅代理请求静态页面,然后无缝升级到 Chromium 模式处理 JS 渲染页面——全程保持同一代理会话和 Cookie。
from DrissionPage import WebPage
import time
def build_proxy_url(country='US', session_id='abc123'):
"""构建 ProxyHat 住宅代理 URL"""
username = f'user-country-{country}-session-{session_id}'
password = 'your_password'
return f'http://{username}:{password}@gate.proxyhat.com:8080'
def scrape_with_escalation():
proxy_url = build_proxy_url(country='US', session_id='sess001')
# 创建 WebPage,初始为 HTTP 模式
page = WebPage(mode='session')
# 配置 HTTP 模式代理
page.set.proxies({
'http': proxy_url,
'https': proxy_url
})
# 第一步:HTTP 模式抓取静态列表页
print('--- HTTP 模式 ---')
page.get('https://books.toscrape.com/')
titles = page.eles('tag:h3')
print(f'HTTP 模式获取到 {len(titles)} 个书名')
for t in titles[:3]:
print(f' - {t.ele("tag:a").text}')
# 第二步:升级到浏览器模式处理 JS 渲染页面
print('--- 切换到 Chromium 模式 ---')
# 通过 ChromiumOptions 配置浏览器代理
from DrissionPage import ChromiumOptions
co = ChromiumOptions()
co.set_proxy(proxy_url)
co.headless(True)
co.set_argument('--no-sandbox')
# 切换模式,Cookie 自动保留
page.change_mode(co)
# 监听后台 API 请求
page.listen.start('api')
# 访问需要 JS 渲染的页面
page.get('https://quotes.toscrape.com/js/')
# 等待页面加载和元素出现
quotes = page.eles('tag:div@class=quote', timeout=10)
print(f'浏览器模式获取到 {len(quotes)} 条引言')
for q in quotes[:3]:
text = q.ele('tag:span@class=text').text
author = q.ele('tag:small@class=author').text
print(f' - {author}: {text[:50]}...')
# 检查是否捕获到 XHR 数据包
packets = page.listen.steps(count=3, timeout=10)
if packets:
print(f'捕获到 {len(packets)} 个网络数据包')
page.close()
scrape_with_escalation()
这个示例的关键在于:change_mode() 调用时,DrissionPage 会自动将 HTTP 模式下获取的 Cookie 传递给新启动的 Chromium 实例,你不需要手动管理会话状态。代理也通过 ChromiumOptions 传递给浏览器进程。
生产级模式:会话固定、重试与并发
会话固定(Sticky Session)
对于需要登录或多步骤流程的爬取,IP 频繁切换会导致会话失效。ProxyHat 支持 session 参数固定 IP:
import random
import string
def generate_session_id():
return ''.join(random.choices(string.ascii_lowercase + string.digits, k=8))
# 同一会话 ID 在有效期内保持同一出口 IP
session_id = generate_session_id()
proxy_url = f'http://user-country-US-session-{session_id}:pass@gate.proxyhat.com:8080'
不同的 session_id 会被分配不同的 IP,相同 ID 在一段时间内复用同一 IP。这让你可以精确控制 IP 轮换粒度。
重试与错误处理
from DrissionPage import WebPage
import time
def fetch_with_retry(url, max_retries=3, backoff=2):
"""带指数退避的重试逻辑"""
page = WebPage(mode='session')
for attempt in range(max_retries):
try:
session_id = f'retry-{attempt}'
proxy = f'http://user-country-US-session-{session_id}:pass@gate.proxyhat.com:8080'
page.set.proxies({'http': proxy, 'https': proxy})
resp = page.get(url, timeout=15)
if resp.status_code == 200:
return resp
elif resp.status_code == 429:
wait = backoff ** attempt
print(f'触发限流,等待 {wait}s 后重试')
time.sleep(wait)
else:
print(f'状态码 {resp.status_code},第 {attempt+1} 次重试')
time.sleep(backoff)
except Exception as e:
print(f'异常: {e},第 {attempt+1} 次重试')
time.sleep(backoff ** attempt)
return None
并发控制
DrissionPage 的 HTTP 模式可以轻松实现 50-100 并发请求,但浏览器模式每个实例占用大量内存,建议将并发控制在 5-10 个浏览器实例。使用线程池或 asyncio 管理并发:
from concurrent.futures import ThreadPoolExecutor, as_completed
from DrissionPage import SessionPage
def scrape_single(url, session_id):
proxy = f'http://user-country-US-session-{session_id}:pass@gate.proxyhat.com:8080'
page = SessionPage()
page.set.proxies({'http': proxy, 'https': proxy})
resp = page.get(url, timeout=15)
result = resp.status_code, len(page.html)
page.close()
return result
urls = ['https://httpbin.org/delay/1'] * 20
session_ids = [f'pool-{i:03d}' for i in range(20)]
with ThreadPoolExecutor(max_workers=10) as executor:
futures = {
executor.submit(scrape_single, url, sid): (url, sid)
for url, sid in zip(urls, session_ids)
}
for future in as_completed(futures):
url, sid = futures[future]
try:
status, length = future.result()
print(f'{sid}: status={status}, length={length}')
except Exception as e:
print(f'{sid}: error={e}')
对于更大规模的需求,可以将浏览器实例容器化(Docker),每个容器运行独立 Chromium 实例并分配不同代理会话。ProxyHat 支持高并发,详见 全球代理节点位置。
用 listen 发现隐藏 API
许多现代网站的数据实际通过后台 XHR 请求加载,页面上看到的数据来自 JSON API。listen 功能让你无需逆向就能发现这些接口:
page = ChromiumPage()
page.listen.start('api/search') # 监听包含 api/search 的请求
page.get('https://example.com/search?q=laptop')
# 获取捕获的请求包
packet = page.listen.wait(timeout=15)
if packet:
print(f'API URL: {packet.url}')
print(f'方法: {packet.method}')
print(f'请求头: {packet.request.headers}')
print(f'响应体: {packet.response.body}')
# 找到 API 后,可以切换到 HTTP 模式直接调用
api_url = packet.url
api_headers = packet.request.headers
发现 API 后,你可以用 SessionPage 直接请求该接口,速度提升 10 倍以上,无需启动浏览器。这就是 WebPage 混合模式的核心价值——用浏览器发现接口,用 HTTP 高效采集。更多爬虫场景参考 ProxyHat 爬虫用例和 SERP 追踪用例。
何时不应升级到浏览器模式
虽然 DrissionPage 让模式切换变得简单,但并非所有场景都需要浏览器。以下情况应保持 HTTP 模式:
- 目标页面是静态 HTML:如果数据直接在 HTML 源码中,用 HTTP 模式即可,浏览器模式是浪费资源。
- 已知 API 端点:如果已经通过
listen或浏览器开发者工具发现了 API,直接用 HTTP 请求 API 更高效。 - 大批量数据采集:需要处理数万 URL 时,HTTP 模式的并发能力和资源效率远超浏览器。
- 简单的表单提交:不涉及 JS 验证的 POST 请求,用 SessionPage 即可完成。
反过来说,以下情况必须使用 ChromiumPage:
- 页面内容由 JavaScript 动态渲染(React、Vue、Angular SPA)。
- 需要执行 JS 计算的加密参数(如签名、token 生成)。
- 需要模拟复杂用户交互(拖拽、滚动加载、Canvas 操作)。
- 目标网站有 JS Challenge / Cloudflare 等浏览器指纹检测。
关键要点总结
DrissionPage 的核心价值:
- SessionPage + ChromiumPage + WebPage 三模式统一 API,Cookie/Session 跨模式共享。
- 先用 HTTP 模式低成本采集,遇到 JS 渲染再升级浏览器,节省 80%+ 资源。
ele()/eles()统一定位语法支持 @属性、tag:标签、xpath 三种格式。listen.start()直接捕获 XHR/JSON 响应,无需逆向接口。- ProxyHat 住宅代理通过
set.proxies()(HTTP)和ChromiumOptions.set_proxy()(浏览器)集成。- 会话固定用
user-country-US-session-xxx用户名格式,重试时更换 session ID 自动换 IP。- HTTP 模式可跑 50-100 并发,浏览器模式建议 5-10 实例并发。
- 始终遵守 robots.txt、服务条款和相关法律法规,只采集公开数据。
更多 ProxyHat 代理配置细节和高级参数,请参阅 ProxyHat 官方文档。如果你需要评估不同代理类型和定价方案,可以查看 ProxyHat 定价页面。






