Chrome DevTools Protocol 进阶:Runtime 域

前言

在 Chrome DevTools Protocol(CDP)中,Runtime 域是一个非常重要的部分,它主要用于与 JavaScript 的执行环境进行交互。通过 Runtime 域,开发者可以在页面上下文中执行 JavaScript 代码、评估表达式、捕获异常等操作,类似于在浏览器的控制台中手动输入代码的操作。Runtime 域的灵活性使得它在调试、测试和自动化任务中得到了广泛应用。

本文将详细介绍 CDP 的 Runtime 域,并通过几个示例展示如何使用它在浏览器中执行代码和处理结果。


Runtime 域简介

Runtime 域包含了一系列与 JavaScript 执行相关的命令和事件,用于控制和管理页面中的 JavaScript 执行环境。常见的功能包括:

  • 在页面上下文中执行任意 JavaScript 代码。
  • 获取 JavaScript 的执行结果。
  • 捕获和处理脚本执行时的异常。
  • 处理 JavaScript 的 promise 和异步操作。
  • 检查、调试 JavaScript 对象的属性和值。

Runtime 域常用命令

1. Runtime.evaluate — 执行 JavaScript 表达式

Runtime.evaluateRuntime 域中最常用的命令,它用于在页面的 JavaScript 上下文中评估一个表达式。这个命令可以在页面中执行任意的 JavaScript 代码,并返回执行结果。

请求结构:

{"id": 1,"method": "Runtime.evaluate","params": {"expression": "document.title","returnByValue": true}
}

参数说明:

  • expression: 需要执行的 JavaScript 表达式。例如,获取页面的 document.title
  • returnByValue: 指定返回结果时,是否将 JavaScript 对象以纯 JSON 格式返回。如果为 true,则会将值序列化后返回;如果为 false,则返回对象的引用。

返回结构:

{"id": 1,"result": {"result": {"type": "string","value": "Example Page Title"}}
}

在这个例子中,Runtime.evaluate 执行了表达式 document.title,并返回了当前页面的标题。

2. Runtime.callFunctionOn — 调用 JavaScript 函数

Runtime.callFunctionOn 命令允许开发者在指定的 JavaScript 对象上下文中调用一个函数。这个命令特别适合用于操作已有的 JavaScript 对象,例如 DOM 元素或自定义对象。

请求结构:

{"id": 2,"method": "Runtime.callFunctionOn","params": {"objectId": "1234.5",  // 目标对象的 ID"functionDeclaration": "function() { return this.innerHTML; }"}
}

参数说明:

  • objectId: JavaScript 对象的 ID,通常通过 Runtime.evaluate 获取到的对象引用。
  • functionDeclaration: 需要调用的 JavaScript 函数声明。

返回结构:

{"id": 2,"result": {"result": {"type": "string","value": "<p>Hello, World!</p>"}}
}

在此示例中,Runtime.callFunctionOn 被用于在特定 DOM 元素的上下文中调用一个函数,获取其 innerHTML 值。

3. Runtime.getProperties — 获取对象属性

Runtime.getProperties 命令用于获取 JavaScript 对象的属性和值。它在调试时非常有用,尤其当你想深入了解某个对象的结构或状态时。

请求结构:

{"id": 2,"result": {"result": {"type": "string","value": "<p>Hello, World!</p>"}}
}

参数说明:

  • objectId: JavaScript 对象的 ID。
  • ownProperties: 如果为 true,则只返回对象自身的属性,不包括继承的属性。

返回结构:

{"id": 3,"result": {"result": [{"name": "tagName","value": {"type": "string","value": "DIV"}},{"name": "innerHTML","value": {"type": "string","value": "<p>Hello, World!</p>"}}]}
}

通过这个命令,开发者可以获取对象的所有属性和值,并在调试过程中检查它们的状态。


异步操作和 Promise 处理

现代 JavaScript 应用广泛使用异步操作和 Promise 对象。Runtime 域同样提供了一些机制来处理这些异步操作。

1. Runtime.awaitPromise — 处理 Promise

Runtime.awaitPromise 命令可以等待一个 Promise 对象的解析(resolve)或拒绝(reject)。这在处理异步代码时非常有用。

请求结构:

{"id": 4,"method": "Runtime.evaluate","params": {"expression": "new Promise((resolve) => setTimeout(() => resolve(42), 1000))","awaitPromise": true}
}

返回结构:

{"id": 4,"result": {"result": {"type": "number","value": 42}}
}

在此例中,Runtime.evaluate 被用于执行一个延迟 1 秒后返回 42 的 Promise。通过设置 awaitPromise: true,我们可以等待 Promise 完成并直接获取其结果。


错误处理

在执行 JavaScript 代码时,错误和异常是不可避免的。Runtime 域提供了一些机制来捕获和处理这些错误,帮助开发者调试代码。

1. 捕获执行错误

Runtime.evaluateRuntime.callFunctionOn 都可以通过响应结构中的 exceptionDetails 字段来返回 JavaScript 执行中的异常。

异常响应结构:

{"id": 5,"result": {"exceptionDetails": {"text": "ReferenceError: myVar is not defined","exception": {"type": "object","className": "ReferenceError","description": "ReferenceError: myVar is not defined"}}}
}

通过检查 exceptionDetails,开发者可以捕获并处理执行中的错误,进一步提高代码的健壮性。

测试案例

import asyncio
import websockets
import jsonasync def runtime_complex_test(cdp_url):async with websockets.connect(cdp_url) as websocket:# 1. 使用 Runtime.evaluate 创建一个对象,并获取对象引用expression = """(() => {const obj = {a: 1,b: 2,add: function() {return this.a + this.b;},async computeAsync() {return new Promise(resolve => setTimeout(() => resolve(42), 1000));}};return obj;})();"""await websocket.send(json.dumps({'id': 1,'method': 'Runtime.evaluate','params': {'expression': expression,'returnByValue': False,  # 返回对象的引用而不是值'objectGroup': 'exampleGroup'  # 对象组名,方便后续引用}}))response = json.loads(await websocket.recv())object_id = response['result']['result']['objectId']print(f"创建对象成功,objectId: {object_id}")# 2. 使用 Runtime.callFunctionOn 调用对象的 add 方法await websocket.send(json.dumps({'id': 2,'method': 'Runtime.callFunctionOn','params': {'objectId': object_id,'functionDeclaration': 'function() { return this.add(); }','returnByValue': True  # 直接返回函数结果}}))response = json.loads(await websocket.recv())add_result = response['result']['result']['value']print(f"调用 add 方法的结果: {add_result}")# 3. 使用 Runtime.getProperties 获取对象的属性await websocket.send(json.dumps({'id': 3,'method': 'Runtime.getProperties','params': {'objectId': object_id,'ownProperties': True  # 仅获取对象自身的属性}}))response = json.loads(await websocket.recv())properties = response['result']['result']print("对象属性:")for prop in properties:name = prop['name']value = prop['value']['value'] if 'value' in prop['value'] else '不可读取'print(f"  {name}: {value}")# 4. 使用 Runtime.callFunctionOn 调用异步方法,并通过 Runtime.awaitPromise 处理返回的 Promiseawait websocket.send(json.dumps({'id': 4,'method': 'Runtime.callFunctionOn','params': {'objectId': object_id,'functionDeclaration': 'function() { return this.computeAsync(); }','awaitPromise': True  # 等待异步操作完成}}))response = json.loads(await websocket.recv())if 'result' in response and response['result']['result']['value'] == 42:print(f"异步方法的返回值: {response['result']['result']['value']}")# 清理对象await websocket.send(json.dumps({'id': 5,'method': 'Runtime.releaseObjectGroup','params': {'objectGroup': 'exampleGroup'}}))print("对象已释放")# 替换成你实际的 CDP WebSocket URL
cdp_url = "ws://localhost:9222/devtools/page/1F1A646103FECD9BDC9C29868F0E31D1"
asyncio.get_event_loop().run_until_complete(runtime_complex_test(cdp_url))

代码解释:

  1. Runtime.evaluate:我们首先通过 Runtime.evaluate 执行一段 JavaScript 代码,返回一个包含属性和方法的对象。这段代码定义了一个简单的对象 obj,具有属性 ab,一个同步方法 add,和一个异步方法 computeAsync
    • returnByValue: False 表示我们只想返回对象的引用(objectId),而不是返回整个对象的内容。
  2. Runtime.callFunctionOn:使用 Runtime.callFunctionOn,我们在第一个对象上调用 add 方法,并返回其执行结果。该方法直接执行对象内部的 add 函数并返回其结果。
    • returnByValue: True 表示直接返回调用结果,而不是对象引用。
  3. Runtime.getProperties:我们使用 Runtime.getProperties 来获取对象的所有属性及其值。返回的属性列表包括对象 ab 的值。
  4. Runtime.awaitPromise:调用异步方法 computeAsync 时,我们需要等待 Promise 完成。通过 awaitPromise: True,CDP 会等待异步操作完成,并返回 Promise 的最终结果。
  5. 清理对象:最后通过 Runtime.releaseObjectGroup 释放对象,避免内存泄漏。

运行结果:

执行此脚本时,你会看到以下输出,展示了每一步操作的结果:

创建对象成功,objectId: -2387282854439575449.11.1
调用 add 方法的结果: 3
对象属性:a: 1b: 2add: 不可读取computeAsync: 不可读取
异步方法的返回值: 42
对象已释放

总结

Runtime 域为开发者提供了一个强大的工具集,可以用于控制和管理页面中的 JavaScript 执行环境。通过 Runtime.evaluateRuntime.callFunctionOn 等命令,开发者能够以编程的方式与页面交互,执行任意的 JavaScript 代码,获取执行结果,并处理 JavaScript 的错误和异步操作。

熟练掌握 Runtime 域可以极大提升调试和自动化任务的效率,帮助开发者更好地管理和控制浏览器中的 JavaScript 执行流程。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android 亮度调节

frameworks/base/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java 更新屏幕亮度值Settings.System.SCREEN_BRIGHTNESS BrightnessController.java中有个onChanged事件&#xff0c;这个是更新 setBrightness(val) private void setBrightness(i…

当你访问一个网站时,数据是怎么传输的呢

摘要&#xff1a; 本文详细阐述了电脑访问网站时数据从电脑端逐步传输到服务器端的完整过程&#xff0c;深入剖析了每一步骤中数据的形态变化以及所涉及的网络协议&#xff0c;包括应用层的 HTTP 与 DNS、传输层的 TCP、网络层的 IP 以及数据链路层的以太网等协议的协同工作机制…

基于 Python、OpenCV 和 PyQt5 的人脸识别上课打卡系统

大家好&#xff0c;我是Java徐师兄&#xff0c;今天为大家带来的是基于 Python、OpenCV 和 PyQt5 的人脸识别上课签到系统。该系统采用 Python 语言开发&#xff0c;开发过程中采用了OpenCV框架&#xff0c;Sqlite db 作为数据库&#xff0c;系统功能完善 &#xff0c;实用性强…

智能化业务校验框架:动态设计与应用实践

目录 一、业务背景 二、配置内容展示 三、商品动态配置内容展示 &#xff08;一&#xff09;商品spu校验信息数据 &#xff08;二&#xff09;商品sku校验信息数据 &#xff08;三&#xff09;组包商品校验信息数据 &#xff08;四&#xff09;商品数据校验数据持有者 &…

鸿蒙面试 --- 性能优化(精简版)

一、性能优化的三个方面 感知流畅&#xff1a;通过合理运用动画提升用户对应用操作的感知流畅度&#xff0c;同时避免因动画滥用导致性能下降。涵盖视觉感知优化、转场场景动效感知流畅&#xff08;如出现 / 消失转场、导航转场、模态转场、共享元素转场等&#xff09;&#x…

idea2024加载flowable6.8.1.36遇到的问题-idea启动flowable问题flowable源码启动问题

代码下载地址&#xff1a; https://gitee.com/hanpenghu_admin_admin/flowable6.8.1.git 1.首先是通过顶层目录maven clean install 发现很多子模块并不会install本地mavenStore库&#xff0c;这导致了&#xff0c;一堆相互依赖的模块报错找不到&#xff0c;所以需要根据报错…

web安全从0到1:burp-suite3

声明&#xff01; 学习视频来自B站up主 **泷羽sec** 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团队无关&a…

深度学习模型: BERT(Bidirectional Encoder Representations from Transformers)详解

一、引言 自然语言处理&#xff08;NLP&#xff09;领域在过去几十年取得了显著的进展。从早期基于规则的方法到统计机器学习方法&#xff0c;再到如今基于深度学习的模型&#xff0c;NLP 不断向着更高的准确性和效率迈进。BERT 的出现为 NLP 带来了新的突破&#xff0c;它能够…

ESP8266 (ESP-01S)烧录固件 和 了解与单片机通信必需的AT指令

ESP8266&#xff08;ESP-01s&#xff09;烧录固件 工具&#xff1a; 需要安装的原装出厂固件库&#xff1a; ESP8266 --接线-- VCC 3.3&#xff08;外接开发板&#xff09; GND GND&#xff08;外接开发板&#xff09; IO0 GND&#xff08;外接…

<三>51单片机PWM开发SG90和超声测距

目录 1,PWM开发SG90 1.1简介 1.2控制舵机 1.3编程实现 2,超声测距 2.1简介 2.2,超声波测距代码实现 1,PWM开发SG90 1.1简介 PWM&#xff0c;英文名Pulse Width Modulation&#xff0c;是脉冲宽度调制缩写&#xff0c;它是通过对一系列脉冲的宽度进 行调制&#xff0c;等…

项目搭建+修改

一 : 在列表成功回调函数,追加数据中,添加修改的按钮 for (let x of res) {//追加数据$("#table").append(<tr><td><input type"checkbox" class"ck" value"\${x.uid}"></td><td>\${x.uid}</td>…

【Python爬虫五十个小案例】爬取猫眼电影Top100

博客主页&#xff1a;小馒头学python 本文专栏: Python爬虫五十个小案例 专栏简介&#xff1a;分享五十个Python爬虫小案例 &#x1f40d;引言 猫眼电影是国内知名的电影票务与资讯平台&#xff0c;其中Top100榜单是影迷和电影产业观察者关注的重点。通过爬取猫眼电影Top10…

springboot信息化在线教学平台的设计与实现(代码+数据库+LW)

摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了信息化在线教学平台的开发全过程。通过分析信息化在线教学平台管理的不足&#xff0c;创建了一个计算机管理信息化在线教学平台的方案。文章介绍了信息化在线教…

Hadoop批量计算实验

参考: Hadoop(一)之实验一CentOS7配置Hadoop系统:配置CentOS和下载安装包_基于虚拟机cents7搭建hadoop实验目的-CSDN博客 --------------------------------------------------------- 一、安装Vmware 二、创建虚拟机 1.安装centos7 ①打开VMware,点击新建虚拟机。 …

Flink四大基石之Time (时间语义) 的使用详解

目录 一、引言 二、Time 的分类及 EventTime 的重要性 Time 分类详述 EventTime 重要性凸显 三、Watermark 机制详解 核心原理 Watermark能解决什么问题,如何解决的? Watermark图解原理 举例 总结 多并行度的水印触发 Watermark代码演示 需求 代码演示&#xff…

Ubuntu 操作系统

一、简介 Ubuntu 是一个基于 Linux 的开源操作系统&#xff0c;它由 Canonical Ltd. 公司维护和资助。Ubuntu 以其易用性、强大的社区支持和定期的安全更新而闻名&#xff0c;一个一桌面应用为主的操作系统。 二、用户使用 1、常规用户的登陆方式 在登录时一般使用普通用户&…

Linux下如何安装JDK

在Linux系统上安装JDK&#xff08;Java Development Kit&#xff09;&#xff0c;通常包括下面步骤&#xff1a; 下载JDK安装包解压安装包配置环境变量等 在介绍安装之前&#xff0c;先厘清一些常用问题。 Linux 下Java 安装到哪个目录比较好&#xff1f; 在Linux系统下&am…

Apifox Echo - 简单而强大的API测试服务

什么是Apifox Echo? Apifox Echo 是由 Apifox 官方推出的一个专业的接口请求和返回数据服务平台。它的主要目的是帮助开发人员和测试人员更好地学习和测试API接口。 核心特点 简单易用 提供简洁的HTTP请求和响应服务操作界面直观,上手容易服务地址统一: https://echo.api…

Linux笔记---进程:进程等待

1. 进程等待的概念 进程等待是指父进程通过系统调用wait或waitpid来对子进程进行状态检测与回收的功能。 当子进程退出时&#xff0c;如果父进程不读取子进程的退出状态&#xff0c;子进程就会成为僵尸进程&#xff0c;造成内存泄漏的问题。因此&#xff0c;父进程需要调用wa…

常见靶场的搭建

漏洞靶场 渗透测试&#xff08;漏洞挖掘&#xff09;切忌纸上谈兵&#xff0c;学习渗透测试&#xff08;漏洞挖掘&#xff09;知识的过程中&#xff0c;我们通常需要一个包含漏洞的测试环境来进行训练。而在非授权情况下&#xff0c;对于网站进行渗透测试攻击&#xff0c;是触及…