Chrome DevTools Protocol 入门:相关概念

前言

在上篇文章中,我们快速地使用了 Chrome DevTools Protocol(CDP)发送指令,成功实现了一些浏览器自动化操作。然而,要想深入使用 CDP,还需要对其中的 协议概念 有更深入的理解。这些概念不仅是我们与浏览器交互的基础,还决定了我们如何构建更复杂、更灵活的调试和自动化操作。为了让这些概念更容易理解,我们将在这里通过实例化的方式,打一些比方,让抽象的概念变得更加具象化。


1. 域(Domain) —— 功能模块的“房间”

想象一下,Chrome DevTools Protocol 是一栋大房子,而这栋房子有很多房间,每个房间都有不同的功能区域。每个房间就是一个 域(Domain)。比如:

  • Page 就像一个专门用于管理页面导航、截图、事件的房间。
  • Network 房间负责监控和处理所有的网络请求,像是管家在查看有哪些资源进出。
  • DOM 房间则是维护和操作网页的 DOM 树结构,类似一个园丁在修剪和修改网页中的元素。

这些“房间”之间是相互独立的,你需要去到不同的房间(域)才能执行特定的操作。比如你要修改页面的样式,就得进入 CSS 这个房间;而如果你想调试 JavaScript,则需要进入 Debugger 房间。

每个房间中有不同的 方法事件,这正是你可以利用的“工具”和“提醒”。


2. 方法(Method) —— 房间中的“操作工具”

在每个“房间”中,我们有各种工具来完成不同的操作。这些工具就是 CDP 中的 方法(Method)。可以把方法想象成每个房间里的“按钮”,按下不同的按钮,就会触发不同的行为:

  • Page 房间中,按下 Page.navigate 按钮,就会让页面导航到指定的 URL,好像打开了一扇新的门,进入了另一个房间。
  • Runtime 房间中,按下 Runtime.evaluate 按钮,就像在房间里执行一段代码,告诉房间该做什么事情。

每个方法通常需要一些 输入参数,这些参数就像是操作工具时所需的说明书。如果你要导航页面,你得告诉 Page.navigate 按钮:“我要去的目标 URL 是什么”。同样,工具执行后通常也会给你一个 返回值,告诉你执行的结果如何,比如页面是否成功导航。

类比:

想象你进入一个 Page 房间,看到墙上有个大按钮,上面写着“导航”。你输入目标地址按下按钮(调用方法时传递参数),浏览器就会载入该页面,并告诉你“页面已经打开”(返回结果)。


3. 事件(Event) —— 自动弹出的“提醒信号”

在每个房间里,不仅有工具可以操作,有时候你会收到一些 提醒信号(事件),告诉你房间里发生了什么变化。这些 事件(Event) 是浏览器主动发出的消息,类似房间中突然响起的警报,告诉你某件事情发生了。

  • 比如在 Page 房间中,当页面加载完成时,系统会自动发出 Page.loadEventFired 事件,就像一个完成通知,提醒你“页面加载已经完成”。
  • Network 房间中,当网络请求发出时,浏览器会发出 Network.requestWillBeSent 事件,提醒你“有一个网络请求刚刚发送”。

事件是被动的,你并不需要主动按下什么按钮或发出请求来获取它们。你只需要订阅这些事件,当事件触发时,浏览器会自动通知你。你就像在房间里安装了监控设备,房间发生了某些事情,它会立刻通知你。

类比:

想象你正在 Network 房间里走动,突然一盏红灯闪烁起来,显示“有新的请求正在发送”(Network.requestWillBeSent 事件)。你可以根据这个提示决定接下来要做的操作,比如拦截或查看这个请求。


4. 类型(Type) —— 方法和事件的“数据结构”

无论是方法的输入参数还是事件的输出结果,所有的数据都需要以某种结构表示出来。这些数据结构就是 类型(Type)。可以把 类型 看作是传递消息时使用的“容器”或“数据模型”。

  • 比如在 DOM 房间里,你可以拿到一个 DOM.Node 类型的对象,这个对象就像一个树形图,里面包含了节点的详细信息,如节点的 ID、名称和子节点数量。
  • Network 房间里,事件返回的 Network.Request 对象包含请求的详细信息,比如 URL、请求头等。

类型 保证了数据的结构化,让浏览器和客户端之间的数据交互更加清晰和有序。你可以理解为,房间里的“工具”所接收的指令(参数)和它们返回的结果都装在特定形状的盒子(类型)里,盒子的结构要符合工具的预期。

类比:

比如,你需要给 Runtime.evaluate 方法传递一段 JavaScript 代码,代码这个数据需要装在一个特定的“盒子”里,这个盒子就是 expression 类型的参数。返回结果时,浏览器会给你另一个特定的“盒子”,里面是执行后的结果数据,比如它的值和类型。


实例:通过 CDP 控制页面的导航与监控

下面是一个使用 Pythonwebsockets 库的示例,展示如何通过 Chrome DevTools Protocol (CDP) 使用 WebSocket 连接控制页面导航并监控事件。我们将实现以下功能:

  1. 通过 WebSocket 连接到 Chrome DevTools Protocol。
  2. 使用 Page.navigate 指令导航到指定页面。
  3. 订阅 Page.loadEventFired 事件,监控页面加载完成。
  4. 订阅 Network.requestWillBeSent 事件,监控页面发出的网络请求。

环境准备

首先,确保你已经安装了 websockets 库:

pip install websockets

示例代码

import asyncio
import websockets
import json

# Chrome DevTools Protocol WebSocket URL (replace with actual URL from http://localhost:9222/json/qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq)
ws_url = 'ws://localhost:9222/devtools/page/{your-page-id}'

# Message ID counter
message_id = 0

# Function to send messages over WebSocket
async def send_message(ws, method, params=None):
    global message_id
    message_id += 1
    message = {
        'id': message_id,
        'method': method,
    }
    if params:
        message['params'] = params
    await ws.send(json.dumps(message))
    print(f"Sent: {message}")

# Function to navigate to a page
async def navigate_to_page(ws, url):
    await send_message(ws, 'Page.navigate', {'url': url})

# Function to enable domains like Page and Network
async def enable_domains(ws):
    await send_message(ws, 'Page.enable')
    await send_message(ws, 'Network.enable')

# Function to handle received messages
async def handle_message(message):
    data = json.loads(message)

    # Page load event fired
    if data.get('method') == 'Page.loadEventFired':
        print("Page has finished loading.")

    # Network request sent
    if data.get('method') == 'Network.requestWillBeSent':
        request = data['params']['request']
        print(f"Network request sent: {request['url']}")

# Main function to run WebSocket client
async def run():
    async with websockets.connect(ws_url) as ws:
        print("Connected to Chrome DevTools Protocol")

        # Enable Page and Network domains
        await enable_domains(ws)

        # Navigate to a test page
        await navigate_to_page(ws, 'https://example.com')

        # Listen for events and responses
        while True:
            message = await ws.recv()
            await handle_message(message)

# Run the WebSocket client
asyncio.get_event_loop().run_until_complete(run())

代码解释

  1. ws_url: 你需要从 Chrome 获取实际的 webSocketDebuggerUrl,通过访问 http://localhost:9222/json/version 获取。
  2. send_message: 这个函数负责通过 WebSocket 向 Chrome 发送 CDP 指令。每条指令都有唯一的 idmethod,有些指令还需要 params
  3. navigate_to_page: 调用 Page.navigate 指令,将浏览器导航到指定 URL。
  4. enable_domains: 启用 PageNetwork 域,以便接收相关的事件。
  5. handle_message: 根据接收到的事件进行处理。当 Page.loadEventFired 触发时,表示页面加载完成。当 Network.requestWillBeSent 触发时,捕获并打印出网络请求信息。
  6. run: 主函数,首先通过 WebSocket 连接到 Chrome,然后发送指令并接收事件。

运行步骤

  1. 打开 Chrome 并启用远程调试,使用命令行启动 Chrome:

bash复制代码chrome.exe --remote-debugging-port=9222

  1. 访问 http://localhost:9222/json/version,找到对应的 webSocketDebuggerUrl,并替换代码中的 {your-page-id}
  2. 运行该 Python 脚本:

bash复制代码python your_script.py

结果

  • 脚本将打开一个新页面导航到 https://example.com。
  • 当页面加载完成时,脚本会输出 "Page has finished loading"
  • 每当页面发出网络请求时,脚本会输出请求的 URL。

这个示例演示了如何通过 CDP 使用 Python 和 WebSocket 实现页面控制和事件监控。在实际项目中,你可以扩展代码来处理更多的指令和事件。


总结

通过这些实例化的比喻和解释,我们可以更直观地理解 Chrome DevTools Protocol 中的 方法事件类型。它们就像一个复杂的建筑体系,每个房间(域)负责不同的功能,每个按钮(方法)执行特定的操作,事件是自动发出的提醒信号,而数据则装在特定的盒子里(类型)进行传递。理解这些概念后,我们可以更加灵活高效地使用 CDP 来完成调试、自动化任务。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/916865.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用 PyAnsys 在 Ansys 随机振动分析中检索螺栓连接中的力和应力

介绍 随机振动模拟通常用于评估组件承受运输过程中振动的能力。随机振动分析利用先前模态分析的频率和模式内容对通过功率谱密度 (PSD) 负载定义的频谱和功率内容进行线性叠加。在大多数装配模型中,螺栓连接(由求解器变为 BEAM188 元素)通常…

1 图的搜索 奇偶剪枝

图论——图的搜索_Alex_McAvoy的博客-CSDN博客 语雀版本 1 深度优先搜索DFS 1. 从图中某个顶点 v0 出发,首先访问 v0 2. 访问结点 v0 的第一个邻接点,以这个邻接点 vt 作为一个新节点,访问 vt 所有邻接点,直到以 vt 出发的所有节…

ElasticSearch-全文检索(一)基本介绍

简介 Elasticsearch:官方分布式搜索和分析引擎 | Elastic 全文搜索属于最常见的需求,开源的Elasticsearch是目前全文搜索引擎的首选。 它可以快速地储存、搜索和分析海量数据。维基百科、StackOverflow、Github都采用它 Elastic的底层是开源库Lucene。但…

Opengl光照测试

代码 #include "Model.h" #include "shader_m.h" #include "imgui.h" #include "imgui_impl_glfw.h" #include "imgui_impl_opengl3.h" //以上是放在同目录的头文件#include <glad/glad.h> #include <GLFW/glfw3.…

传奇996_19——龙岭总结

功能&#xff1a; 切割 切割属性&#xff1a; 即人物属性&#xff0c;可以设置临时属性或者永久属性&#xff0c;龙岭使用的是临时属性&#xff0c;所谓临时就是存在有效期&#xff0c;龙岭设置的有效期是123456789秒&#xff0c;即1428.89802天。 龙岭写法&#xff08;倒叙…

亲测有效:Maven3.8.1使用Tomcat8插件启动项目

我本地maven的settings.xml文件中的配置&#xff1a; <mirror><id>aliyunmaven</id><mirrorOf>central</mirrorOf><name>阿里云公共仓库</name><url>https://maven.aliyun.com/repository/public</url> </mirror>…

关于 MSVCP110.dll 缺失的解决方案

背景&#xff1a;之前使用 PR&#xff08;Adobe Premiere&#xff09; 从来没有遇到过这样的问题。今天重装系统后&#xff08;window 10&#xff09;&#xff0c;想要重新安装以前的软件时&#xff0c;遇到了以下 DLL 文件缺失的错误。 解决方案&#xff1a; 可以到微软官网的…

贝叶斯网络——基于概率的图模型(详解)

贝叶斯网络&#xff08;Bayesian Network&#xff0c;简称BN&#xff09;是一种基于概率图模型的表示方法&#xff0c;用于表示变量之间的依赖关系&#xff0c;并通过条件概率推断变量间的关系。它通过有向无环图&#xff08;DAG&#xff09;来描述变量之间的依赖关系&#xff…

嵌入式硬件电子电路设计(五)MOS管详解(NMOS、PMOS、三极管跟mos管的区别)

引言&#xff1a;在我们的日常使用中&#xff0c;MOS就是个纯粹的电子开关&#xff0c;虽然MOS管也有放大作用&#xff0c;但是几乎用不到&#xff0c;只用它的开关作用&#xff0c;一般的电机驱动&#xff0c;开关电源&#xff0c;逆变器等大功率设备&#xff0c;全部使用MOS管…

cocoscreator-doc-TS-脚本开发-获取和设置资源

资源属性的声明 cc.Asset 的子类下面这些 cc.Texture2D、cc.SpriteFrame、cc.AnimationClip、cc.Prefab 等 加载场景&#xff0c;会自动加载场景关联的资源 &#xff0c;再加载关联的资源所关联的资源&#xff0c;直到全加载 在属性检查器中设置资源 property(cc.Label) la…

在Keil删除原有的组出现系统软件无响应的原因

取消掉core的勾选。 keil 添加文件夹&#xff0c;软件崩溃解决办法_keil5创建文件夹卡死-CSDN博客

超越传统:探索ONLYOFFICE的革命性办公新纪元

目录 &#x1f341;引言 &#x1f341;一、ONLYOFFICE产品简介 &#xff08;一&#xff09;、介绍 &#xff08;二&#xff09;、基本功能简介 &#x1f341;二、核心功能具体介绍 1、编辑操作 2、文本与段落&#xff1a; 3、样式与图形&#xff1a; 4、表格与图表&…

一文说清libc、glibc、glib的发展和关系

一 引言 在大家的技术生涯中&#xff0c;一定会遇到glib、glibc、libc这些个名词。 尤其像我这种对英文名脸盲的人&#xff0c;看着它们就头大&#xff0c;因为单从名字上看&#xff0c;也太像了&#xff0c;所以经常容易混淆。 即使翻翻网上的资料&#xff0c;看完还是有点懵…

OceanBase 升级过程研究(4.2.1.6-4.2.1.8)

模拟业务 使用benchmark加载10仓数据模拟业务场景 升级方法 使用滚动升级方式来进行OB升级。该方法前提是OB集群必须满足官方规定的高可用架构(如果 Zone 个数小于 3&#xff0c;滚动升级时则无法构成多数派), 滚动升级的原理就是轮流完成每个ZONE的升级工作&#xff0c;由于…

使用 Ant Design Vue 自定渲染函数customRender实现单元格合并功能rowSpan

使用 Ant Design Vue 自定渲染函数customRender实现单元格合并功能rowSpan 背景 在使用Ant Design Vue 开发数据表格时&#xff0c;我们常常会遇到需要合并单元格的需求。 比如&#xff0c;某些字段的值可能会在多行中重复出现&#xff0c;而我们希望将这些重复的单元格合并为…

Godot的开发框架应当是什么样子的?

目录 前言 全局协程还是实例协程&#xff1f; 存档&#xff01; 全局管理类&#xff1f; UI框架&#xff1f; Godot中的异步&#xff08;多线程&#xff09;加载 Godot中的ScriptableObject 游戏流程思考 结语 前言 这是一篇杂谈&#xff0c;主要内容是对我…

ssm118亿互游在线平台设计与开发+vue(论文+源码)_kaic

毕业设计(论文) 亿互游在线平台的设计与开发 学生姓名 XXX 学 号 XXXXXXXX 分院名称 XXXXXXXX 专业班级 XXXXX 指导教师 XXXX 填写日期 XXXX年…

MySQL技巧之跨服务器数据查询:基础篇-A数据库与B数据库查询合并

MySQL技巧之跨服务器数据查询&#xff1a;基础篇-A数据库与B数据库查询合并 上一篇已经描述&#xff1a;借用微软的SQL Server ODBC 即可实现MySQL跨服务器间的数据查询。 而且还介绍了如何获得一个在MS SQL Server 可以连接指定实例的MySQL数据库的链接名: MY_ODBC_MYSQL 以…

LLaMA-Factory全流程训练模型

&#x1f917;本文主要讲述在docker下使用LLaMA-Factory训练推理模型。 &#x1fae1;拉取镜像 首先需要启动docker&#xff0c;然后在终端中输入&#xff1a; docker run -tid --gpus all -p 8000:8000 --name LLM -e NVIDIA_DRIVER_CAPABILITIEScompute,utility -e NVIDIA…

英语每日一句

目录 每日一句今日单词知识加餐 每日一句 We will fail when we fail to try. 当我们不努力的时候&#xff0c;我们就会失败。 —— 罗莎帕克斯 今日单词 fail /feɪl/ v. 不及格&#xff1b;失败&#xff1b;未能&#xff08;做到&#xff09;&#xff1b;失灵&#xff1b…