添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

Chrome DevTools Protocol (CDP)是 Chrome 开始开放的一个WebSocket通信协议。

可以访问 https://chromedevtools.github.io/devtools-protocol/ 官方文档查看websocket通信时的各种接口调用参数。

接口通信使用json格式:

"id": "消息ID" , "method": "方法名称" , "params" : {}

id: messageId,数字类型,不能为0,最好不要重复,要通过messageId区分响应信息

method: CDP 方法名称(Browser.getVersion、Page.getResourceTree...)

params:  请求方法参数

“id”:
"请求时传入的消息Id" , "result" : {}

开发者工具的所有操作都是遵循的这个协议,也就是说可以通过这个协议,绕开chrome 各种限制(ಥ_ಥ),比如获取网页所有标签详细信息(包括嵌套的iframe)。

执行Chrome DevTools Protocol 方法:

DevToolsClient 是CefSharp 专门对 CDP 接口做的的封装(Page、DOM、Browser...等等),或者通过ExecuteDevToolsMethodAsync手动执行方法:

声明DevToolsClient全局变量:

//声明全局变量
DevToolsClient devTool = null;
//添加ChromiumWebBrowser初始化事件,初始化时赋值
private void Form1_Load(object sender, EventArgs e)
    DevToolsClient chromiumWebBrowser1.IsBrowserInitializedChanged += new EventHandler(delegate {
        devTool = chromiumWebBrowser1.GetBrowser().GetDevToolsClient();

执行自定义方法:

//添加一个执行方法
public async Task<string> ExecuteDevToolsMethods(string method, IDictionary<string, object> param = null)
       DevToolsMethodResponse resp = await devTool.ExecuteDevToolsMethodAsync(method, param);
       return resp.ResponseAsJsonString;
//执行
private void button1_Click(object sender, EventArgs e)
    ExecuteDevToolsMethods("DOM.getDocument").ContinueWith(new Action<Task<string>>((result) =>
        Console.WriteLine(result.Result);

注意: 不要使用Wait()等待函数,不然会导致卡死

或者使用CefSharp封装好的对象调用:

private async void button1_Click(object sender, EventArgs e)
    await devTool.Browser.GetVersionAsync().ContinueWith(new Action<Task<GetVersionResponse>>((resp)=> {
        Console.WriteLine(resp);

如果使用CefSharp封装对象调用时,需要在执行方法体上添加async/await,才不会导致程序卡死。

可以看一下 stackoverflow 中锁死的几种情况:https://stackoverflow.com/questions/65895251/cefsharp-use-devtoolsclient-execute-method-after-call-wait-function-waiting/65895577?noredirect=1#comment116512155_65895577

不熟悉async/await的原理,如果各位有好的处理建议,请留言,非常感谢!

调试CDP接口:

配置CefSettings, 指定CefSharp 启动时打开远程调试端口:

CefSettings _settings = new CefSettings();
_settings.RemoteDebuggingPort = 32999;
Cef.Initialize(_settings);
一定要在创建窗体时执行配置全局CefSettings配置:
        public Form1()
            InitializeComponent();
            CefSettings _settings = new CefSettings();
            _settings.RemoteDebuggingPort = 32999;//调试端口,一会程序启动后,需要访问这个端口
            Cef.Initialize(_settings);
如果在其他地方配置时会报(暂时还没找到原因...):
CEF can only be initialized once per process. This is a limitation of the underlying CEF/Chromium framework. You can change many (not all) settings at runtime through RequestContext.SetPreference.

这时启动程序,不出意外的话,直接访问: {ip}:{port}(localhost:32999):

 和chrome的远程调试页面比,要简陋一点点....

页面中列出浏览器端(CefSharp)当前打开了几个网页,打开开发者工具,切换到ws标签,在点进网页的同时,会发现建立了一个websocket长连接,每一个网页都有属于自己的一个websocket链接地址

注意: 一定要点进网页前打开开发者工具开始监听websocket,点进页面后,在打开开发者工具监听就晚了,因为websocket是长连接,在一次通信过程中,只会建立一次链接,如果在建立链接时没有打开开发者工具开启监听,ws标签下就一直不会有websocket实时通信内容..

手动调用CDP接口:

访问 {ip}:{port} (localhost:32999) / json  获取websocket链接:

或者通过DOM.getDocument获取百度页面标签内容(包含iframe嵌套iframe,没有同源限制,可以获取所有标签内容):

DOM.getDocument

获取网页文档层级结构.

  depth[可选]: integer (递归检索子节点深度,默认为1)

  pierce[可选]:boolean(是否遍历iframes下内容(个人理解,可能有误,请参照谷歌官网文档),默认为false)

  root: Node对象

 在执行DOM、Page.等其他模块时,最好先执行DOM.enable开启模块代理(看开发者工具在打开页时,总是先enable一堆模块...)

 希望对你有帮助...୧(﹒︠ᴗ﹒︡)୨