Chrome DevTools Protocol (CDP) 详解
一、概述
Chrome DevTools Protocol(简称 CDP)是 Chrome 浏览器提供的远程调试协议,它允许外部程序通过 WebSocket 连接与 Chrome 进行双向通信,从而程序化地控制浏览器行为。Chrome DevTools 本身就是通过这个协议与浏览器交互的。
二、架构
code复制
scss
┌─────────────┐ WebSocket ┌──────────────────┐
│ 外部客户端 │ ◄──────────────► │ Chrome Browser │
│ (Node/Python) │ JSON-RPC │ (DevTools Agent) │
└─────────────┘ └──────────────────┘
核心组成:
| 组件 | 说明 |
|---|---|
| DevTools Frontend | Chrome 开发者工具 UI |
| DevTools Agent | 浏览器内嵌的协议服务端 |
| WebSocket 通道 | 通信载体,基于 JSON-RPC 2.0 |
三、连接方式
1. 启动带调试端口的 Chrome
bash复制
ini
# macOS
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \
--remote-debugging-port=9222
# 指定用户数据目录(避免冲突)
--user-data-dir=/tmp/chrome-debug
2. 发现可调试目标
bash复制
bash
curl http://localhost:9222/json
返回类似:
json复制
css
[ { "description": "", "devtoolsFrontendUrl": "...", "id": "ABC123", "title": "New Tab", "type": "page", "url": "chrome://newtab/", "webSocketDebuggerUrl": "ws://localhost:9222/devtools/page/ABC123"}]
3. 建立 WebSocket 连接
javascript复制
javascript
const WebSocket = require('ws');
const ws = new WebSocket('ws://localhost:9222/devtools/page/ABC123');
ws.on('open', () => {
// 发送 CDP 命令
ws.send(JSON.stringify({
id: 1,
method: 'Page.navigate',
params: { url: 'https://example.com' }
}));
});
ws.on('message', (data) => {
console.log(JSON.parse(data));
});
四、协议格式
CDP 基于 JSON-RPC 2.0,有两种消息类型:
1. 请求/响应(Command)
json复制
json
// 请求
{
"id": 1,
"method": "Runtime.evaluate",
"params": {
"expression": "document.title"
}
}
// 响应
{
"id": 1,
"result": {
"result": {
"type": "string",
"value": "Example Domain"
}
}
}
2. 事件(Event)
json复制
json
{
"method": "Network.responseReceived",
"params": {
"requestId": "1001",
"response": {
"url": "https://example.com/api",
"status": 200,
"mimeType": "application/json"
}
}
}
五、核心域(Domains)
CDP 将功能划分为多个域,每个域包含方法(Methods)和事件(Events):
| 域 | 用途 | 常用方法 |
|---|---|---|
| Page | 页面操作 | navigate, reload, captureScreenshot |
| Runtime | JS 执行环境 | evaluate, callFunctionOn, enable |
| Network | 网络监控 | enable, requestWillBeSent, getResponseBody |
| DOM | DOM 操作 | getDocument, querySelector, setAttributeValue |
| CSS | 样式操作 | getComputedStyleForNode, addRule |
| Emulation | 设备模拟 | setDeviceMetricsOverride, setTouchEmulationEnabled |
| Input | 输入模拟 | dispatchMouseEvent, dispatchKeyEvent, insertText |
| Target | 目标管理 | getTargets, createTarget, attachToTarget |
| Security | 安全控制 | handleCertificateError, setOverrideCertificateErrors |
| Performance | 性能监控 | enable, getMetrics |
| Console | 控制台 | enable, messageAdded |
六、常用场景与示例
1. 截图
json复制
json
{
"id": 1,
"method": "Page.captureScreenshot",
"params": {
"format": "png",
"quality": 90
}
}
2. 执行 JavaScript
json复制
json
{
"id": 2,
"method": "Runtime.evaluate",
"params": {
"expression": "document.querySelectorAll('a').length",
"returnByValue": true
}
}
3. 监控网络请求
json复制
json
// 1. 启用网络域
{ "id": 1, "method": "Network.enable" }
// 2. 监听事件 → Network.requestWillBeSent
// 3. 监听事件 → Network.responseReceived
// 4. 获取响应体
{
"id": 2,
"method": "Network.getResponseBody",
"params": { "requestId": "xxx" }
}
4. 模拟点击
json复制
json
{
"id": 1,
"method": "Input.dispatchMouseEvent",
"params": {
"type": "mousePressed",
"x": 100,
"y": 200,
"button": "left",
"clickCount": 1
}
}
{
"id": 2,
"method": "Input.dispatchMouseEvent",
"params": {
"type": "mouseReleased",
"x": 100,
"y": 200,
"button": "left",
"clickCount": 1
}
}
七、主流工具库
| 工具 | 语言 | 特点 |
|---|---|---|
| Puppeteer | Node.js | Google 官方,高级 API 封装,最流行 |
| Playwright | Node/Python/Java/.NET | 跨浏览器,API 更现代 |
| chrome-remote-interface | Node.js | CDP 的底层薄封装,灵活 |
| CDP4J | Java | Java 生态的 CDP 客户端 |
| Pyppeteer | Python | Puppeteer 的 Python 移植版 |
Puppeteer 示例
javascript复制
javascript
const puppeteer = require('puppeteer');
const browser = await puppeteer.launch({
headless: true,
args: ['--remote-debugging-port=9222']
});
// Puppeteer 内部就是通过 CDP 与浏览器通信
const page = await browser.newPage();
// 可以直接访问 CDP Session
const cdp = await page.createCDPSession();
await cdp.send('Network.enable');
cdp.on('Network.requestWillBeSent', (e) => {
console.log('Request:', e.params.request.url);
});
await page.goto('https://example.com');
八、高级特性
1. 多 Target 管理
json复制
json
// 获取所有可调试目标
{ "id": 1, "method": "Target.getTargets" }
// 创建新标签页
{
"id": 2,
"method": "Target.createTarget",
"params": { "url": "https://example.com" }
}
// 附加到指定目标
{
"id": 3,
"method": "Target.attachToTarget",
"params": { "targetId": "ABC123", "flatten": true }
}
2. 设备模拟
json复制
json
{
"id": 1,
"method": "Emulation.setDeviceMetricsOverride",
"params": {
"width": 375,
"height": 812,
"deviceScaleFactor": 3,
"mobile": true
}
}
3. 拦截和修改请求
json复制
json
// 启用请求拦截
{ "id": 1, "method": "Network.setRequestInterception", "params": { "patterns": [{ "urlPattern": "*.js" }] } }
// 在事件 Network.requestIntercepted 中决定继续或修改
{
"id": 2,
"method": "Network.continueInterceptedRequest",
"params": {
"interceptionId": "xxx",
"rawResponse": "<base64 encoded response>"
}
}
九、安全注意事项
| 风险 | 说明 |
|---|---|
| 端口暴露 | 调试端口可被同网络机器访问,生产环境禁止开启 |
| 代码执行 | CDP 可执行任意 JS,等价于完全控制浏览器 |
| Cookie 窃取 | 可通过 Network.getCookies 获取所有 Cookie |
| 建议 | 仅绑定 127.0.0.1,使用后关闭端口 |
十、协议文档
- 官方文档 :chromedevtools.github.io/devtools-pr...
- 源码定义 :Chrome 源码中的
.pd文件 - 版本对应:每个 Chrome 版本的 CDP 域/方法可能略有差异
CDP 是浏览器自动化、爬虫、性能测试、UI 测试等场景的底层基石。Puppeteer 和 Playwright 等工具虽然提供了更友好的高层 API,但理解 CDP 本身能让你在遇到复杂需求时(如拦截请求、注入代码、监控性能指标)直接操作协议层面,获得最大灵活性。
以上就是 Chrome DevTools Protocol 的完整介绍。如果你对某个具体域(如 Network 拦截、Performance 监控)或实战场景(爬虫、自动化测试)有更深入的需求,可以继续问我!