失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 尝试自动重定向的次数太多_GoRod:基于DP协议的Web自动化和数据抓取工具

尝试自动重定向的次数太多_GoRod:基于DP协议的Web自动化和数据抓取工具

时间:2023-10-05 16:35:38

相关推荐

尝试自动重定向的次数太多_GoRod:基于DP协议的Web自动化和数据抓取工具

在日常开发中我们经常可能会遇到这样一些情景:需要使用一些自动化的手段来帮助我们测试;在获取某些网页的数据的时候,由于目标网页的数据是动态的,使用传统的数据获取手段无法有效的抓取;需要时不时的抓取某个网页保存为截图作为快照,以用于诸如竞品监测分析等;诸如以上的场景可能在以前我们比较难以实现,或者现有的工具或多或少存在着某些不足。今天就来介绍一款 Go 语言写的基于 DevTools Protocol 的工具,叫 Rod 。

Rod的Github地址:/go-rod/rod

Rod 是什么?

Rod 是一款直接基于 DevTools Protocol 的高级 DevTools 驱动程序,它是为了网页自动化和抓取而设计的,Rod 还给用户暴露了一些底层接口,以便如果缺失某些功能的话,用户可以直接调用这些接口发送控制请求给浏览器。

Rod 能做什么?

既然是基于 DevTools Protocol 协议的,那基本 DevTools 能实现的功能大部分都能实现。比如浏览器页面控制、窗口控制、事件监听,根据选择器获取网页元素,模拟鼠标移动点击,页面事件监听、触发,网页注入脚本、样式表,网页内容修改,网页内容获取,执行脚本,Cookie 获取设置,页面截图,会话复用,页面监控等等功能。

Rod 的工作原理是什么?

Rod 在被调用后会尝试使用 WebSocket 去连接 DevTools,如果没有找到的话,会基于不同的系统尝试去一些默认的路径寻找本地浏览器,找到就打开,没有找到的话会尝试去下载一个再启动。

然后 Rod 使用 JSON-RPC 去和 DevTools 交互,以便控制浏览器。当需要控制某个具体的页面的时候,Rod 会给这个页面注入一个js的助手脚本,Rod 使用这个脚本来完成页面内容的获取,控制等。

其他同类工具存在什么问题?

chromedp 由于需要使用复杂的类 DSL 的任务来处理主逻辑,导致发生问题时很难通过理解代码来解决,也很难去追踪问题。chromedp 也无法处理 iframe,不支持影子 DOM,当程序崩溃时,会留下僵尸进程等。

selenium 由于是基于 webdriver protocol 的,功能上相对更少,比如没法处理关闭的影子 DOM,没办法保存网页为 PDF,没有对性能等工具的支持,由于依赖于浏览器驱动等也使得其变得难以使用和维护。虽然 selenium 宣称是支持跨浏览器的,但实际上在很多浏览器上都或多或少存在这样或那样的问题。

puppeteer 需要去处理复杂的 promise/async/await 问题,但在进行自动化测试的时候,更多想要同步的获取到状态之后再进行后续操作,对于 QA 来说不太友好。

cypress 对关闭的影子 DOM 限制很大,对跨域 iframe 来说也不太安全。

案例一:定时对某个网页截图

就像前面说的,有时候我们需要对某个竞品网页保持长期的关注,需要定时的保存快照来做分析,这时候我们就可以使用 rod 来方便的完成这个需求。

这里我写了一个小方法,每3秒(测试用,实际环境可以调整为半天、一天等频率)请求一次 gocn 这个网站,然后等页面加载完成后,将整个页面截图并按截图时间作为文件名保存到本地。

import ( "/go-rod/rod" "strconv" "time")func monitorGocn() {// 创建一个浏览器的实例 browser := rod.New().Connect() url := "https://gocn.vip" // 指定要获取的网页 page := browser.Page(url) // 指定窗口大小,避免截图时截不完整 page.Window(0, 0, 1024, 768) // 指定截图间隔时间,我这里是测试,就设置了3秒 interval := time.Duration(3) * time.Second for {select {casenowTimestamp := time.Now().Unix() nowTimestampStr := strconv.Itoa(int(nowTimestamp)) // 重定向页面,后面的参数无实意,只是为了确保页面刷新 page.Navigate(url + "/?__t__=" + nowTimestampStr) // 等待页面加载完成 wait := page.WaitRequestIdle() wait() file := "screenshot/" + nowTimestampStr + ".jpg" // 整个页面截图并保存 page.ScreenshotFullPage(file)} }}

截图的结果:

截图效果如下:

案例二:自动签到某度贴吧

这个案例主要是以自动签到某度贴吧为例展示自动化操作,我们复用了用户的登录信息,设定一些需要登录的贴吧的数组,每天自动打开每个贴吧的首页,点击签到按钮进行签到。

对签到按钮进行元素审查,很容易得到对应的元素选择器。

然后我们编写代码:

import ( "/go-rod/rod" "/go-rod/rod/lib/launcher" "time")func signInBa() {// 以NewUserMode形式启动,这样可以复用会话信息 // 当然你也可以以普通模式启动,自己调用程序登录 url := launcher.NewUserMode().Launch() browser := rod.New().ControlURL(url).Connect() // 先打开某度贴吧首页,方便复用 page := browser.Page("/") // 设定窗口大小 page.Window(0, 0, 1024, 768) // 等待页面加载完成 wait := page.WaitRequestIdle() wait() // 这里是需要签到的贴吧的名称 kws := []string{"php", "java", "javascript"} for _, kw := range kws {// 组装贴吧地址url := "/f?kw=" + kw// 前往某个贴吧首页page.Navigate(url)wait = page.WaitRequestIdle()wait()// 点击签到按钮page.Element(".j_signbtn").Click()// 休息10秒再继续time.Sleep(time.Duration(10) * time.Second) }}

执行后就可以看到如下效果:

以上两个案例也只是抛砖引玉,充分利用 Rod 能完成的功能远比这些强大,同时支持在 Docker 中启动浏览器,也就是说可以在服务器上去使用 Rod 的所有功能,写好的程序直接扔服务器上就可以等他定时执行,而且支持监控,也能自己处理错误来返回。

总之,用好 Rod 能使你的工作效率大大提升,也能为你完成各种定制化的自动化功能和高级抓取数据需求。

如果觉得《尝试自动重定向的次数太多_GoRod:基于DP协议的Web自动化和数据抓取工具》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。