chromedp网络监听_动态爬虫三:监听网络事件 + 监听js事件

一: 概述


       上两篇文章介绍了cdp协议和chromedp库,从这篇文章开始动手实战一下,我们要拿到页面上更多的网络请求,最直接的想法就是类似于开发者工具里的network,只有一有网络请求就显示在列表里(在network里隐藏的网络请求后续讨论),完后页面加载完后就可以浏览页面操作页面了,比如 点击,滑动等等,这些都是 js 的事件,如果能把所有绑定了事件的元素都找到, 再去触发它,那么网络请求那边就能监听到。

二:小试牛刀


这是开发者工具的网络窗口:

c476486f0e47e13877c46d9b04b848c8.png

思路有了接下来我们就是要找到一个合适的事件,打开协议监控(参考上几篇文章),完后刷新页面,完后搜索 network 就会看到和网络相关的事件了(network是来源于cdp协议文档里)

0a13ad813581bf3f4ad4ca999ad12ba4.png

从这个字面理解网络请求即将发送,很适合啊,就它了。

291f6552b540235fac790cf684b2ca4b.png

顺便看一下其他事件,下面这个很适合采集响应

4f216bbbe9342f7500c05d444aeb7d4f.png

使用之前搭建的框架试一下,代码结构如下:

9f83111f535a43cfc85bc2605932dc82.png

项目结构等完后单独写篇文章讨论,上面提到的逻辑都写在 scan.go 中了,总体代码如下:

func run(cmd *cobra.Command, args []string) {   sugar := logger.Sugar()   var ws sync.WaitGroup   listRequest := list.New()   listResponse := list.New()   options := append(chromedp.DefaultExecAllocatorOptions[:],      chromedp.Flag("headless", true),      chromedp.Flag("disable-gpu", false),      chromedp.Flag("disable-extensions", true),      chromedp.Flag("hide-scrollbars", false),      chromedp.Flag("mute-audio", false),      chromedp.Flag("enable-automation", false),      chromedp.UserAgent(`Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36`),   )   defaultCtx, cancel := chromedp.NewExecAllocator(context.Background(), options...)   defer cancel()   withLogCtx, cancel := chromedp.NewContext(defaultCtx, chromedp.WithLogf(log.Printf))   defer cancel()   timeoutCtx, cancel := context.WithTimeout(withLogCtx, time.Duration(viper.GetInt64("timeout")) *time.Second)   defer cancel()   if err := chromedp.Run(timeoutCtx, make([]chromedp.Action, 0, 1)...); err != nil {      sugar.Fatal("create chrome error", err)   }   sugar.Info("Chrome instance create success. \n")   chromedp.ListenTarget(timeoutCtx, func(event interface{}) {      switch event.(type) {      case *network.EventRequestWillBeSent:         ws.Add(1)         go func(req *network.EventRequestWillBeSent) {            harReq := common.ProcessRequest(req)            rm := map[network.RequestID]*har.Request{}            rm[req.RequestID] = harReq            listRequest.PushBack(rm)            ws.Done()         }(event.(*network.EventRequestWillBeSent))      case *network.EventResponseReceived:         ws.Add(1)         go func(resp *network.EventResponseReceived) {            harResp := common.ProcessResponse(resp)            rm := map[network.RequestID]*har.Response{}            rm[resp.RequestID] = harResp            listResponse.PushBack(rm)            ws.Done()         }(event.(*network.EventResponseReceived))      case *network.EventDataReceived:         // TODO::      }   })   if err := chromedp.Run(timeoutCtx, network.Enable()); err != nil {      panic(err)   }   if err:= chromedp.Run(timeoutCtx, dom.Enable()); err != nil {      panic(err)   }   if err:= chromedp.Run(timeoutCtx, chromedp.Navigate(args[0])); err != nil {      panic(err)   }   if err := chromedp.Run(timeoutCtx, common.WalkAllNode()); err != nil {      panic(err)   }   ws.Wait()}

创建浏览器实例部分之前解释过,这里就不多说了,我们现在创建了一个浏览器实例,得为我们的浏览器设置网络监听处理,就是下面这段

chromedp.ListenTarget(timeoutCtx, func(event interface{}) {      switch event.(type) {      case *network.EventRequestWillBeSent:   发请求前监听的事件         ws.Add(1)         go func(req *network.EventRequestWillBeSent) {            harReq := common.ProcessRequest(req)            rm := map[network.RequestID]*har.Request{}            rm[req.RequestID] = harReq            listRequest.PushBack(rm)            ws.Done()         }(event.(*network.EventRequestWillBeSent))      case *network.EventResponseReceived:  收到响应监听的事件         ws.Add(1)         go func(resp *network.EventResponseReceived) {            harResp := common.ProcessResponse(resp)            rm := map[network.RequestID]*har.Response{}            rm[resp.RequestID] = harResp            listResponse.PushBack(rm)            ws.Done()         }(event.(*network.EventResponseReceived))      case *network.EventDataReceived:         // TODO::      }   })

这些事件最好都在协程里处理, 同时注意要开启网络监听,我弄那会儿就折腾了半天抓不到流量,仔细看文档才发现的

if err := chromedp.Run(timeoutCtx, network.Enable()); err != nil {   panic(err)}

中间插一个介绍,har 这个东西,我之前都不知道,翻源码发现的,就是专门记录http流量的一个格式

742a19fc1c8dc70d13e7570f1237570d.pngd2ebb37124a1020dd99529d25260860a.png

维基百科介绍: https://zh.wikipedia.org/wiki/.har

反正现在还不知道存成啥样子呢,先按这个格式来吧,上面写了2个处理函数,代码如下:

func ProcessRequest(r *network.EventRequestWillBeSent) *har.Request {   req := har.Request{}   req.Method = r.Request.Method   req.URL = r.Request.URL   req.Headers = []*har.NameValuePair{}   for header := range r.Request.Headers {      h := har.NameValuePair{}      h.Name = header      h.Value = r.Request.Headers[header].(string)      req.Headers = append(req.Headers, &h)   }   req.Cookies = []*har.Cookie{}   req.QueryString = []*har.NameValuePair{}   u, err := url.Parse(req.URL)   if err != nil {      log.Printf("[E] Invalid URL data recived : %v", err)   }   for name := range u.Query() {      if len(name) != 0 {         values := u.Query()[name]         for _, val := range values {            req.QueryString = append(req.QueryString, &har.NameValuePair{               Name:  name,               Value: val,            })         }      }   }   if req.Method == "POST" {      // Process the post data of the form *har.PostData   }   return &req}func ProcessResponse(r *network.EventResponseReceived) *har.Response {   res := har.Response{}   res.Status = r.Response.Status   res.StatusText = r.Response.StatusText   res.HTTPVersion = r.Response.Protocol   // TODO : implement cookie information.   res.Cookies = nil   res.Headers = []*har.NameValuePair{}   // headers from the *network.EventRequestWillBeSent are in the form,   // map[key:value]. this needs to be converted to the form of a   // har.NameValuePair   for header := range r.Response.Headers {      h := har.NameValuePair{}      h.Name = header      h.Value = r.Response.Headers[header].(string)      res.Headers = append(res.Headers, &h)   }   // response content   res.Content = &har.Content{}   res.Content.MimeType = r.Response.MimeType   res.Content.Size = 0   // Redirect URL   res.RedirectURL = ""   res.HeadersSize = 0   res.BodySize = 0   return &res}

好了,跑一下程序试试效果

e97399ff9dfcb45ca315315176d187e4.png

看着还可以,哈哈哈,接下来该到查看所有带事件的节点了,我们知道 html 最后会解析为一棵 DOM 树,那么怎么获取这个树呢,还是翻文档,发现个这个,如下:

c36b0827b53e6b5b58a884d2b07a300c.png

把所有节点打平到一个数组里,正是我们想要的。数组里是 Node 结构,如下:

ad63607c741400e909e330966d15769f.png

翻了一下发现好像没事件相关的东西,这个地方折腾了好一会儿,还是看文档,如下:

481841b2dc9e56c1aae80a71c5aeed64.png

事件相关的在 DOMDebugger 中,这个方法可以获取所有事件监听。但是这个函数要的参数是一个 RemoteObjectID。

517236954a87173009911214c64a0e8b.png

我擦,此时陷入了迷茫,我有的只有一个 nodeID,怎么获取 RemoteObjectId ???

d36f36820d160f036d8d38f32c7092e1.png

功夫不负有心人,找到一篇文章

67d58c058ccd45c99ae1fbfa0b2750ce.png

(链接:https://stackoverflow.com/questions/31280653/what-is-nodeid-in-chrome-extension-chrome-debugger)

搞清楚后,还是回到文档,开始找找转换函数,于是找到了这个货

f59fe6b082b30fb79398d879b556887c.png

胜利就在前方,上代码

func WalkAllNode() chromedp.Tasks {   return chromedp.Tasks{      chromedp.ActionFunc(func(ctx context.Context) error {         node, err := dom.GetFlattenedDocument().Do(ctx)         if err != nil {            return err         }         for _, tmpNode := range node {            rmObject, _ := dom.ResolveNode().WithNodeID(tmpNode.NodeID).Do(ctx)            eventLister, _ := domdebugger.GetEventListeners(rmObject.ObjectID).Do(ctx)            if len(eventLister) > 0 {               fmt.Println(tmpNode.NodeName, tmpNode.Attributes)               for _, event := range eventLister {                  fmt.Println(event.Type)               }            }         }         return nil      }),   }}

调用的地方在这里

...if err:= chromedp.Run(timeoutCtx, chromedp.Navigate(args[0])); err != nil {   panic(err)}if err := chromedp.Run(timeoutCtx, common.WalkAllNode()); err != nil {   panic(err)}ws.Wait()...

跑一下,效果如下

609cfcc2427a71405860167e12cb2024.png

和开发者工具里的对比一下

b7258e725902693b47741f5e02c6c8e4.png

顺利拿到,下一篇分享怎么触发这些事件。

三:总结


        感觉文档真的很重要,之前没接触过这些,上面只是最普通的情况,好多其他的情况都没考虑,慢慢来,前端博大精深。 

‍

Golang爬虫终极杀器——Chromedp让你成为二维码登陆终结者(教程) chromedp是一个更快、更简单的Golang库用于调用支持Chrome DevTools协议的浏览器,同时不需要额外的依赖,文章记录了使用chromedp进行二维码登陆的过程 阅读详情

相关推荐

Chromedp实战:如何监听动态网页的XHR请求(附完整代码示例)

本文详细介绍了使用Chromedp监听动态网页XHR请求的完整实战方案。通过搭建开发环境、注册网络事件监听器,并配合电商价格监控的实战案例,帮助开发者绕过前端渲染,直接捕获纯净的结构化数据,高效应对动态网页的数据抓取挑战。

weixin_29207533的博客 662

「Go开源包」chromedp:一个基于Chrome DevTools协议的库,支持数据采集、截取网页长图

chromedp基于Chrome DevTool协议实现。可以对网页内容进行采集、模拟点击、提交数据、将网页内容转换成pdf、抓取网页长图等功能。

Ch3nnn的博客 3844

利用 Chromedp 实现动态网页请求与响应的智能监控

本文详细介绍了如何利用Chromedp实现动态网页请求与响应的智能监控。通过解析电商价格监控等实际案例,展示了Chromedp在解决动态参数反爬机制中的优势,包括真实浏览器环境模拟、完整请求生命周期监控和动态参数自动解析。文章提供了完整的实战代码示例,涵盖请求过滤、数据存储和错误处理等关键功能,帮助开发者高效应对现代网页的动态特性。

weixin_28452161的博客 199

chromedp抓取数据,从0开始踩坑记录

chromedp抓取youtube、ins、tiktok数据,从0开始踩坑记录。文中几乎会涉及到所有chromedp的函数使用场景和特性&&各种奇奇怪怪的bug

pt13558684045的博客 3166

Go语言爬虫:chromedp 的详细使用

chromedp 是 Go 语言中无头浏览器自动化的终极利器。它能驱动真实的 Chrome 浏览器,处理 JavaScript 渲染、复杂交互和反爬虫机制

数据知道的博客 4492

Autosar Davinci Configurator新建工程以及导入DBC和CDD

Autosar Davinci Configurator新建工程前言一、Autosar Davinci Configurator新建工程二、Autosar Davinci Configurator导入DBC和CDD1.引入库2.读入数据总结 前言 如何用 DavinciCFG 新建工程,以及导入DBC和CDD文件。 一、Autosar Davinci Configurator新建工程 示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。 二、Autosar Davinc

别再跑偏了的博客 1万+

Golang爬虫新利器——Chromedp实战:破解动态验证码登录(教程)

本文详细介绍了如何使用Golang的Chromedp库破解动态验证码登录,特别是二维码扫码登录。通过实战教程,展示了从环境搭建、元素定位、模拟点击、截图二维码到状态监听与Cookie持久化的完整自动化流程,帮助开发者高效处理现代网页的动态内容爬取难题。

ik678901234的博客 1043

无人车路径规划方法汇总

无人车路径规划方法汇总

weixin_44380244的博客 2557

利用 Chromedp 动态解析网页加密请求参数

本文详细介绍了如何利用Chromedp动态解析网页加密请求参数。通过搭建无头浏览器监听环境,实时捕获XHR/Fetch请求与响应,绕过复杂的JS混淆加密逻辑,直接获取正确的签名、时间戳等动态参数。该方法高效可靠,是应对前端反爬策略的实用技巧,并提供了过滤、参数分析及性能优化等进阶指南。

1a2s3d4f5g的博客 710

Ethercat学习-从站源码生成

移植平台GD32F450,从站芯片AX58100

西澳峰的博客 9209

Vivado时序约束实战:input_delay在高速接口设计中的关键作用

本文深入探讨了在Vivado时序约束中,input_delay对于高速接口设计的关键作用。通过一个RGMII以太网接口调试的实际案例,解释了为何仅靠仿真正确而实际数据采集会失败,并揭示了set_input_delay约束的本质是告知时序分析工具外部芯片的时序关系,而非添加物理延迟。文章详细讲解了如何根据数据手册计算约束值、针对不同采样时钟方案(如移相时钟)进行约束,并指导如何通过时序报告验证约束效果,是解决FPGA高速接口时序问题的实战指南。

ee345的博客 252

sitespeed.io CDP 实战配方:用 Chrome DevTools Protocol 精确控制浏览器行为与网络环境

本文是 sitespeed.io / Browsertime 脚本体系中 CDP(Chrome DevTools Protocol)系列的实战篇。在阅读 [Chrome DevTools Protocol 教程](https://link.gitcode.com/i/397e340d4f43b939b056457c392a2503)掌握了 `cdp.send`、`cdp.sendAndGet`、`

gitblog_00078的博客 171

Centos7安装NVIDIA驱动并在docker容器中使用GPU

Centos7安装NVIDIA驱动并在docker容器中使用GPU

运维giao的博客 2083

Castor 如何从网页里找到视频:网页视频流嗅探与提取原理揭秘

**Castor** 是一款开源的网页视频嗅探与投屏工具:你只需把网页链接丢给它,它就能自动嗅探页面里的视频流、转码并实时投到你的电视上(甚至还能生成烧录字幕)。那么 Castor 是如何从一个普通的网页里"找到视频"的?这篇文章带你揭秘它的网页视频流嗅探与提取原理——不需要看代码,也能搞懂整个流程。 [![Castor 网页视频嗅探工具:浏览器式选择界面](https://raw.gitcod

gitblog_00302的博客 187

S32K324 Stack异常分析及解决方案

在项目开发过程中,在一次软件变更时,调整了task优先级之后导致应用层软件中的float数据经常性的变为NAN,导致应用层功能失效。本文记录下这个bug的分析及解决过程。该问题排查了好几天,最开始正向排查不出来,差点放弃了,ETAS OS也没有人支持,只能换一种思路,通过反向推,最终定位到问题,能完美解决,还是很欣慰的。遇到问题不可怕,Bug一直都会有,主要是在解决问题中的思路和方法,不断总结积累,总会越来越好的!

赞的博客 596

IgH EtherCAT 从入门到精通:第 2 章 环境搭建与编译安装

环境搭建与编译安装指南 本章详细介绍了搭建IgH EtherCAT Master开发环境的完整流程。内容包括: 硬件要求:支持多种Intel和Realtek网卡的原生驱动,以及通用网卡的generic驱动选项 软件依赖:列出Linux系统下所需的工具链和开发包 源码获取:通过Git克隆官方仓库并切换稳定版本的方法 配置选项:详细解析bootstrap脚本和configure的核心参数,包括路径设置、功能开关和实时框架选项 编译流程:从生成构建系统到最终编译安装的完整步骤 通过本章指导,读者可以完成一个可运行

从事嵌入式linux android驱动开发,拥有全栈能力 473

Go语言驱动Firefox自动化:Selenium WebDriver与GeckoDriver深度整合实战

Web自动化测试与数据采集是现代软件开发与数据分析中的关键技术,其核心原理是通过程序模拟用户操作浏览器,实现对网页的交互与内容获取。Selenium WebDriver作为行业标准协议,为跨语言控制浏览器提供了统一接口,而GeckoDriver则是Firefox浏览器的专用驱动实现。在追求高性能、低资源消耗和易于部署的自动化服务或爬虫场景下,Go语言凭借其卓越的并发模型(goroutine)和编译为单一可执行文件的特性,展现出独特的技术价值。通过将Go与Selenium、GeckoDriver深度整合,开发

weixin_34174322的博客 359

反应动力学仿真软件:Kintecus_(12).高级功能与技巧

Kintecus允许用户自定义复杂的反应方程,包括非线性反应和多相反应。通过自定义反应方程,用户可以更准确地描述实际反应系统。多尺度仿真是指在同一模型中同时考虑不同时间和空间尺度的反应过程。Kintecus提供了工具来处理从微观分子动力学到宏观反应动力学的多尺度仿真。通过本节的学习,您已经掌握了Kintecus的高级功能与技巧,包括复杂反应网络的构建、参数优化与敏感性分析、自定义反应机制、多尺度仿真、并行计算与批处理,以及数据可视化与后处理。

kkchenjj的博客 1047

chromedp入门

chromedp是什么?chromedp是go写的,支持Chrome DevTools Protocol 的一个驱动浏览器的库。并且它不需要依赖其他的外界服务(比如 Selenium 和...

轩脉刃的刀光剑影 6425

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

谷歌浏览器爬虫(chromedp)页面请求超时的解决方案

模式(即无头模式,无GUI界面模式)运行,发现亚马逊一个页面请求,页面一直未加载完成,卡死了。服务,专门用来做浏览器爬虫。服务器上部署了谷歌浏览器以。

青哥的博客 3646

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

使用 Chromedp 监听网页请求和响应

ChromeDP 是一个 Go 语言实现的库,它提供了无头浏览器的操作和控制能力,可以用来进行网页自动化、爬虫和测试等工作。通过 ChromeDP,我们可以编程方式监听网页上的各种事件,包括网络请求和响应。

Clown95 1894

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

探索`chromedp`:无头浏览器编程的利器

探索chromedp:无头浏览器编程的利器 exampleschromedp code examples.项目地址:https://gitcode.com/gh_mirrors/examples12/examples chromedp是一个高效且易于使用的Go语言库,用于控制Chrome或Chromium浏览器,实现自动化任务,如网页抓取、测试和数据提取等。本项目集合了一系列丰富的示例代码,旨在...

gitblog_00067的博客 867

Go+chromedp实现Web UI自动化测试

如题

路飞 1795

【Golang源码学习】chromedp篇

chromedp源码阅读

qq_40119224的博客 1456

chromedp如何在CentOs7上使用

chrome官方为我们提供了Centos环境下的chrome,可以达到和windows环境下的chrome同等效果,windows的话,直接下载软件安装即可,Linux系统的话,需要使用docker启动chrome headless服务。

sunriseYJP的博客 4818
上一篇: linux 普通用户touch权限不够_一篇文章让你轻松了解 Linux 的权限
下一篇: go string 换行_从词法分析角度聊 Go 代码组成
Air君陈怡帆
博客等级 码龄9年 43粉丝 1852原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值