啥是cdp

根据官网的说法,cdp(Chrome DevTools Protocol) 允许我们检测,调试Chromium, Chrome 和其他基于 Blink的 浏览器. 这个协议被广泛使用. 其中最著名的是 Chrome DevTools,协议的api也由这个团队维护。

使用cdp的姿势

首先需要打开 "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"    --remote-debugging-port=9222

如果在浏览器中,当你打开devtools时,其实你已经在使用cdp了,只是感知不深罢了,一种办法可以更直观的感知cdp,就是打开devtools的devtools,具体操作如下:

  1. 将开发者工具设置为独立窗口,dock side点第一个
    cdp协议简介
  2. 在开发者工具上再使用快捷键ctrl+shift+i,就可以打开开发者工具的开发者工具了(就是先打开开发者工具成独立窗口;再在这个独立窗口上再用快捷键ctrl+shift+i,又打开了开发者工具),现在在新打开的开发者工具的console里面,输入下面的代码:
let Main = await import('./main/main.js');
Main.MainImpl.sendOverProtocol('Runtime.evaluate', {expression: 'alert (12345)'});

这时网页会alert 12345,你会发现平时在控制台简单的代码执行,其实是通过cdp远程调用网页的js引擎去执行再返回结果的。

除此之外,protocol monitor也可以帮助我们更直观的理解cdp。

几个重要的URL

当一个页面暴露出它的remote debugging port时,我们就可以借助cdp来对这个网页进行remote debugging了。由于cdp是借助websocket实现的,所以,在一切开始之前,有两个url是比较重要的
http://localhost:[port]/json/list
http://localhost:[port]/json/version
这两个url,可以让我们拿到网页的websocket url,json/list返回的数据类似于:

[
{
description: "",
devtoolsFrontendUrl: "/devtools/inspector.html?ws=localhost:8080/devtools/page/a31c4d5c-b0df-48e8-8dcc-7c98964e2ebe",
id: "a31c4d5c-b0df-48e8-8dcc-7c98964e2ebe",
title: "",
type: "page",
url: "xxx://xxx",
webSocketDebuggerUrl: "ws://localhost:8080/devtools/page/a31c4d5c-b0df-48e8-8dcc-7c98964e2ebe"
}
]

其中webSocketDebuggerUrl就是我们需要的打开remote debugging 的钥匙

重头戏websocket

接下来我们连上ws,就可以愉快的远程操作页面了,正如chrome devtools所做的那样,下面是一个例子:

const WebSocket = require('ws');
const puppeteer = require('puppeteer');

(async () => {
  // Puppeteer launches browser with a --remote-debugging-port=0 flag,
  // parses Remote Debugging URL from Chromium's STDOUT and exposes
  // it as |browser.wsEndpoint()|.
  const browser = await puppeteer.launch();

  // Create a websocket to issue CDP commands.
  const ws = new WebSocket(browser.wsEndpoint(), {perMessageDeflate: false});
  await new Promise(resolve => ws.once('open', resolve));
  console.log('connected!');

  ws.on('message', msg => console.log(msg));

  console.log('Sending Target.setDiscoverTargets');
  ws.send(JSON.stringify({
    id: 1,
    method: 'Target.setDiscoverTargets',
    params: {
      discover: true
    },
  }));
})();

更多例子可以在这里

jsonRPC

如上面例子所示,当ws连接后,一个发给浏览器的指令大概包括3部分id,method,params,比如一个执行一段console.log('hello')代码的指令:

{
  "id": 235,
  "method": "Runtime.evaluate",
  "params": {
    "expression": "console.log('hello');",
    "objectGroup": "console",
    "includeCommandLineAPI": true,
    "silent": false,
    "contextId": 1,
    "returnByValue": false,
    "generatePreview": true,
    "userGesture": true,
    "awaitPromise": false
  }
}

chrome devtools可以完成的功能非常庞大,而这些功能基本都是使用这样的一个个指令实现的,让人想起那句古老的中国名言:九层之台,起于垒土。本文完

参考资料:
https://chromedevtools.github.io/devtools-protocol
https://github.com/aslushnikov/getting-started-with-cdp/blob/master/README.md

文章来源: www.cnblogs.com,作者:nobody-junior,版权归原作者所有,如需转载,请联系作者。

原文链接:https://www.cnblogs.com/imgss/p/12852595.html

 


 

这边我选择的是 python 的 pychromegithub 地址,使用方法很简单,直接看 github 上它的 Demo

这个库依赖websocket-client

获取 performance api 数据

这里使用 Runtime Domain 中运行 JavaScript 脚本的 APIRuntime.evaluate

# 开始前先启动chrome,启动chrome必须带上参数`--remote-debugging-port=9222`开启远程调试否则无法与chrome交互
browser = pychrome.Browser('http://127.0.0.1:%d' % 9222)
tab = browser.new_tab()
tab.start()
tab.Runtime.enable()
tab.Page.navigate(url={你的页面地址})
# 设置等待页面加载完成的时间
tab.wait(10)
# 运行js脚本
timing_remote_object = tab.Runtime.evaluate(
            expression='performance.timing'
        )
# 获取performance.timing结果数据
timing_properties = tab.Runtime.getProperties(
            objectId=timing_remote_object.get('result').get('objectId')
        )
timing = {}
for item in timing_properties.get('result'):
            if item.get('value', {}).get('type') == 'number':
                    timing[item.get('name')] = item.get('value').get('value')
# 获取performance.getEntries()数据
entries_remote_object = tab.Runtime.evaluate(
            expression='performance.getEntries()'
        )
entries_properties = tab.Runtime.getProperties(
            objectId=entries_remote_object.get('result').get('objectId')
        )
entries_values = []
for item in entries_properties.get('result'):
  if item.get('name').isdigit():
    url_timing_properties = tab.Runtime.getProperties(
                    objectId=item.get('value').get('objectId')
                )
     entries_value = {}
     for son_item in url_timing_properties.get('result'):
                    if (son_item.get('value', {}).get('type') == 'number'or
                            son_item.get('value', {}).get('type') == 'string'):
                        

相关文章:

  • 2021-12-10
  • 2021-12-10
  • 2021-11-27
  • 2021-05-24
  • 2021-09-09
  • 2021-12-19
  • 2021-09-27
  • 2021-06-21
猜你喜欢
  • 2021-10-02
  • 2022-12-23
  • 2021-09-07
  • 2021-05-23
  • 2022-12-23
  • 2022-01-03
  • 2021-12-09
相关资源
相似解决方案