baseaction.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. package browser
  2. import (
  3. "context"
  4. "log"
  5. "strings"
  6. "time"
  7. "KeyWebsiteMonitor/spider/util"
  8. "github.com/chromedp/cdproto/cdp"
  9. "github.com/chromedp/cdproto/fetch"
  10. "github.com/chromedp/cdproto/input"
  11. "github.com/chromedp/cdproto/network"
  12. "github.com/chromedp/cdproto/page"
  13. "github.com/chromedp/chromedp"
  14. )
  15. // CloseTabs关闭页面
  16. func (b *Browser) CloseTabs(tabTitle, tabUrl string, timeoutInt64 int64) (err error) {
  17. if timeoutInt64 == 0 {
  18. timeoutInt64 = 5
  19. }
  20. timeout := time.Duration(timeoutInt64) * time.Millisecond
  21. ts, err := chromedp.Targets(b.Ctx)
  22. if err != nil {
  23. return err
  24. }
  25. for _, t := range ts {
  26. bl := false
  27. if tabUrl != "" && t.URL != "" {
  28. tu := strings.ReplaceAll(strings.ReplaceAll(tabUrl, "https://", ""), "http://", "")
  29. tURL := strings.ReplaceAll(strings.ReplaceAll(t.URL, "https://", ""), "http://", "")
  30. if strings.Contains(tURL, tu) {
  31. bl = true
  32. }
  33. }
  34. log.Println(tabTitle != "", strings.Contains(t.Title, tabTitle), tabUrl != "", strings.Contains(t.URL, tabUrl), bl)
  35. if (tabTitle != "" && strings.Contains(t.Title, tabTitle)) ||
  36. (tabUrl != "" && strings.Contains(t.URL, tabUrl) ||
  37. bl) {
  38. newCtx, _ := chromedp.NewContext(b.Ctx, chromedp.WithTargetID(t.TargetID))
  39. ctx, _ := context.WithTimeout(newCtx, timeout)
  40. chromedp.Run(
  41. ctx,
  42. page.Close(),
  43. )
  44. } else {
  45. log.Printf("tabTile:%s ,taburl:%s ,无法关闭。", tabTitle, tabUrl)
  46. }
  47. }
  48. return nil
  49. }
  50. // CloseTabs关闭页面
  51. func (b *Browser) CloseTabsWithout(tabTitle, tabUrl string, timeoutInt64 int64) (err error) {
  52. if timeoutInt64 == 0 {
  53. timeoutInt64 = 5
  54. }
  55. timeout := time.Duration(timeoutInt64) * time.Millisecond
  56. ts, err := chromedp.Targets(b.Ctx)
  57. if err != nil {
  58. return err
  59. }
  60. for _, t := range ts {
  61. if (tabTitle != "" && !strings.Contains(t.Title, tabTitle)) ||
  62. (tabUrl != "" && !strings.Contains(t.URL, tabUrl)) {
  63. newCtx, _ := chromedp.NewContext(b.Ctx, chromedp.WithTargetID(t.TargetID))
  64. ctx, _ := context.WithTimeout(newCtx, timeout)
  65. chromedp.Run(
  66. ctx,
  67. page.Close(),
  68. )
  69. }
  70. }
  71. return nil
  72. }
  73. // Navigate 导航到指定网址
  74. func (b *Browser) Navigate(tabTitle string,
  75. tabUrl string, isNewTab bool,
  76. targetUrl string, timeout int64) (err error) {
  77. ctx, _, err := b.findTabContext(tabTitle, tabUrl, timeout)
  78. if err != nil {
  79. return err
  80. }
  81. //defer fn()
  82. //新标签页
  83. if isNewTab {
  84. ctx, _ = chromedp.NewContext(ctx)
  85. }
  86. //
  87. er := chromedp.Run(ctx,
  88. //这里作反爬检测
  89. chromedp.ActionFunc(func(cxt context.Context) error {
  90. _, err := page.AddScriptToEvaluateOnNewDocument("Object.defineProperty(navigator, 'webdriver', { get: () => false, });").Do(cxt)
  91. return err
  92. }),
  93. chromedp.Navigate(targetUrl))
  94. return er
  95. }
  96. func DisableFetchExceptScripts(ctx context.Context, abortUrls []string) func(event interface{}) {
  97. return func(event interface{}) {
  98. switch ev := event.(type) {
  99. case *fetch.EventRequestPaused:
  100. go func() {
  101. c := chromedp.FromContext(ctx)
  102. ctx := cdp.WithExecutor(ctx, c.Target)
  103. if util.StrHasFlags(ev.Request.URL, abortUrls) {
  104. //fmt.Println("Abort url", ev.Request.URL)
  105. fetch.FailRequest(ev.RequestID, network.ErrorReasonBlockedByClient).Do(ctx)
  106. } else {
  107. fetch.ContinueRequest(ev.RequestID).Do(ctx)
  108. }
  109. }()
  110. }
  111. }
  112. }
  113. // Navigate 导航到指定网址,可以中断一些不必要的请求
  114. func (b *Browser) NavigateWithAbortFlags(tabTitle string,
  115. tabUrl string, isNewTab bool,
  116. targetUrl string, abortUrlFlag string, timeout int64) (err error) {
  117. ctx, _, err := b.findTabContext(tabTitle, tabUrl, timeout)
  118. if err != nil {
  119. return err
  120. }
  121. //defer fn()
  122. //新标签页
  123. if isNewTab {
  124. ctx, _ = chromedp.NewContext(ctx)
  125. }
  126. flagArr := strings.Split(abortUrlFlag, ";")
  127. chromedp.ListenTarget(ctx, DisableFetchExceptScripts(ctx, flagArr))
  128. //
  129. return chromedp.Run(ctx,
  130. fetch.Enable(),
  131. //这里作反爬检测
  132. chromedp.ActionFunc(func(cxt context.Context) error {
  133. _, err := page.AddScriptToEvaluateOnNewDocument("Object.defineProperty(navigator, 'webdriver', { get: () => false, });").Do(cxt)
  134. return err
  135. }),
  136. chromedp.Navigate(targetUrl))
  137. }
  138. // Reload 重新加载tab页地址
  139. func (b *Browser) Reload(tabTitle string,
  140. tabUrl string, timeout int64) (err error) {
  141. ctx, fn, err := b.findTabContext(tabTitle, tabUrl, timeout)
  142. if err != nil {
  143. return err
  144. }
  145. defer fn()
  146. return chromedp.Run(ctx,
  147. chromedp.Reload())
  148. }
  149. // Back 回退
  150. func (b *Browser) Back(tabTitle string,
  151. tabUrl string, timeout int64) (err error) {
  152. ctx, _, err := b.findTabContext(tabTitle, tabUrl, timeout)
  153. if err != nil {
  154. return err
  155. }
  156. //defer fn()
  157. //
  158. return chromedp.Run(ctx,
  159. chromedp.NavigateBack())
  160. }
  161. // Forward 向前
  162. func (b *Browser) Forward(tabTitle string,
  163. tabUrl string, timeout int64) (err error) {
  164. ctx, _, err := b.findTabContext(tabTitle, tabUrl, timeout)
  165. if err != nil {
  166. return err
  167. }
  168. //defer fn()
  169. //
  170. return chromedp.Run(ctx,
  171. chromedp.NavigateForward())
  172. }
  173. // ExecuteJS 执行脚本
  174. //某些js需要延迟关闭 needsleep
  175. func (b *Browser) ExecuteJS(tabTitle, tabUrl, script string, ret interface{}, timeout int64, needSleep bool) (err error) {
  176. b.ExecuteJSChan <- true
  177. defer func() {
  178. <-b.ExecuteJSChan
  179. }()
  180. // log.Println("timeout", timeout)
  181. // timeout = 15 * 1000
  182. ctx, _, err := b.findTabContext(tabTitle, tabUrl, timeout+5000)
  183. if err != nil {
  184. return err
  185. }
  186. // defer fn()
  187. // return chromedp.Run(ctx,
  188. // chromedp.Evaluate(script, ret))
  189. if needSleep {
  190. err = chromedp.Run(ctx,
  191. chromedp.Evaluate(script, ret), chromedp.Sleep(time.Millisecond*time.Duration(timeout)))
  192. } else {
  193. err = chromedp.Run(ctx,
  194. chromedp.Evaluate(script, ret))
  195. }
  196. if err != nil {
  197. log.Println(needSleep, timeout, "err", err)
  198. }
  199. return err
  200. }
  201. // Click 点击
  202. func (b *Browser) Click(tabTitle, tabUrl, selector string, selectorType int, timeout int64) (err error) {
  203. ctx, _, err := b.findTabContext(tabTitle, tabUrl, timeout)
  204. if err != nil {
  205. return err
  206. }
  207. //defer fn()
  208. var act chromedp.QueryAction
  209. switch selectorType {
  210. case selector_type_id:
  211. act = chromedp.Click(selector, chromedp.ByID)
  212. case selector_type_query:
  213. act = chromedp.Click(selector, chromedp.ByQuery)
  214. case selector_type_search:
  215. act = chromedp.Click(selector, chromedp.BySearch)
  216. case selector_type_jspath:
  217. act = chromedp.Click(selector, chromedp.ByJSPath)
  218. default:
  219. act = chromedp.Click(selector, chromedp.ByQueryAll)
  220. }
  221. return chromedp.Run(ctx,
  222. act)
  223. }
  224. // keysend 键盘输入
  225. func (b *Browser) KeySend(tabTitle, tabUrl, selector, sendStr string,
  226. selectorType int, timeout int64) (err error) {
  227. ctx, _, err := b.findTabContext(tabTitle, tabUrl, timeout)
  228. if err != nil {
  229. return err
  230. }
  231. //defer fn()
  232. var act chromedp.QueryAction
  233. switch selectorType {
  234. case selector_type_id:
  235. act = chromedp.SendKeys(selector, sendStr, chromedp.ByID)
  236. case selector_type_query:
  237. act = chromedp.SendKeys(selector, sendStr, chromedp.ByQuery)
  238. case selector_type_search:
  239. act = chromedp.SendKeys(selector, sendStr, chromedp.BySearch)
  240. case selector_type_jspath:
  241. act = chromedp.SendKeys(selector, sendStr, chromedp.ByJSPath)
  242. default:
  243. act = chromedp.SendKeys(selector, sendStr, chromedp.ByQueryAll)
  244. }
  245. return chromedp.Run(ctx,
  246. act)
  247. }
  248. // WaitVisible 等待元素可见
  249. func (b *Browser) WaitVisible(tabTitle, tabUrl, selector string,
  250. selectorType int, timeout int64) error {
  251. ctx, _, err := b.findTabContext(tabTitle, tabUrl, timeout)
  252. if err != nil {
  253. return err
  254. }
  255. //defer fn()
  256. var act chromedp.QueryAction
  257. switch selectorType {
  258. case selector_type_id:
  259. act = chromedp.WaitVisible(selector, chromedp.ByID)
  260. case selector_type_query:
  261. act = chromedp.WaitVisible(selector, chromedp.ByQuery)
  262. case selector_type_search:
  263. act = chromedp.WaitVisible(selector, chromedp.BySearch)
  264. case selector_type_jspath:
  265. act = chromedp.WaitVisible(selector, chromedp.ByJSPath)
  266. case 22:
  267. act = chromedp.WaitReady(selector, chromedp.ByID)
  268. default:
  269. act = chromedp.WaitVisible(selector, chromedp.ByQueryAll)
  270. }
  271. return chromedp.Run(ctx,
  272. act)
  273. }
  274. // 鼠标点击 双击
  275. func (b *Browser) DoubleClick(tabTitle, tabUrl, selector string, selectorType int, timeout int64) (err error) {
  276. ctx, _, err := b.findTabContext(tabTitle, tabUrl, timeout)
  277. if err != nil {
  278. return err
  279. }
  280. //defer fn()
  281. var act chromedp.QueryAction
  282. switch selectorType {
  283. case selector_type_id:
  284. act = chromedp.DoubleClick(selector, chromedp.ByID)
  285. case selector_type_query:
  286. act = chromedp.DoubleClick(selector, chromedp.ByQuery)
  287. case selector_type_search:
  288. act = chromedp.DoubleClick(selector, chromedp.BySearch)
  289. case selector_type_jspath:
  290. act = chromedp.DoubleClick(selector, chromedp.ByJSPath)
  291. default:
  292. act = chromedp.DoubleClick(selector, chromedp.ByQueryAll)
  293. }
  294. return chromedp.Run(ctx,
  295. act)
  296. }
  297. // 鼠标拖拽
  298. func (b *Browser) MouseDrag(tabTitle, tabUrl string, points [][2]float64, delay []int64, timeout int64) (err error) {
  299. ctx, _, err := b.findTabContext(tabTitle, tabUrl, timeout)
  300. if err != nil {
  301. return err
  302. }
  303. //defer fn()
  304. //鼠标拖拽
  305. actionsLen := len(points)*2 + 2
  306. pointsLen := len(points)
  307. var acts = make([]chromedp.Action, actionsLen, actionsLen)
  308. //第一个动作
  309. acts[0] = chromedp.MouseEvent(input.MousePressed, points[0][0], points[0][1], chromedp.ButtonLeft)
  310. for i := 1; i <= len(points); i++ {
  311. acts[i*2] = chromedp.MouseEvent(input.MouseMoved, points[i-1][0], points[i-1][1], chromedp.ButtonLeft)
  312. acts[i*2+1] = chromedp.Sleep(time.Duration(delay[i]) * time.Millisecond)
  313. }
  314. acts[actionsLen-1] = chromedp.MouseEvent(input.MouseReleased, points[pointsLen-1][0], points[pointsLen-1][1], chromedp.ButtonLeft)
  315. return chromedp.Run(ctx,
  316. acts...)
  317. }
  318. // 等待准备好
  319. func (b *Browser) WaitReady(tabTitle, tabUrl, selector string, selectorType int, timeout int64) (err error) {
  320. ctx, _, err := b.findTabContext(tabTitle, tabUrl, timeout)
  321. if err != nil {
  322. return err
  323. }
  324. //defer fn()
  325. var act chromedp.QueryAction
  326. switch selectorType {
  327. case selector_type_id:
  328. act = chromedp.WaitReady(selector, chromedp.ByID)
  329. case selector_type_query:
  330. act = chromedp.WaitReady(selector, chromedp.ByQuery)
  331. case selector_type_search:
  332. act = chromedp.WaitReady(selector, chromedp.BySearch)
  333. case selector_type_jspath:
  334. act = chromedp.WaitReady(selector, chromedp.ByJSPath)
  335. default:
  336. act = chromedp.WaitReady(selector, chromedp.ByQueryAll)
  337. }
  338. return chromedp.Run(ctx,
  339. act)
  340. }