最新动态
Python cdp ( Chrome DevTools Protocol ) 爬虫
2024-12-01 04:01
Python cdp ( Chrome DevTools Protocol ) 爬虫 爬虫

Python cdp ( Chrome DevTools Protocol ) 爬虫

devtools-protocol:https://github.com/ChromeDevTools/devtools-protocol Chrome DevTools Protocol:https://chromedevtools.github.io/devtools-protocol/ 实现 CDP 协议的库:https://github.com/ChromeDevTools/awesome-chrome-devtools

cdp chrome

Chrome 提供了 websocket 调试接口用于对当前 Tab 内页面的 DOM、网络、性能、存储 等等进行调试,我们常用的开发者工具就是基于此接口,这个接口也支持远程调用,在启动参数中加上 --remote-debugging-port=9222 即可。

Python cdp ( Chrome DevTools Protocol ) 爬虫

远程调试接口是一个 WebSocket 的接口,Chrome 提供的开发者工具是一种客户端,自己写代码调用也是一种客户端。DevTools 可以 attach 到一个远程运行的 Chrome 实例,来进行 debug

  • 启动一个 host Chrome 实例chrome.exe --remote-debugging-port=9222
  • 指定一个用户的 profile 启动一个 client 客户端 Chrome 实例chrome.exe --user-data-dir=<some directory>

在客户端中输入 http://localhost:9222,你会看到当前 client 端的 DevTools 就像内嵌在电脑中Chrome 的 devtools 一样,然后你就可以通过 client 操作他了。

  • 当用 client 连接到 9222 的时候,DevTools 前端 会被 host Chrome 实例 serve 为一个远程服务端的 web application,他会通过 HTTP 协议 fetch HTML,Javascript,CSS,一旦加载,DevTools 会和 host 建立一个 ws 链接,并开始交换 JSON 信息

也可以用自己的实现来替代 DevTools 前端,除了 localhost:9222

远程调试还提供了一个JSON接口,用于管理浏览器的 Tab 页面。( localhost:9222/json 来获取到 ws 通信的 JSONobject,并修改使用它们, HTTP Endpoints 章节中有详细内容。

实战 Chrome Headless 数据抓取(上:https://blog.csdn.net/chixulu6723/article/details/100730003

启动之前,需要关闭所有 Chrome 窗口

Linux 中的 screen 命令使用:https://blog.csdn.net/han0373/article/details/81352663

如果在远程服务器上建议在 screen 里运行,一个小工具防止网络突然中断:$ screen -S chrome

然后会打开一个新的 shell,可以用 Ctrl + A + D 切出来,或者断开SSH 直接切出来。再进去只需要执行:$ screen -r chrome

然后在 screen 里面的 shell 执行( 本机 Windows 调试把 google-chrome-unstable 换成chrome.exe :$ google-chrome-unstable --headless --remote-debugging-port=9222 --user-data-dir='/home/luke/chrome-data/baidu' --user-agent='Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3080.5 Safari/537.36'

解释下参数

  • --headless:无头模式,就是无界面模式运行
  • --remote-debugging-port:开启远程调试,端口9222和我们之前转发出来的端口一致
  • --user-data-dir:设置独立的文件保存目录,建议一个网站一个目录
  • --user-agent:伪装浏览器,默认User-Agent里的浏览器叫HeadlessChrome,很容易被发现

启动之前,需要关闭所有 Chrome 窗口,然后在启动

远程调试接口是一个 WebSocket 的接口,Chrome 提供的开发者工具是一种客户端,我们自己写代码调用也是一种客户端。这里先用开发者工具测试,后面会写代码来实现。 在本地浏览器开:http://服务器IP:9222/json ,本机测试的话就是 http://127.0.0.1:9222/json 。我已经用 SSH 把服务器的 9222 转发到本机的 9222 了,这是效果

Python cdp ( Chrome DevTools Protocol ) 爬虫

这里列出了当前远程浏览器内打开的Tab,每个页面一个UUID用以识别。已知接口

  • http://127.0.0.1:9222/json :查看已经打开的Tab列表
  • http://127.0.0.1:9222/json/version : 查看浏览器版本信息
  • http://127.0.0.1:9222/json/new?http://www.baidu.com : 新开Tab打开指定地址
  • http://127.0.0.1:9222/json/close/ac5a6adb-bb53-44f1-a9e6-2354bd724924 : 关闭指定Tab
  • http://127.0.0.1:9222/json/activate/69301801-d503-42a3-9335-3e448a780857 : 切换到目标Tab

远程打开,新开一个 Tab 打开百度首页,然后刷新 http://127.0.0.1:9222/json ,可以看到百度已经打开了

Python cdp ( Chrome DevTools Protocol ) 爬虫

 注意到,有一个devtoolsFrontendUrl,那就是开发者工具的前端地址,就是一个html应用,url里面传过去WebSocket调试地址。打开这个地址就可以看到熟悉的开发者工具了!注意:这个窗口调试的是远程chrome上的页面。

Python cdp ( Chrome DevTools Protocol ) 爬虫

如果你想看看页面在远程服务器的 Chrome 里渲染的结果,在开发者工具里切换到 Performance,勾选 Screenshots,点刷新图标,重新加载完成就可以看到逐帧加载的截图。

思路:我们在 Elements 里面找到输入框的 ID,使用 JQuery 操作。百度首页已经有 JQuery 了,其他网站我们可以在 Console 里执行 JS,加载一个。 我们切换到 Console 里直接用 JS 操作DOM,执行

 

相当于在百度输入框里输入了测试并点击了“百度一下”按钮。

Python cdp ( Chrome DevTools Protocol ) 爬虫

现在再打开 http://127.0.0.1:9222/json ,可以看到原来的页面标题已经变成了 “测试_百度搜索”,也就说明成功完成了搜索。 

依然是在 Elements 里面找到结果列表的 ID,然后用 JS 获取内容。 获得结果数量

 

获得所有结果标题

 

Python cdp ( Chrome DevTools Protocol ) 爬虫

Chrome DevTools Protocol 的指令分为三十多个大类,每类又有若干个指令,这里不能一一介绍,只选择几个简单而常用的指令介绍一下

  • 跳转到指定页面
  • 执行JS函数
  • 获取资源树
  • 获取资源

其中 Page.navigate 是必备指令,用于跳转页面。而 Runtime.evaluate 的效果等同于在 Develop Tools 的 Console 控制台执行指令,基本可以执行任何js指令,模拟输入,输出渲染后的 html 用它都可以轻松搞定,可以说是大杀器了。

Python cdp ( Chrome DevTools Protocol ) 爬虫

 获取资源树和获取资源指令则用于获取浏览器当前原始请求的数据,可以用它来构建Develop Tools的Source树。

Python cdp ( Chrome DevTools Protocol ) 爬虫

可以说,利用 Develop Tools 实现的功能我们都可以通过 Chrome DevTools Protocol 实现,Chrome 自己也内置了一个官方的实现,用 Chrome 直接访问页面信息的 devtoolsFrontendUrl 即可看到,和按 F12 调用出来的 Develop Tools 基本一模一样。 

From:https://brucedone.com/archives/1201

要分析的网站:https://datacenter.jin10.com/price

 

 

整体逻辑非常简单,打开指定页面,等待页面数据刷新,然后直接偷懒拿数据渲染之后的页面值,运行效果如下

Python cdp ( Chrome DevTools Protocol ) 爬虫

这里使用 chrome-headless 的相关渲染环境来解决了抓取数据的问题,并且使用 websocket api 来进一步操作,其实 google 官方有 sdk 进行操作,https://github.com/GoogleChrome/puppeteer ,渲染的终究不是高效的做法,但是对于这种单页面目的性很强的数据,可以尝试渲染大法

Pyppeteer 防止检测

chrome devtools protocol 允许第三方对基于 chrome 的 web 应用程序进行调试、分析等,它基于 WebSocket,利用 WebSocke t建立连接 DevTools 和浏览器内核的快速数据通道。一句话,有了这个协议就可以自己开发工具获取 chrome 的数据

协议详细内容看这里 chrome devtools protocolChrome DevTools Protocol

目前已经有很多大神针对这个协议封装出不同语言(nodejs,python,java...)的库。

awesome-chrome-devtools

  • Javascript/Node.js: chrome-remote-interface - The most-used Javascript API for the protocol
  • Typescript/Node.js: chrome-debugging-client
  • Java: chrome-devtools-java-client
  • Java: karate - Web-service testing framework with a Java API to automate Chrome
  • Java: jvppeteer - Headless Chrome For Java
  • Python: PyCDP - Pure-Python, sans-IO wrappers. See also the Trio CDP driver
  • Python: chromewhip - drop-in replacement for the  service
  • Python: pychrome - low level CDP transport handler
  • Python: ChromeController - high-level browser mgmt
  • Go: chromedp - High-level actions and tasks for driving browsers
  • Go: cdp
  • Go: gcd
  • Go: godet
  • Go: Rod
  • C#/dotnet: chrome-dev-tools - Protocol wrapper generator that can be customized by editing handlebars templates. Includes .Net Core template.
  • Ruby: Cuprite - Capybara driver
  • Ruby: ChromeRemote
  • Kotlin: chrome-reactive-kotlin - reactive (rxjava 2.x), low-level client library in Kotlin
  • Kotlin: chrome-devtools-kotlin - A coroutine-based client library, providing low-level CDP primitives and high-level extensions.
  • Clojure: clj-chrome-devtools - The CDP wrapper API is autogenerated and will be updated when CDP protocol changes.
  • PHP: chrome-devtools-protocol - A PHP client library for the protocol.

PyChromeDevTools:https://github.com/marty90/PyChromeDevTools

PyChromeDevTools 是一个 Python 模块,允许在 Python 脚本中使用 Chrome DevTools 协议与 Google Chrome 交互。

页面加载时间

 

打印所有安装的 cookies

 

打印页面的所有对象 URL

 

Pychrome:能跟 chrome 开发者工具交流的 Python 包,查看 github 代码中 examples 文件夹,查看更多例子。pychrome github地址,使用方法很简单,直接看 github上它的 Demo

这个库依赖 websocket-client

python - pychrome 页面抓取测试:https://blog.csdn.net/max229max/article/details/91972429

使用 Chrome-headless 抓取页面内容,使用 python 的 pychrome 包。

要先开启浏览器,然后通过pychrome调用chrome dev protocol

 

chrome devtools protocol --- Web 性能自动化实践介绍 :https://testerhome.com/topics/15817

在测试 Web 页面加载时间时,可能会是这样的

  1. 打开 chrome 浏览器。
  2. 按 F12 打开开发者工具。
  3. 在浏览器上打开要测试的页面
  4. 查看开发者工具中 Network 面板的页面性能数据并记录
  5. 或者 开发者 Console 面板运行 performance.timing 和 performance.getEntries() 收集数据

performance 相关信息看这里 https://www.w3.org/TR/navigation-timing-2/#the-performancetiming-interface

几十上百个页面,每个版本都这样来,估计疯了,所以就想怎么把它做成自动化呢

获取 performance api 数据

这里使用 Runtime Domain 中运行 Javascript 脚本的 API Runtime.evaluate

 

获取 Network 数据

实际上 performance.getEntries() 不会记录 404 的请求信息,另外当前页面通过 js 触发新 html 页面请求时它只会记录第一个页面的请求,在这些情况下就需要通过 Network Domain 的 API 来收集所有请求信息,先介绍用到的 API

  • Network.requestWillBeSent  每个 http 请求发送前回调
  • Network.responseReceived  首次接送到 http 响应时回调
  • Network.loadingFinished  请求加载完成时回调
  • Network.loadingFailed  请求加载失败时回调
 

监听 页面 事件

有时候特别是一些复杂的页面,页面依赖 js 和 后端资源数据,并不是通常意义上页 loadEventEnd 事件触发完就表示页面加载完成,这种情况可能需要依赖开发打点。

这里以开发设计了一个 Loaded 事件为例

 

有个坑 获取与 chrome 开发者工具协议一样类型的时间时,这个时间不准确,只好用 

写在最后

一开始是使用 nodejs 的 chrome-remote-interface,但是发现 Page.loadEventFired 回调后不会再记录请求,事实上有些页面仍然有请求没有完成,不懂是不是我使用姿势不对。。。

附赠 W3C 的一幅图

Python cdp ( Chrome DevTools Protocol ) 爬虫

    以上就是本篇文章【Python cdp ( Chrome DevTools Protocol ) 爬虫】的全部内容了,欢迎阅览 ! 文章地址:http://keair.bhha.com.cn/quote/3436.html 
     动态      相关文章      文章      同类文章      热门文章      栏目首页      网站地图      返回首页 康宝晨移动站 http://keair.bhha.com.cn/mobile/ , 查看更多