rod_utils.go 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. package common
  2. import (
  3. "errors"
  4. "git.listensoft.net/tool/jspkit/common/lxrod"
  5. "git.listensoft.net/tool/jspkit/logger"
  6. "git.listensoft.net/tool/jspkit/taxerr"
  7. "github.com/go-kratos/kratos/v2/log"
  8. "github.com/go-rod/rod"
  9. "github.com/go-rod/rod/lib/input"
  10. "github.com/go-rod/rod/lib/proto"
  11. "github.com/go-rod/rod/lib/utils"
  12. "go.uber.org/zap"
  13. "strings"
  14. "time"
  15. )
  16. func MustHas(page *rod.Page, xpath string) bool {
  17. x, _, _ := HasX(page, xpath)
  18. return x
  19. }
  20. func MustHasX(page *rod.Page, xpath string) bool {
  21. x, _, _ := HasX(page, xpath)
  22. return x
  23. }
  24. func MustHasXV(page *rod.Page, xpath string) bool {
  25. for _, element := range MustElementsX(page, xpath) {
  26. visible, _ := element.Visible()
  27. if visible {
  28. return true
  29. }
  30. }
  31. return false
  32. }
  33. func MustElementX(page *rod.Page, xpath string) *rod.Element {
  34. for i := 0; i < 5; i++ {
  35. x, _ := ElementX(page, xpath)
  36. if x != nil {
  37. return x
  38. }
  39. utils.Sleep(1)
  40. }
  41. return nil
  42. }
  43. func MustHasXV1(page *rod.Page, xpath string) bool {
  44. for _, element := range MustElementsX1(page, xpath) {
  45. visible, _ := element.Visible()
  46. if visible {
  47. return true
  48. }
  49. }
  50. return false
  51. }
  52. func HasX(page *rod.Page, xpath string) (bool, *rod.Element, error) {
  53. var x *rod.Element
  54. var has bool
  55. var err error
  56. err = rod.Try(func() {
  57. has, x, err = page.HasX(xpath)
  58. if has {
  59. return
  60. }
  61. if err != nil {
  62. panic(err)
  63. }
  64. if has {
  65. return
  66. }
  67. iframe := GetAllIframe(page)
  68. for _, pg := range iframe {
  69. has, x, err = pg.HasX(xpath)
  70. if has {
  71. return
  72. }
  73. if err != nil {
  74. panic(err)
  75. }
  76. if has {
  77. return
  78. }
  79. }
  80. })
  81. if x != nil {
  82. x = x.Timeout(time.Second * 15)
  83. }
  84. return has, x, err
  85. }
  86. func ElementX(page *rod.Page, xpath string) (*rod.Element, error) {
  87. _, element, err := HasX(page, xpath)
  88. if err != nil {
  89. err = taxerr.NewWebStuckTitle(false)
  90. }
  91. return element, err
  92. }
  93. func GetAllIframe(page *rod.Page) []*rod.Page {
  94. fs := make([]*rod.Page, 0)
  95. if page.MustHasX(`//iframe`) {
  96. for _, element := range page.MustElementsX(`//iframe`) {
  97. fs = append(fs, element.MustFrame())
  98. fs = append(fs, GetAllIframe(element.MustFrame())...)
  99. }
  100. }
  101. return fs
  102. }
  103. func MustElementXV(page *rod.Page, xpath string) *rod.Element {
  104. for i := 0; i < 5; i++ {
  105. x, _ := ElementsX(page, xpath)
  106. for _, element := range x {
  107. visible, _ := element.Visible()
  108. if visible {
  109. return element
  110. }
  111. }
  112. utils.Sleep(1)
  113. }
  114. return nil
  115. }
  116. func MustElementsX(page *rod.Page, xpath string) (x []*rod.Element) {
  117. for i := 0; i < 5; i++ {
  118. x, _ = ElementsX(page, xpath)
  119. if len(x) != 0 {
  120. break
  121. }
  122. utils.Sleep(1)
  123. }
  124. return x
  125. }
  126. func MustElementsX1(page *rod.Page, xpath string) (x []*rod.Element) {
  127. x, _ = ElementsX(page, xpath)
  128. return x
  129. }
  130. func ElementsX(page *rod.Page, xpath string) ([]*rod.Element, error) {
  131. var arr []*rod.Element
  132. var err error
  133. err = rod.Try(func() {
  134. r, _ := page.Timeout(ClickTimeOut).ElementsX(xpath)
  135. if err != nil {
  136. panic(err)
  137. }
  138. arr = append(arr, r...)
  139. for _, pg := range GetAllIframe(page) {
  140. pg.MustWaitLoad()
  141. r, err = pg.Timeout(ClickTimeOut).ElementsX(xpath)
  142. if err != nil {
  143. panic(err)
  144. }
  145. arr = append(arr, r...)
  146. }
  147. })
  148. return arr, err
  149. }
  150. func WaitElementX(page *rod.Page, xpath string, interval float64) *rod.Element {
  151. for i := 0; i < 60; i++ {
  152. if has, el, _ := HasX(page, xpath); has {
  153. return el
  154. }
  155. time.Sleep(time.Duration(float64(time.Second) * interval))
  156. }
  157. return nil
  158. }
  159. func WaitNavigation(page *rod.Page, url string) {
  160. navigation := page.Timeout(time.Minute).MustWaitNavigation()
  161. page.Timeout(time.Minute).MustNavigate(url)
  162. logger.Info("调试埋点11-1")
  163. utils.Sleep(1)
  164. WaitTimeOut(navigation, time.Minute)
  165. logger.Info("埋点11-2")
  166. }
  167. func WaitTimeOut(f func(), timeout time.Duration) {
  168. resultChan := make(chan struct{}, 1)
  169. go func() {
  170. f()
  171. resultChan <- struct{}{}
  172. }()
  173. select {
  174. case <-resultChan:
  175. return
  176. case <-time.After(timeout):
  177. panic(taxerr.NewWebStuckTitle(ComInfo.Cscsts))
  178. }
  179. }
  180. func Link(p *rod.Page) {
  181. go func() {
  182. //for {
  183. //utils.Sleep(1)
  184. if p == nil {
  185. return
  186. }
  187. rod.Try(func() {
  188. lxrod.DialogWatch(nil, p)
  189. go p.Browser().EachEvent(func(e *proto.TargetTargetCreated) {
  190. defer func() {
  191. if r := recover(); r != nil {
  192. logger.Error("EachPageCreatedEvent recover:", zap.Any("r", r))
  193. }
  194. }()
  195. if e.TargetInfo.Type != proto.TargetTargetInfoTypePage {
  196. return
  197. }
  198. page := p.Browser().MustPageFromTargetID(e.TargetInfo.TargetID)
  199. lxrod.DialogWatch(nil, page)
  200. })()
  201. // has, _, _ := p.Has("dialog")
  202. // if has {
  203. // _, _ = p.Eval(`
  204. //window.alert = function() {};
  205. //window.confirm = function() { return true; };
  206. //window.prompt = function() {};`)
  207. // }
  208. })
  209. //}
  210. }()
  211. }
  212. // 有就点 没有就不点击
  213. func MustClick(page *rod.Page, xpath string) {
  214. x := MustElementsX(page, xpath)
  215. for _, element := range x {
  216. visible, _ := element.Visible()
  217. if visible {
  218. element.MustClick()
  219. break
  220. }
  221. }
  222. }
  223. func MustText(page *rod.Page, xpath string) string {
  224. //去掉左右空格
  225. return strings.TrimSpace(MustElementX(page, xpath).MustText())
  226. }
  227. // 输入文字
  228. func Input(p *rod.Page, selector, inputVal string) {
  229. err := rod.Try(func() {
  230. if inputVal == "" || inputVal == "*" {
  231. inputVal = "0"
  232. }
  233. e := rod.Try(func() {
  234. p.Timeout(time.Second).MustSearch(selector).MustSelectAllText().MustFrame().Keyboard.MustType(input.Backspace)
  235. })
  236. if e != nil {
  237. if w := errors.Unwrap(e); w != nil {
  238. log.Info(w.Error() + "-" + selector + "-" + inputVal)
  239. } else {
  240. log.Info(e.Error() + "-" + selector + "-" + inputVal)
  241. }
  242. }
  243. e = rod.Try(func() {
  244. p.Timeout(time.Second).MustSearch(selector).MustSelectAllText().MustInput(inputVal)
  245. })
  246. if e != nil {
  247. if w := errors.Unwrap(e); w != nil {
  248. log.Info(strings.Split(w.Error(), "\t")[0] + "-" + selector + "-" + inputVal)
  249. } else {
  250. log.Info(strings.Split(e.Error(), "\t")[0] + "-" + selector + "-" + inputVal)
  251. }
  252. }
  253. })
  254. if err != nil {
  255. log.Info(err.Error() + "-" + selector + "-" + inputVal)
  256. }
  257. }
  258. // 输入文字
  259. func MustInputX(p *rod.Page, xPath, inputVal string) {
  260. e := MustElementX(p, xPath)
  261. _ = e.ScrollIntoView()
  262. e.MustClick().MustSelectAllText().MustInput(inputVal)
  263. }
  264. // 拦截请求
  265. func PageHijackReq(b *rod.Page, pattern string, ch chan []byte) *rod.HijackRouter {
  266. router := b.HijackRequests()
  267. router.MustAdd(pattern, func(ctx *rod.Hijack) {
  268. rod.Try(func() {
  269. ctx.MustLoadResponse()
  270. ch <- []byte(ctx.Response.Body())
  271. utils.Sleep(5)
  272. select {
  273. case <-ch:
  274. break
  275. }
  276. })
  277. })
  278. go router.Run()
  279. return router
  280. }
  281. // 获取拦截请求的值
  282. func GetHijackResp(ch chan []byte, t float64) ([]byte, error) {
  283. d := time.Duration(t * float64(time.Second))
  284. select {
  285. case val := <-ch:
  286. return val, nil
  287. case <-time.After(d):
  288. return nil, errors.New("请求网页超时,请稍后重试!")
  289. }
  290. }