| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254 |
- package rod_helper
- import (
- "context"
- "crypto/tls"
- "errors"
- "github.com/go-rod/rod"
- "github.com/go-rod/rod/lib/launcher"
- "github.com/go-rod/rod/lib/proto"
- "net/http"
- "net/url"
- "time"
- )
- /**
- * @Description: 新建一个支持代理的 browser 对象
- * @param httpProxyURL http://127.0.0.1:10809
- * @return *rod.Browser
- * @return error
- */
- func NewBrowser(httpProxyURL string) (*rod.Browser, error) {
- var browser *rod.Browser
- err := rod.Try(func() {
- u := launcher.New().
- Proxy(httpProxyURL).
- MustLaunch()
- browser = rod.New().ControlURL(u).MustConnect()
- })
- if err != nil {
- return nil, err
- }
- return browser, nil
- }
- /**
- * @Description: 访问目标 Url,返回 page,只是这个 page 有效,如果再次出发其他的事件无效
- * @param desURL 目标 Url
- * @param httpProxyURL http://127.0.0.1:10809
- * @param timeOut 超时时间
- * @param maxRetryTimes 当是非超时 err 的时候,最多可以重试几次
- * @return *rod.Page
- * @return error
- */
- func NewBrowserFromDocker(httpProxyURL, remoteDockerURL string) (*rod.Browser, error) {
- var browser *rod.Browser
- err := rod.Try(func() {
- l := launcher.MustNewRemote(remoteDockerURL)
- u := l.Proxy(httpProxyURL).MustLaunch()
- l.Headless(false).XVFB()
- browser = rod.New().Client(l.Client()).ControlURL(u).MustConnect()
- })
- if err != nil {
- return nil, err
- }
- return browser, nil
- }
- func NewPage(browser *rod.Browser) (*rod.Page, error) {
- page, err := browser.Page(proto.TargetCreateTarget{URL: ""})
- if err != nil {
- return nil, err
- }
- return page, err
- }
- func NewPageNavigate(browser *rod.Browser, desURL string, timeOut time.Duration, maxRetryTimes int) (*rod.Page, error) {
- page, err := NewPage(browser)
- if err != nil {
- return nil, err
- }
- page = page.Timeout(timeOut)
- nowRetryTimes := 0
- for nowRetryTimes <= maxRetryTimes {
- err = rod.Try(func() {
- wait := page.MustWaitNavigation()
- page.MustNavigate(desURL)
- wait()
- })
- if errors.Is(err, context.DeadlineExceeded) {
- // 超时
- return nil, err
- } else if err == nil {
- // 没有问题
- return page, nil
- }
- }
- return nil, err
- }
- func PageNavigate(page *rod.Page, desURL string, timeOut time.Duration, maxRetryTimes int) (*rod.Page, error) {
- var err error
- page = page.Timeout(timeOut)
- nowRetryTimes := 0
- for nowRetryTimes <= maxRetryTimes {
- err = rod.Try(func() {
- wait := page.MustWaitNavigation()
- page.MustNavigate(desURL)
- wait()
- })
- if errors.Is(err, context.DeadlineExceeded) {
- // 超时
- return nil, err
- } else if err == nil {
- // 没有问题
- return page, nil
- }
- }
- return nil, err
- }
- /**
- * @Description: 访问目标 Url,返回 page,只是这个 page 有效,如果再次出发其他的事件无效
- * @param desURL 目标 Url
- * @param httpProxyURL http://127.0.0.1:10809
- * @param timeOut 超时时间
- * @param maxRetryTimes 当是非超时 err 的时候,最多可以重试几次
- * @return *rod.Page
- * @return error
- */
- func NewBrowserLoadPage(desURL string, httpProxyURL string, timeOut time.Duration, maxRetryTimes int) (*rod.Page, error) {
- browser, err := NewBrowser(httpProxyURL)
- if err != nil {
- return nil, err
- }
- page, err := browser.Page(proto.TargetCreateTarget{URL: ""})
- if err != nil {
- return nil, err
- }
- page = page.Timeout(timeOut)
- nowRetryTimes := 0
- for nowRetryTimes <= maxRetryTimes {
- err = rod.Try(func() {
- wait := page.MustWaitNavigation()
- page.MustNavigate(desURL)
- wait()
- })
- if errors.Is(err, context.DeadlineExceeded) {
- // 超时
- return nil, err
- } else if err == nil {
- // 没有问题
- return page, nil
- }
- }
- return nil, err
- }
- /**
- * @Description: 访问目标 Url,返回 page,只是这个 page 有效,如果再次出发其他的事件无效
- * @param desURL 目标 Url
- * @param httpProxyURL http://127.0.0.1:10809
- * @param timeOut 超时时间
- * @param maxRetryTimes 当是非超时 err 的时候,最多可以重试几次
- * @return *rod.Page
- * @return error
- */
- func NewBrowserLoadPageFromRemoteDocker(desURL string, httpProxyURL, remoteDockerURL string, timeOut time.Duration, maxRetryTimes int) (*rod.Page, error) {
- browser, err := NewBrowserFromDocker(httpProxyURL, remoteDockerURL)
- if err != nil {
- return nil, err
- }
- page, err := browser.Page(proto.TargetCreateTarget{URL: ""})
- if err != nil {
- return nil, err
- }
- page = page.Timeout(timeOut)
- nowRetryTimes := 0
- for nowRetryTimes <= maxRetryTimes {
- err = rod.Try(func() {
- wait := page.MustWaitNavigation()
- page.MustNavigate(desURL)
- wait()
- })
- if errors.Is(err, context.DeadlineExceeded) {
- // 超时
- return nil, err
- } else if err == nil {
- // 没有问题
- break
- }
- }
- return page, nil
- }
- /**
- * @Description: 访问目标 Url,返回 page,只是这个 page 有效,如果再次出发其他的事件无效
- * @param desURL 目标 Url
- * @param httpProxyURL http://127.0.0.1:10809
- * @param timeOut 超时时间
- * @param maxRetryTimes 当是非超时 err 的时候,最多可以重试几次
- * @return *rod.Page
- * @return error
- */
- func NewBrowserLoadPageByHijackRequests(desURL string, httpProxyURL string, timeOut time.Duration, maxRetryTimes int) (*rod.Page, error) {
- var page *rod.Page
- var err error
- // 创建一个 page
- browser := rod.New()
- err = browser.Connect()
- if err != nil {
- return nil, err
- }
- page, err = browser.Page(proto.TargetCreateTarget{URL: ""})
- if err != nil {
- return nil, err
- }
- page = page.Timeout(timeOut)
- // 设置代理
- router := page.HijackRequests()
- defer router.Stop()
- err = rod.Try(func() {
- router.MustAdd("*", func(ctx *rod.Hijack) {
- px, _ := url.Parse(httpProxyURL)
- ctx.LoadResponse(&http.Client{
- Transport: &http.Transport{
- Proxy: http.ProxyURL(px),
- TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
- },
- Timeout: timeOut,
- }, true)
- })
- })
- if err != nil {
- return nil ,err
- }
- go router.Run()
- nowRetryTimes := 0
- for nowRetryTimes <= maxRetryTimes {
- err = rod.Try(func() {
- page.MustNavigate(desURL).MustWaitLoad()
- })
- if errors.Is(err, context.DeadlineExceeded) {
- // 超时
- return nil, err
- } else if err == nil {
- // 没有问题
- break
- }
- time.Sleep(time.Second)
- nowRetryTimes++
- }
- return page, nil
- }
|