rodHelper.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. package rod_helper
  2. import (
  3. "context"
  4. "crypto/tls"
  5. "errors"
  6. "github.com/go-rod/rod"
  7. "github.com/go-rod/rod/lib/launcher"
  8. "github.com/go-rod/rod/lib/proto"
  9. "net/http"
  10. "net/url"
  11. "time"
  12. )
  13. /**
  14. * @Description: 新建一个支持代理的 browser 对象
  15. * @param httpProxyURL http://127.0.0.1:10809
  16. * @return *rod.Browser
  17. * @return error
  18. */
  19. func NewBrowser(httpProxyURL string) (*rod.Browser, error) {
  20. var browser *rod.Browser
  21. err := rod.Try(func() {
  22. u := launcher.New().
  23. Proxy(httpProxyURL).
  24. MustLaunch()
  25. browser = rod.New().ControlURL(u).MustConnect()
  26. })
  27. if err != nil {
  28. return nil, err
  29. }
  30. return browser, nil
  31. }
  32. /**
  33. * @Description: 访问目标 Url,返回 page,只是这个 page 有效,如果再次出发其他的事件无效
  34. * @param desURL 目标 Url
  35. * @param httpProxyURL http://127.0.0.1:10809
  36. * @param timeOut 超时时间
  37. * @param maxRetryTimes 当是非超时 err 的时候,最多可以重试几次
  38. * @return *rod.Page
  39. * @return error
  40. */
  41. func NewBrowserFromDocker(httpProxyURL, remoteDockerURL string) (*rod.Browser, error) {
  42. var browser *rod.Browser
  43. err := rod.Try(func() {
  44. l := launcher.MustNewRemote(remoteDockerURL)
  45. u := l.Proxy(httpProxyURL).MustLaunch()
  46. l.Headless(false).XVFB()
  47. browser = rod.New().Client(l.Client()).ControlURL(u).MustConnect()
  48. })
  49. if err != nil {
  50. return nil, err
  51. }
  52. return browser, nil
  53. }
  54. func NewPage(browser *rod.Browser) (*rod.Page, error) {
  55. page, err := browser.Page(proto.TargetCreateTarget{URL: ""})
  56. if err != nil {
  57. return nil, err
  58. }
  59. return page, err
  60. }
  61. func NewPageNavigate(browser *rod.Browser, desURL string, timeOut time.Duration, maxRetryTimes int) (*rod.Page, error) {
  62. page, err := NewPage(browser)
  63. if err != nil {
  64. return nil, err
  65. }
  66. page = page.Timeout(timeOut)
  67. nowRetryTimes := 0
  68. for nowRetryTimes <= maxRetryTimes {
  69. err = rod.Try(func() {
  70. wait := page.MustWaitNavigation()
  71. page.MustNavigate(desURL)
  72. wait()
  73. })
  74. if errors.Is(err, context.DeadlineExceeded) {
  75. // 超时
  76. return nil, err
  77. } else if err == nil {
  78. // 没有问题
  79. return page, nil
  80. }
  81. }
  82. return nil, err
  83. }
  84. func PageNavigate(page *rod.Page, desURL string, timeOut time.Duration, maxRetryTimes int) (*rod.Page, error) {
  85. var err error
  86. page = page.Timeout(timeOut)
  87. nowRetryTimes := 0
  88. for nowRetryTimes <= maxRetryTimes {
  89. err = rod.Try(func() {
  90. wait := page.MustWaitNavigation()
  91. page.MustNavigate(desURL)
  92. wait()
  93. })
  94. if errors.Is(err, context.DeadlineExceeded) {
  95. // 超时
  96. return nil, err
  97. } else if err == nil {
  98. // 没有问题
  99. return page, nil
  100. }
  101. }
  102. return nil, err
  103. }
  104. /**
  105. * @Description: 访问目标 Url,返回 page,只是这个 page 有效,如果再次出发其他的事件无效
  106. * @param desURL 目标 Url
  107. * @param httpProxyURL http://127.0.0.1:10809
  108. * @param timeOut 超时时间
  109. * @param maxRetryTimes 当是非超时 err 的时候,最多可以重试几次
  110. * @return *rod.Page
  111. * @return error
  112. */
  113. func NewBrowserLoadPage(desURL string, httpProxyURL string, timeOut time.Duration, maxRetryTimes int) (*rod.Page, error) {
  114. browser, err := NewBrowser(httpProxyURL)
  115. if err != nil {
  116. return nil, err
  117. }
  118. page, err := browser.Page(proto.TargetCreateTarget{URL: ""})
  119. if err != nil {
  120. return nil, err
  121. }
  122. page = page.Timeout(timeOut)
  123. nowRetryTimes := 0
  124. for nowRetryTimes <= maxRetryTimes {
  125. err = rod.Try(func() {
  126. wait := page.MustWaitNavigation()
  127. page.MustNavigate(desURL)
  128. wait()
  129. })
  130. if errors.Is(err, context.DeadlineExceeded) {
  131. // 超时
  132. return nil, err
  133. } else if err == nil {
  134. // 没有问题
  135. return page, nil
  136. }
  137. }
  138. return nil, err
  139. }
  140. /**
  141. * @Description: 访问目标 Url,返回 page,只是这个 page 有效,如果再次出发其他的事件无效
  142. * @param desURL 目标 Url
  143. * @param httpProxyURL http://127.0.0.1:10809
  144. * @param timeOut 超时时间
  145. * @param maxRetryTimes 当是非超时 err 的时候,最多可以重试几次
  146. * @return *rod.Page
  147. * @return error
  148. */
  149. func NewBrowserLoadPageFromRemoteDocker(desURL string, httpProxyURL, remoteDockerURL string, timeOut time.Duration, maxRetryTimes int) (*rod.Page, error) {
  150. browser, err := NewBrowserFromDocker(httpProxyURL, remoteDockerURL)
  151. if err != nil {
  152. return nil, err
  153. }
  154. page, err := browser.Page(proto.TargetCreateTarget{URL: ""})
  155. if err != nil {
  156. return nil, err
  157. }
  158. page = page.Timeout(timeOut)
  159. nowRetryTimes := 0
  160. for nowRetryTimes <= maxRetryTimes {
  161. err = rod.Try(func() {
  162. wait := page.MustWaitNavigation()
  163. page.MustNavigate(desURL)
  164. wait()
  165. })
  166. if errors.Is(err, context.DeadlineExceeded) {
  167. // 超时
  168. return nil, err
  169. } else if err == nil {
  170. // 没有问题
  171. break
  172. }
  173. }
  174. return page, nil
  175. }
  176. /**
  177. * @Description: 访问目标 Url,返回 page,只是这个 page 有效,如果再次出发其他的事件无效
  178. * @param desURL 目标 Url
  179. * @param httpProxyURL http://127.0.0.1:10809
  180. * @param timeOut 超时时间
  181. * @param maxRetryTimes 当是非超时 err 的时候,最多可以重试几次
  182. * @return *rod.Page
  183. * @return error
  184. */
  185. func NewBrowserLoadPageByHijackRequests(desURL string, httpProxyURL string, timeOut time.Duration, maxRetryTimes int) (*rod.Page, error) {
  186. var page *rod.Page
  187. var err error
  188. // 创建一个 page
  189. browser := rod.New()
  190. err = browser.Connect()
  191. if err != nil {
  192. return nil, err
  193. }
  194. page, err = browser.Page(proto.TargetCreateTarget{URL: ""})
  195. if err != nil {
  196. return nil, err
  197. }
  198. page = page.Timeout(timeOut)
  199. // 设置代理
  200. router := page.HijackRequests()
  201. defer router.Stop()
  202. err = rod.Try(func() {
  203. router.MustAdd("*", func(ctx *rod.Hijack) {
  204. px, _ := url.Parse(httpProxyURL)
  205. ctx.LoadResponse(&http.Client{
  206. Transport: &http.Transport{
  207. Proxy: http.ProxyURL(px),
  208. TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
  209. },
  210. Timeout: timeOut,
  211. }, true)
  212. })
  213. })
  214. if err != nil {
  215. return nil ,err
  216. }
  217. go router.Run()
  218. nowRetryTimes := 0
  219. for nowRetryTimes <= maxRetryTimes {
  220. err = rod.Try(func() {
  221. page.MustNavigate(desURL).MustWaitLoad()
  222. })
  223. if errors.Is(err, context.DeadlineExceeded) {
  224. // 超时
  225. return nil, err
  226. } else if err == nil {
  227. // 没有问题
  228. break
  229. }
  230. time.Sleep(time.Second)
  231. nowRetryTimes++
  232. }
  233. return page, nil
  234. }