
本文详解如何在SeleniumBase中正确启用CDP事件监听(而非依赖已弃用的get_log("performance")),通过RequestWillBeSent和ResponseReceived事件实时捕获Fetch/XHR请求及响应元数据,并支持后续调用Network.getResponseBody获取原始响应体。
本文详解如何在seleniumbase中正确启用cdp事件监听(而非依赖已弃用的`get_log("performance")`),通过`requestwillbesent`和`responsereceived`事件实时捕获fetch/xhr请求及响应元数据,并支持后续调用`network.getresponsebody`获取原始响应体。
SeleniumBase 的 log_cdp=True 参数并不等价于传统 Selenium 的 "goog:loggingPrefs" 配置——它仅启用底层 CDP 日志输出(如调试信息),无法直接替代 Performance Log 的结构化网络事件捕获。driver.get_log("performance") 在 SeleniumBase 中默认不可用,因其底层驱动(尤其是 UC 模式)未启用 Chrome 的性能日志记录通道,且该机制在 Headless 模式下本就受限(Chrome 官方已明确不保证 Headless 下 performance log 的完整性)。真正可靠、跨模式(Headless/Headful)、细粒度可控的方案是 SeleniumBase 内置的 CDP Mode。
CDP Mode 提供了对 Chrome DevTools Protocol 的原生封装,允许开发者注册异步事件处理器,精准监听网络生命周期关键节点。核心事件包括:
-
network.RequestWillBeSent:请求发出前,可获取方法、URL、Headers、POST 数据等; -
network.ResponseReceived:响应头到达时触发,含状态码、Content-Type、重定向信息等; - (进阶)
network.GetResponseBody:需在ResponseReceived后显式调用,以获取压缩/解码后的响应体内容(需注意 Content-Encoding 和文本编码)。
以下为生产级可用的完整示例(兼容 Windows + WSL Ubuntu,适配 Chrome 131+):
import colorama
import sys
from seleniumbase import SB
# 注意:mycdp 是 SeleniumBase 内置模块,无需额外安装
from seleniumbase.common.mycdp import network
c1 = colorama.Fore.BLUE + colorama.Back.LIGHTYELLOW_EX
c2 = colorama.Fore.BLUE + colorama.Back.LIGHTGREEN_EX
cr = colorama.Style.RESET_ALL
# Linux/WSL 环境下禁用 ANSI 颜色避免乱码
if "linux" in sys.platform or "wsl" in sys.platform.lower():
c1 = c2 = cr = ""
async def on_request(event: network.RequestWillBeSent):
req = event.request
print(c1 + f"? 请求发起: {req.method} {req.url}" + cr)
if req.post_data:
print(f" → POST 数据: {req.post_data[:100]}{'...' if len(req.post_data) > 100 else ''}")
async def on_response(event: network.ResponseReceived):
res = event.response
print(c2 + f"✅ 响应接收: {res.status} {res.url}" + cr)
# ✅ 关键:此处可安全调用 getResponseBody(需确保响应非流式且未被缓存)
try:
body = await event.page.cdp.network.get_response_body(res.request_id)
if body and body.text:
print(f" → 响应体长度: {len(body.text)} 字符")
# 示例:只打印 JSON 响应前 200 字符
if "application/json" in res.headers.get("content-type", "").lower():
print(f" → JSON 片段: {body.text[:200]}{'...' if len(body.text) > 200 else ''}")
except Exception as e:
# 处理常见异常:空响应、编码错误、流式响应(如 chunked)等
print(f" ⚠️ 获取响应体失败: {e}")
# 启动配置:UC 模式 + 显式 locale + 禁用无关扩展提升稳定性
with SB(
uc=True,
headless=True, # 支持 Headless 模式稳定运行
locale_code="en-US",
agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
disable_gpu=True,
no_sandbox=True,
) as sb:
# 必须先激活 CDP Mode(传入任意 URL 或 about:blank)
sb.activate_cdp_mode("about:blank")
# 注册事件处理器(类型提示增强可读性与 IDE 支持)
sb.cdp.add_handler(network.RequestWillBeSent, on_request)
sb.cdp.add_handler(network.ResponseReceived, on_response)
# 使用 CDP.open() 而非 driver.get(),确保页面上下文与 CDP 绑定
target_url = "https://httpbin.org/json"
sb.cdp.open(target_url)
# 等待关键响应完成(推荐使用 sb.wait_for_text_visible 或 sb.assert_element)
sb.sleep(3) # 简单等待;生产环境建议用显式等待
? 重要注意事项:
-
sb.cdp.open()是必须的:它确保页面加载全程处于 CDP 监控上下文中;sb.get()不触发 CDP 网络事件。 -
响应体获取限制:
Network.getResponseBody仅对非流式、非分块(non-chunked)、且未被浏览器缓存的响应有效。若返回No resource with given identifier found,说明响应已被释放或未启用Network.enable(SeleniumBase 已自动处理)。 -
Headless 兼容性:本方案在 Headless 模式下完全可用,且比
performance log更稳定——因 CDP 协议本身不依赖图形界面。 -
编码处理:响应体可能为 Base64 编码(如图片),需根据
response.headers["content-encoding"]和content-type判断并解码。 - 性能开销:高频请求场景下,建议按需注册事件(如仅监听特定 URL 正则),避免过度日志输出影响执行速度。
总结而言,放弃 get_log("performance") 的兼容性幻想,转向 CDP Mode 是 SeleniumBase 用户捕获网络流量的唯一现代、可靠、可维护路径。它不仅是技术升级,更是思维方式的转变:从被动读取日志,到主动订阅协议事件——让自动化真正具备“可观测性”与“可干预性”。










