chromedp
chromedp 是一個用于 Chrome 瀏覽器的自動化測試工具,基于 Go 語言開發,專門用于控制和操作 Chrome 瀏覽器實例。
chromedp 安裝
go get -u github.com/chromedp/chromedp
基于chromedp 實現的的簡易學習通刷課系統
目前實現的功能:
- 自動登錄,找到課程中第一個沒刷的課
- 視頻播放意外暫停時,自動恢復播放
package mainimport ("context""fmt""log""time""github.com/chromedp/chromedp"
)func main() {// 1. 創建有界面的瀏覽器選項opts := append(chromedp.DefaultExecAllocatorOptions[:],chromedp.Flag("headless", false),chromedp.Flag("start-maximized", true),chromedp.UserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36"),)// 2. 創建上下文allocCtx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)defer cancel()ctx, cancel := chromedp.NewContext(allocCtx, chromedp.WithLogf(log.Printf))defer cancel()// 3. 運行主流程err := chromedp.Run(ctx,// 登錄流程chromedp.Navigate("課程url"), // 替換為要刷的課的urlchromedp.WaitVisible(`#phone`, chromedp.ByID), chromedp.SendKeys(`#phone`, "賬號", chromedp.ByID), // 替換為自己的賬號chromedp.SendKeys(`#pwd`, "密碼", chromedp.ByID), // 替換為自己的密碼chromedp.Click(`#loginBtn`, chromedp.ByID),chromedp.Sleep(3*time.Second),// 開始學習流程startLearningProcess(),)if err != nil {log.Fatal("運行失敗: ", err)}
}func startLearningProcess() chromedp.Action {return chromedp.ActionFunc(func(ctx context.Context) error {// 1. 點擊第一個待完成任務if err := chromedp.Run(ctx,chromedp.WaitVisible(`.catalog_points_yi`, chromedp.ByQuery),chromedp.Click(`.posCatalog_select:has(.catalog_points_yi) .posCatalog_name`, chromedp.NodeVisible),chromedp.Sleep(2*time.Second),); err != nil {return fmt.Errorf("點擊任務失敗: %w", err)}// 2. 處理視頻播放if err := handleVideoPlayback(ctx); err != nil {return fmt.Errorf("視頻處理失敗: %w", err)}// todo 視頻結束后自動刷題return nil})
}func handleVideoPlayback(ctx context.Context) error {// 嘗試點擊播放按鈕if err := chromedp.Run(ctx,chromedp.Click(`//button[@class="vjs-big-play-button"]`, chromedp.NodeVisible),chromedp.Sleep(3*time.Second),); err != nil {log.Println("未能點擊播放按鈕,可能已自動播放:", err)}// 監控視頻狀態for {var videoState struct {CurrentTime float64 `js:"currentTime"`Duration float64 `js:"duration"`Ended bool `js:"ended"`Paused bool `js:"paused"`}var result []interface{}err := chromedp.Evaluate(`var video = document.getElementById('iframe').contentWindow.document.querySelector(".ans-attach-online").contentWindow.document.getElementById('video_html5_api');[video.currentTime,video.duration,video.ended,video.paused]
`, &result).Do(ctx)videoState.CurrentTime = result[0].(float64)videoState.Duration = result[1].(float64)videoState.Ended = result[2].(bool)videoState.Paused = result[3].(bool)if err != nil {return fmt.Errorf("獲取視頻狀態失敗: %w", err)}if videoState.Duration == 0 {log.Println("等待視頻加載...")time.Sleep(3 * time.Second)continue}log.Printf("視頻進度: %.1f/%.1f秒, 已暫停: %v, 已結束: %v",videoState.CurrentTime, videoState.Duration, videoState.Paused, videoState.Ended)if videoState.Ended {log.Println("視頻播放結束")return nil}if videoState.Paused {log.Println("檢測到視頻暫停,嘗試恢復播放...")if err := chromedp.Run(ctx,chromedp.Evaluate(`document.getElementById('iframe').contentWindow.document.querySelector(".ans-attach-online").contentWindow.document.getElementById('video_html5_api').play()`, nil),); err != nil {log.Println("恢復播放失敗:", err)}}time.Sleep(10 * time.Second) // 每10秒檢查一次}
}
課程url為該頁面的url: