chrome远程调试协议配置的分析
字数 947 2025-08-05 08:20:05
Chrome远程调试协议配置与分析教程
1. 概述
本教程详细讲解如何通过Chrome远程调试协议实现JavaScript的自动调试分析,特别是如何获取调用栈内的变量信息。教程基于对DevTools通信流量的抓包分析,提供了完整的Python实现代码。
2. 准备工作
2.1 启动Chrome远程调试
chrome.exe --remote-debugging-port=9222
2.2 安装必要Python库
pip install pychrome
3. 基础调试配置
3.1 基本连接与初始化
import pychrome
# 连接远程调试
remote_chrome = "http://127.0.0.1:9222"
browser = pychrome.Browser(url=remote_chrome)
# 新建标签页
tab = browser.new_tab()
tab.start()
# 启用必要模块
tab.Page.enable()
tab.Debugger.enable()
tab.Runtime.enable()
3.2 高级调试配置
# 增加脚本缓存大小
tab.Debugger.enable(maxScriptsCacheSize=10000000)
# 设置异步调用栈深度
tab.Debugger.setAsyncCallStackDepth(maxDepth=50)
4. 调试事件处理
4.1 暂停事件处理函数
def GetObject(objectId):
result = tab.Runtime.getProperties(
objectId=objectId,
ownProperties=False,
accessorPropertiesOnly=False,
generatePreview=True,
nonIndexedPropertiesOnly=False,
)
return result["result"]
def DebugPaused(**kw):
callFrames = kw.get("callFrames")
result = dict()
for callFrame in callFrames:
result[callFrame["callFrameId"]] = dict()
# 遍历每一个调用栈
# 先获得范围内的变量集合
scopeChain = callFrame["scopeChain"]
for _vars in scopeChain:
# 这里只获取局部变量
if _vars["type"] == "local":
_objectId = _vars["object"]["objectId"]
_object = GetObject(_objectId)
result[callFrame["callFrameId"]][_objectId] = _object
# 保存调试信息
with open("result.json", "w", encoding="utf-8") as f:
import json
f.write(json.dumps(kw, indent=4))
with open("stack.json", "w", encoding="utf-8") as f:
import json
f.write(json.dumps(kw, indent=4))
# 恢复执行
tab.Debugger.resume()
# 绑定调试函数
tab.Debugger.paused = DebugPaused
5. 设置断点
5.1 设置XHR/Fetch断点
# 设置XHR断点
tab.DOMDebugger.setXHRBreakpoint(url="")
5.2 导航到目标页面
# 打开网页
tab.Page.navigate(url="https://www.baidu.com/")
# 保持程序运行
while True:
input()
6. 关键数据结构解析
6.1 Debugger.paused返回结构
callFrames: 调用栈帧数组,按从栈顶到栈底顺序排列asyncStackTrace: 异步调用栈信息(需要额外配置)
6.2 callFrame结构
{
"callFrameId": "唯一标识符",
"functionName": "函数名",
"location": {
"scriptId": "脚本ID",
"lineNumber": 行号,
"columnNumber": 列号
},
"scopeChain": [
{
"type": "作用域类型",
"object": {
"type": "object",
"objectId": "对象ID"
}
}
],
"this": {
"type": "对象类型",
"objectId": "对象ID"
}
}
6.3 scopeChain类型
local: 局部作用域closure: 闭包作用域catch: catch块作用域block: 块级作用域script: 脚本作用域with: with语句作用域global: 全局作用域
7. 获取变量信息的方法
通过Runtime.getProperties方法获取变量信息:
result = tab.Runtime.getProperties(
objectId=objectId,
ownProperties=False,
accessorPropertiesOnly=False,
generatePreview=True,
nonIndexedPropertiesOnly=False,
)
8. 完整代码示例
import pychrome
# 连接远程调试
remote_chrome = "http://127.0.0.1:9222"
browser = pychrome.Browser(url=remote_chrome)
# 新建标签页
tab = browser.new_tab()
tab.start()
# 启用必要模块
tab.Page.enable()
tab.Debugger.enable()
tab.Runtime.enable()
# 高级调试配置
tab.Debugger.enable(maxScriptsCacheSize=10000000)
tab.Debugger.setAsyncCallStackDepth(maxDepth=50)
def GetObject(objectId):
result = tab.Runtime.getProperties(
objectId=objectId,
ownProperties=False,
accessorPropertiesOnly=False,
generatePreview=True,
nonIndexedPropertiesOnly=False,
)
return result["result"]
def DebugPaused(**kw):
callFrames = kw.get("callFrames")
result = dict()
for callFrame in callFrames:
result[callFrame["callFrameId"]] = dict()
# 遍历每一个调用栈
# 先获得范围内的变量集合
scopeChain = callFrame["scopeChain"]
for _vars in scopeChain:
# 这里只获取局部变量
if _vars["type"] == "local":
_objectId = _vars["object"]["objectId"]
_object = GetObject(_objectId)
result[callFrame["callFrameId"]][_objectId] = _object
# 保存调试信息
with open("result.json", "w", encoding="utf-8") as f:
import json
f.write(json.dumps(kw, indent=4))
with open("stack.json", "w", encoding="utf-8") as f:
import json
f.write(json.dumps(kw, indent=4))
# 恢复执行
tab.Debugger.resume()
# 绑定调试函数
tab.Debugger.paused = DebugPaused
# 设置XHR断点
tab.DOMDebugger.setXHRBreakpoint(url="")
# 打开网页
tab.Page.navigate(url="https://www.baidu.com/")
# 保持程序运行
while True:
input()
9. 调试技巧
- 流量分析: 使用Wireshark抓取WebSocket通信数据包,分析DevTools实际操作
- 事件启用: 使用任何功能前,确保已启用相应模块的事件报告
- 异步调用栈: 需要显式设置
setAsyncCallStackDepth才能获取异步调用栈信息 - 变量获取: 通过
scopeChain中的objectId获取变量详细信息
10. 总结
通过分析DevTools的实际通信流量,我们可以复现DevTools中的各种调试操作。关键点包括:
- 正确配置调试参数(如脚本缓存大小、异步调用栈深度)
- 理解
Debugger.paused事件返回的数据结构 - 通过
scopeChain和Runtime.getProperties获取变量信息 - 合理设置断点触发调试暂停
这种方法可以扩展到其他调试功能的实现,如条件断点、变量监控等。