尝试自动重定向的次数太多_GoRod:基于DP协议的Web自动化和数据抓取工具
在日常開發中我們經常可能會遇到這樣一些情景:需要使用一些自動化的手段來幫助我們測試;在獲取某些網頁的數據的時候,由于目標網頁的數據是動態的,使用傳統的數據獲取手段無法有效的抓取;需要時不時的抓取某個網頁保存為截圖作為快照,以用于諸如競品監測分析等;諸如以上的場景可能在以前我們比較難以實現,或者現有的工具或多或少存在著某些不足。今天就來介紹一款 Go 語言寫的基于 DevTools Protocol 的工具,叫 Rod 。
Rod的Github地址:https://github.com/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 ( "github.com/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 { case nowTimestamp := 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 ( "github.com/go-rod/rod" "github.com/go-rod/rod/lib/launcher" "time")func signInBa() { // 以NewUserMode形式啟動,這樣可以復用會話信息 // 當然你也可以以普通模式啟動,自己調用程序登錄 url := launcher.NewUserMode().Launch() browser := rod.New().ControlURL(url).Connect() // 先打開某度貼吧首頁,方便復用 page := browser.Page("https://tieba.example.com/") // 設定窗口大小 page.Window(0, 0, 1024, 768) // 等待頁面加載完成 wait := page.WaitRequestIdle() wait() // 這里是需要簽到的貼吧的名稱 kws := []string{"php", "java", "javascript"} for _, kw := range kws { // 組裝貼吧地址 url := "https://tieba.example.com/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自动化和数据抓取工具的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: sublime python运行快捷键_
- 下一篇: vc2010中开始执行不调试灰的_消防水