DrissionPage 代理配置完全指南:HTTP 与浏览器双模式爬虫实战

学习如何在 DrissionPage 中配置 ProxyHat 住宅代理,实现 SessionPage HTTP 模式与 ChromiumPage 浏览器模式无缝切换,涵盖 ele() 定位、listen 监听、会话固定与并发控制。

DrissionPage Proxy Guide: HTTP + Chromium Scraping with Residential IPs

法律与合规声明:本文仅讨论公开可访问数据的采集方法。在使用 DrissionPage 或任何爬虫工具前,请遵守目标网站的 robots.txt 和服务条款,并了解美国《计算机欺诈和滥用法》(CFAA)欧盟《通用数据保护条例》(GDPR)的相关规定。如果目标平台提供官方 API,请优先使用。

如果你是一名 Python 爬虫开发者,大概率遇到过这样的困境:requests 速度快、内存占用低,但碰到 JS 渲染页面就无能为力;Selenium 或 Playwright 能渲染页面,但每个请求都启动浏览器实例,内存吃掉 2 GB,速度慢 10 倍。DrissionPage 正是为解决这个矛盾而生——它在一个框架内同时提供 HTTP 模式和浏览器模式,通过 WebPage 实现无缝切换并共享 cookies 和会话状态。本篇 DrissionPage 教程将深入讲解如何将住宅代理集成到这个双模式框架中,实现高效且不易被封的 DrissionPage web scraping 工作流。

DrissionPage 是什么:HTTP 与浏览器的统一框架

DrissionPage 是一个基于 Python 的自动化工具库,由国内开发者 g1879 创建并在 GitHub 开源。其核心设计理念是"一个工具,两种模式"。它通过 Chrome DevTools Protocol(CDP)直接与 Chromium 浏览器通信,无需 WebDriver 中间层,因此比 Selenium 更轻量、更快。

三种页面模型

DrissionPage 提供三种页面类型,各有适用场景:

  • SessionPage:基于 Python requests 库的 HTTP 客户端模式。内存占用约 50 MB,适合采集静态页面或直接调用 JSON API。不支持 JavaScript 渲染。
  • ChromiumPage:通过 CDP 协议控制 Chromium 浏览器。支持完整的 JS 渲染、截图、文件下载等操作。内存占用约 300-500 MB,适合处理动态渲染页面。DrissionPage Chromium 模式是处理现代 SPA 网站的关键能力。
  • WebPage:DrissionPage 的核心创新。它同时持有 SessionPage 和 ChromiumPage 的能力,可以在运行时切换模式,且两种模式共享 cookies、headers 和会话状态。先用 HTTP 模式快速获取列表页,再切换到浏览器模式渲染详情页——无需重新登录或传递 cookies。
特性SessionPageChromiumPageWebPage
底层引擎requests (HTTP)CDP → Chromium可切换
JS 渲染不支持支持按需启用
典型内存~50 MB~300-500 MB取决于当前模式
Cookie 共享自身会话浏览器上下文跨模式共享
代理配置方式set_proxies()ChromiumOptions.set_proxy()两种方式均支持

这种架构的经济学意义在于:大多数爬虫任务中,只有 10%-30% 的页面真正需要浏览器渲染。用 SessionPage 处理其余 70%-90% 的请求,可以将服务器成本降低 60% 以上。查看 ProxyHat 定价方案,结合你的并发需求估算代理成本。

DrissionPage 惯用 API:定位器、选项与监听器

ele() 与 eles() 元素定位

DrissionPage 提供了一套简洁的元素定位语法,比 Selenium 的 find_element 更直观:

# 按 ID
page.ele('#username')

# 按 class
page.ele('.search-box')

# 按属性
page.ele('@class=result-item')
page.ele('@type=submit')

# 按标签
page.ele('tag:input')
page.ele('tag:div@class=container')

# XPath
page.ele('xpath://div[@class="content"]/p[1]')

# 获取多个元素
items = page.eles('tag:article')
for item in items:
    print(item.text)

ChromiumOptions 配置

ChromiumOptions 是 ChromiumPage 的配置中心,用于设置浏览器路径、启动参数、代理等:

from DrissionPage import ChromiumOptions

co = ChromiumOptions()
co.set_argument('--no-sandbox')
co.set_argument('--disable-gpu')
co.set_argument('--window-size', '1920,1080')
co.headless()  # 无头模式

listen.start() 监听网络请求

这是 DrissionPage 最强大的功能之一——监听浏览器发出的后台 XHR/fetch 请求,直接捕获 JSON 数据,无需解析渲染后的 HTML:

from DrissionPage import WebPage

page = WebPage()
page.listen.start('api/products')  # 监听匹配 URL 的请求

page.get('https://example.com/shop')
# 等待并获取数据包
packet = page.listen.wait(timeout=10)
if packet:
    print(packet.url)            # 请求 URL
    print(packet.method)        # GET / POST
    print(packet.response.body) # 响应体(通常为 JSON)

page.listen.stop()

通过 listen 捕获后台 API 响应,你可以跳过 HTML 解析,直接获取结构化 JSON 数据。这在 DrissionPage web scraping 中是一个关键技巧——许多现代网站通过 XHR 加载数据,监听网络流量比解析 DOM 更可靠。

配置 DrissionPage 代理:SessionPage 与 ChromiumPage

在 DrissionPage 中配置代理需要区分两种模式。SessionPage 使用 set.proxies() 方法,而 ChromiumPage 通过 ChromiumOptions.set_proxy() 设置。DrissionPage proxy 配置的核心区别在于:HTTP 模式走 requests 的代理机制,浏览器模式走 Chromium 的代理机制。

SessionPage 代理配置

from DrissionPage import SessionPage

page = SessionPage()
page.set.proxies({
    'http': 'http://user-country-US:pass@gate.proxyhat.com:8080',
    'https': 'http://user-country-US:pass@gate.proxyhat.com:8080'
})

page.get('https://httpbin.org/ip')
print(page.json)

ChromiumPage 代理配置

from DrissionPage import ChromiumPage, ChromiumOptions

co = ChromiumOptions()
co.set_proxy('http://user-country-US:pass@gate.proxyhat.com:8080')
co.headless()

page = ChromiumPage(co)
page.get('https://httpbin.org/ip')
print(page.ele('tag:pre').text)

对于硬目标网站(如电商、社交媒体、票务平台),数据中心 IP 往往被直接封禁。住宅代理使用真实 ISP 分配的 IP 地址,请求看起来来自普通家庭用户,因此成功率显著更高。ProxyHat 提供覆盖全球的住宅代理网络,支持国家/城市级地理定位,查看 可用代理位置 了解覆盖范围。

完整示例:WebPage 双模式 + ProxyHat 住宅代理

下面是一个完整的可运行示例,展示 WebPage 如何在 HTTP 模式和浏览器模式之间切换,同时保持代理和会话状态。我们使用 ProxyHat 的住宅代理端点,通过用户名参数实现地理定位和会话固定。

首先,创建一个 ProxyHat 用户名构建器:

class ProxyHatConfig:
    GATEWAY = 'gate.proxyhat.com'
    HTTP_PORT = 8080
    SOCKS5_PORT = 1080

    @staticmethod
    def build_username(country=None, city=None, session=None):
        parts = ['user']
        if country:
            parts.append(f'country-{country}')
        if city:
            parts.append(f'city-{city}')
        if session:
            parts.append(f'session-{session}')
        return '-'.join(parts)

    @classmethod
    def http_url(cls, country=None, city=None, session=None):
        username = cls.build_username(country, city, session)
        return f'http://{username}:pass@{cls.GATEWAY}:{cls.HTTP_PORT}'

    @classmethod
    def socks5_url(cls, country=None, city=None, session=None):
        username = cls.build_username(country, city, session)
        return f'socks5://{username}:pass@{cls.GATEWAY}:{cls.SOCKS5_PORT}'

然后,使用 WebPage 实现双模式采集:

from DrissionPage import WebPage, ChromiumOptions
import uuid

# 构建 ProxyHat 住宅代理 URL
session_id = str(uuid.uuid4())[:8]
proxy_url = ProxyHatConfig.http_url(
    country='US',
    session=session_id
)

# 创建 WebPage,初始使用 HTTP 模式
page = WebPage()
page.set.proxies({
    'http': proxy_url,
    'https': proxy_url
})

# 第一步:HTTP 模式获取列表页(快速、低开销)
page.get('https://example.com/products?page=1')
links = page.eles('tag:a@class=product-link')
product_urls = [link.attr('href') for link in links[:5]]
print(f'HTTP 模式获取到 {len(product_urls)} 个产品链接')

# 第二步:切换到 Chromium 模式渲染 JS 详情页
co = ChromiumOptions()
co.set_proxy(proxy_url)
co.headless()

page.change_mode(co)  # 切换到浏览器模式,cookies 自动传递

# 监听后台 API
page.listen.start('api/product-detail')

for url in product_urls[:3]:
    page.get(url)
    packet = page.listen.wait(timeout=15)
    if packet:
        data = packet.response.body
        print(f'产品数据: {data[:200]}')
    else:
        # 降级为 DOM 解析
        title = page.ele('h1').text
        print(f'产品名称: {title}')

page.listen.stop()
page.quit()

这个示例展示了 DrissionPage 的核心优势:先用 SessionPage 快速抓取列表页(每个请求约 200ms),再切换到 ChromiumPage 渲染需要 JS 执行的详情页。代理在两种模式下保持一致,cookies 自动传递,无需手动管理会话。

生产级模式:会话固定、重试与并发

会话固定(Sticky Session)

许多网站要求同一会话使用同一 IP(登录后操作、多步表单等)。ProxyHat 支持通过用户名中的 session-xxx 参数固定 IP。在 DrissionPage 中,为每个 WebPage 实例分配独立的 session ID:

import uuid
from DrissionPage import WebPage

def create_pinned_session(country='US'):
    session_id = str(uuid.uuid4())[:8]
    proxy = ProxyHatConfig.http_url(
        country=country,
        session=session_id
    )
    page = WebPage()
    page.set.proxies({'http': proxy, 'https': proxy})
    return page, session_id

# 每个任务使用独立的 sticky session
page, sid = create_pinned_session('US')
# 同一 session_id 在有效期内保持同一出口 IP

重试与错误处理

import time
from DrissionPage.errors import ElementNotFoundError

def safe_get(page, url, max_retries=3):
    for attempt in range(max_retries):
        try:
            resp = page.get(url, timeout=15)
            if resp and page.status_code == 200:
                return page
            print(f'尝试 {attempt+1} 失败: HTTP {page.status_code}')
        except ElementNotFoundError:
            print(f'尝试 {attempt+1} 失败: 元素未找到')
        except Exception as e:
            print(f'尝试 {attempt+1} 失败: {e}')
        time.sleep(2 ** attempt)  # 指数退避
    return None

并发控制

DrissionPage 本身不提供并发管理,但可以与 concurrent.futuresasyncio 配合使用。关键原则:

  • SessionPage 模式下,每个线程使用独立的 WebPage 实例和独立代理 session ID。
  • ChromiumPage 模式下,每个浏览器实例约占用 300-500 MB 内存。一台 16 GB 内存的服务器建议最多运行 20-30 个并发浏览器实例。
  • 设置合理的请求间隔(1-3 秒),避免触发目标网站的频率限制。
  • 使用 ProxyHat 的旋转代理模式(不指定 session)实现每请求换 IP,适合大规模 SERP 采集。参考 SERP 跟踪用例 了解更多。
from concurrent.futures import ThreadPoolExecutor, as_completed
import uuid

def scrape_task(url):
    session_id = str(uuid.uuid4())[:8]
    proxy = ProxyHatConfig.http_url(country='US', session=session_id)
    page = WebPage()
    page.set.proxies({'http': proxy, 'https': proxy})
    try:
        page.get(url, timeout=15)
        result = page.ele('h1').text if page.ele('h1') else 'N/A'
        return url, result
    finally:
        page.close()

urls = ['https://example.com/page/1', 'https://example.com/page/2']
with ThreadPoolExecutor(max_workers=10) as executor:
    futures = [executor.submit(scrape_task, url) for url in urls]
    for f in as_completed(futures):
        url, result = f.result()
        print(f'{url}: {result}')

通过 listen 发现隐藏 API

许多现代网站将数据放在后台 XHR 请求中,前端只负责渲染。通过 listen.start() 监听网络流量,你可以发现这些隐藏的 API 端点,然后直接用 SessionPage 调用它们——无需浏览器渲染。这是从 ChromiumPage 降级到 SessionPage 的关键发现手段。

# 第一步:用浏览器模式监听,发现 API
page = ChromiumPage(co)
page.listen.start('api/')  # 监听所有 API 请求
page.get('https://target-site.com')
# 收集所有 API 端点
for _ in range(10):
    pkt = page.listen.wait(timeout=5)
    if pkt:
        print(f'发现 API: {pkt.url} -> {pkt.response.status}')
page.listen.stop()
page.quit()

# 第二步:切换到 SessionPage 直接调用 API
sp = SessionPage()
sp.set.proxies({'http': proxy_url, 'https': proxy_url})
sp.get('https://target-site.com/api/data?page=1')
data = sp.json  # 直接获取 JSON

什么时候不要升级到浏览器

DrissionPage 的双模式设计很强大,但并非所有场景都需要浏览器。以下情况应保持 SessionPage 模式:

  • 目标页面是静态 HTML:如果页面源码中已包含所需数据,用 SessionPage 即可,延迟约 200ms,而浏览器渲染需要 2-5 秒。
  • 已发现后台 API:通过 listen 发现 JSON API 后,直接用 SessionPage 调用,效率高 10 倍以上。
  • 大规模列表页采集:数千个列表页用 HTTP 模式可以在几分钟内完成,浏览器模式则需数小时。
  • 仅需 HTTP header 交互:设置 cookies、发送 POST 请求等,SessionPage 完全够用。

反之,以下情况需要升级到 ChromiumPage:

  • 页面数据由 JavaScript 动态生成,源码中不存在。
  • 需要与页面交互(点击、滚动、填表)。
  • 目标网站使用 Cloudflare Turnstile 或 reCAPTCHA 等 JS 验证。
  • 需要截图或下载文件。

更多爬虫场景的最佳实践,参考 Web Scraping 用例页面。ProxyHat 的 官方文档 提供了完整的代理配置参数说明。

关键要点

  • 双模式是核心价值:DrissionPage 的 WebPage 让你在 SessionPage(HTTP)和 ChromiumPage(浏览器)之间无缝切换,共享 cookies 和代理,按需付费——只在必要时才启动浏览器。
  • 代理配置分两路:SessionPage 用 set.proxies(),ChromiumPage 用 ChromiumOptions.set_proxy()。ProxyHat 住宅代理通过 gate.proxyhat.com:8080 接入。
  • listen 是杀手锏:用 listen.start() 监听浏览器网络流量,发现隐藏 API 后降级到 HTTP 模式,效率提升 10 倍以上。
  • 会话固定很重要:通过用户名中的 session-xxx 参数为每个任务分配独立 sticky session,避免 IP 频繁切换导致封号。
  • 合规先行:只采集公开数据,遵守 robots.txt 和服务条款,了解 CFAA 和 GDPR 的法律边界。

DrissionPage + ProxyHat 住宅代理的组合,为 Python 爬虫开发者提供了一个兼具效率和隐蔽性的解决方案。从 ProxyHat 定价方案 开始,选择适合你业务规模的代理套餐,然后按照本教程的示例快速集成到你的 DrissionPage 项目中。

准备开始了吗?

通过AI过滤访问148多个国家的5000多万个住宅IP。

查看价格住宅代理
← 返回博客