第一章、Chrome DevTools Protocol (CDP) 详解

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,使用后关闭端口

十、协议文档


CDP 是浏览器自动化、爬虫、性能测试、UI 测试等场景的底层基石。Puppeteer 和 Playwright 等工具虽然提供了更友好的高层 API,但理解 CDP 本身能让你在遇到复杂需求时(如拦截请求、注入代码、监控性能指标)直接操作协议层面,获得最大灵活性。

以上就是 Chrome DevTools Protocol 的完整介绍。如果你对某个具体域(如 Network 拦截、Performance 监控)或实战场景(爬虫、自动化测试)有更深入的需求,可以继续问我!

相关推荐
前端之虎陈随易9 小时前
编程语言级别的Skill市场,AI Agent 的未来形态
前端·vue.js·人工智能·typescript·node.js
一路向北he9 小时前
字节钢铁军团--“提供情境,而非控制”
java·开发语言·前端
kyriewen10 小时前
豆包和千问同时关了智能体,我用它们搭的 3 个自动化全废了——迁移方案整理
前端·javascript·ai编程
前端一小卒10 小时前
我用 TypeScript 从零手写了一个 Claude Code,然后发现它的核心只有 30 行
前端·agent
铁皮饭盒10 小时前
用 Bun.cron 定时 7 月 7 日,为啥? 看图1
javascript
大圣编程12 小时前
Python中continue语句的用法是什么?
开发语言·前端·python
yuhaiqiang12 小时前
随手 vibecoding 的浏览器插件已经 6000 多次下载,聊聊他的产品设计
前端·后端·面试
之歆12 小时前
Vue商品详情与放大镜组件
前端·javascript·vue.js
再吃一根胡萝卜13 小时前
如何把小米 MiMo 接入 CodeBuddy,打造私有 Agent
前端
负责的蛋挞14 小时前
异步HttpModule的实现方式
java·服务器·前端