rod.go 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959
  1. package lxrod
  2. import (
  3. "context"
  4. "encoding/base64"
  5. "fmt"
  6. "git.listensoft.net/tool/jspkit/common/lxhttp"
  7. "git.listensoft.net/tool/jspkit/common/variable"
  8. "git.listensoft.net/tool/jspkit/taxerr"
  9. "github.com/go-rod/stealth"
  10. "io"
  11. "net/http"
  12. "net/url"
  13. "os"
  14. "os/exec"
  15. "strconv"
  16. "strings"
  17. "time"
  18. "github.com/go-rod/rod"
  19. "github.com/go-rod/rod/lib/launcher"
  20. "github.com/go-rod/rod/lib/proto"
  21. "github.com/go-rod/rod/lib/utils"
  22. )
  23. var (
  24. LastAlertMsg = make(chan string, 100)
  25. )
  26. // 只允许task.go 初始化一次
  27. type Lxrod struct {
  28. Area variable.Area
  29. Browser *rod.Browser
  30. Launcher *launcher.Launcher
  31. NoByPass bool //添加反反爬虫代码 原理就是执行一段js去掉window属性中关于自动化的代码
  32. Headless bool //headless 默认显示浏览器 为true是不显示浏览器
  33. MonitorDialog bool //默认监控alert然后去点击true 如果要自己处理 设置为true不添加监控
  34. PageEvent bool //默认每个页面的监听事件 设置为true不添加监控
  35. UseProxy bool //代理
  36. Leakless bool
  37. NoDefaultDevice bool
  38. Proxy string
  39. ProxyAuth string
  40. WsURL string // rod的ws地址
  41. NoEachEventForCreated bool
  42. LoginErrImg string
  43. }
  44. // 关闭浏览器 统一控制
  45. func (lr *Lxrod) CloseBrowser() (err error) {
  46. if lr.Browser != nil {
  47. return rod.Try(func() {
  48. if lr.Browser != nil {
  49. lr.Browser.Close()
  50. go rod.Try(func() {
  51. lr.Launcher.Cleanup()
  52. lr.Launcher.Kill()
  53. })
  54. }
  55. })
  56. }
  57. return nil
  58. }
  59. // 关闭浏览器 统一控制
  60. func (lr *Lxrod) CloseBrowserNew() {
  61. if lr.Browser != nil {
  62. _ = lr.Browser.Close()
  63. lr.Launcher.Cleanup()
  64. }
  65. }
  66. func GetAlertMsg() string {
  67. select {
  68. case v := <-LastAlertMsg:
  69. return v
  70. case <-time.After(time.Second * 8):
  71. return ""
  72. }
  73. }
  74. func ClickDialog(p *rod.Page, h func(bool, string)) { //默认添加点击alert事件
  75. go func() {
  76. defer func() {
  77. if err := recover(); err != nil {
  78. rod.Try(func() { h(true, "确定") })
  79. }
  80. }()
  81. h(true, "确定") //dialog 浏览器语言中文默认是确定 alert浏览器语言英文默认是ok
  82. }()
  83. }
  84. // 监听 alert confirm 等事件打开
  85. func DialogWatch(ctx context.Context, page *rod.Page) {
  86. defer func() {
  87. if r := recover(); r != nil {
  88. }
  89. }()
  90. _, h := page.MustHandleDialog()
  91. go page.EachEvent(func(e *proto.PageJavascriptDialogOpening) {
  92. defer func() {
  93. if r := recover(); r != nil {
  94. }
  95. }()
  96. if strings.Contains(page.MustInfo().URL, `henan`) {
  97. if strings.Contains(e.Message, `请重新登录`) || strings.Contains(e.Message, `访问异常`) {
  98. page.Browser().MustSetCookies()
  99. page.MustNavigate("")
  100. }
  101. }
  102. if strings.Contains(page.MustInfo().URL, `jiangxi`) {
  103. if strings.Contains(e.Message, "纳税人识别号未注册电子税务局") {
  104. //LastAlertMsgJiangXi <- e.Message
  105. }
  106. }
  107. LastAlertMsg <- e.Message
  108. ClickDialog(page, h)
  109. utils.Sleep(5)
  110. if len(LastAlertMsg) > 0 {
  111. _ = <-LastAlertMsg
  112. } else {
  113. }
  114. })()
  115. }
  116. // 新建浏览器对象-青岛
  117. func (lxrod *Lxrod) Newqd(ctx context.Context) (b *rod.Browser, p *rod.Page, err error) {
  118. rod.Try(func() {
  119. lxrod.CloseBrowser()
  120. })
  121. utils.Sleep(1)
  122. lxrod.Launcher = launcher.New()
  123. lxrod.Launcher.Set("window-size", "1600,900").
  124. Set("no-sandbox").
  125. Set("ignore-certificate-errors").
  126. Set("ignore-certificate-errors-spki-list").
  127. Set("ignore-ssl-errors").
  128. Set("disable-features", "CalculateNativeWinOcclusion").
  129. Headless(lxrod.Headless)
  130. //lxrod.Launcher.UserDataDir("user-data")
  131. //if viper.GetString("env") == string(variable.Development) {
  132. // lxrod.Launcher.Leakless(false) //开发环境不使用用leakless
  133. //}
  134. lxrod.Launcher.Flags["disable-blink-features"] = []string{"AutomationControlled"}
  135. u, err := lxrod.Launcher.Launch()
  136. if err != nil {
  137. err = taxerr.New("调用浏览器失败,请稍后重试!")
  138. return lxrod.Browser, p, taxerr.NewWebStuckTitle(true)
  139. }
  140. b = rod.New().ControlURL(u).MustConnect().Context(ctx).NoDefaultDevice() //.Trace(true) Trace调试打开
  141. utils.Sleep(1)
  142. b.MustSetCookies()
  143. p = b.MustPage("").MustSetWindow(0, 0, 1600, 900).MustSetViewport(1600, 900, 1, false)
  144. lxrod.Browser = b
  145. return lxrod.Browser, p, err
  146. }
  147. // 新建浏览器对象
  148. func (lxrod *Lxrod) New(ctx context.Context) (b *rod.Browser, p *rod.Page, err error) {
  149. rod.Try(func() {
  150. lxrod.CloseBrowser()
  151. })
  152. utils.Sleep(1)
  153. // if viper.GetString("env") == string(variable.Development) { //直接启动浏览器
  154. lxrod.Launcher = launcher.New()
  155. // } else { //容器内启动
  156. // serviceURL := os.Getenv("serviceURL")
  157. // lxrod.Launcher, err = launcher.NewManaged(serviceURL)
  158. // if err != nil {
  159. //
  160. // err = taxerr.New("调用浏览器失败,请稍后重试!")
  161. // return lxrod.Browser, p, err
  162. // }
  163. // lxrod.Launcher.XVFB("--server-num=5", "--server-args=-screen 0 1600x900x16")
  164. // }
  165. lxrod.Launcher.Set("window-size", "1600,900").
  166. Set("no-sandbox").
  167. Set("ignore-certificate-errors").
  168. Set("ignore-certificate-errors-spki-list").
  169. Set("ignore-ssl-errors").
  170. Set("disable-features", "CalculateNativeWinOcclusion").
  171. //UserDataDir("user-data").
  172. Headless(lxrod.Headless)
  173. //if lxrod.Area == "hebei" {
  174. // lxrod.Launcher.UserDataDir("user-data")
  175. //}
  176. //if lxrod.Area == "hebei" {
  177. lxrod.Launcher.Flags["disable-blink-features"] = []string{"AutomationControlled"}
  178. //}
  179. //if viper.GetString("env") == string(variable.Development) {
  180. // //lxrod.Launcher.Leakless(false) //开发环境不使用用leakless todo 进程老是结束不掉
  181. //}
  182. // Leakless(lxrod.Leakless)
  183. // chromePath, ok := launcher.LookPath()
  184. // fmt.Println(ok)
  185. // fmt.Println(chromePath)
  186. // if ok {
  187. // lxrod.Launcher.Bin(chromePath)
  188. // }
  189. if lxrod.UseProxy {
  190. lxrod.Proxy, lxrod.ProxyAuth = GetLocalProxy(string(lxrod.Area))
  191. lxrod.Launcher.Proxy(lxrod.Proxy)
  192. }
  193. u, err := lxrod.Launcher.Launch()
  194. lxrod.WsURL = u
  195. if err != nil {
  196. err = taxerr.New("调用浏览器失败,请稍后重试!")
  197. return lxrod.Browser, p, taxerr.NewWebStuckTitle(true)
  198. }
  199. // lxrod.Browser = rod.New().Client(lxrod.Launcher.MustClient()).MustConnect().Context(ctx).MustSetCookies() //.Trace(true) Trace调试打开
  200. lxrod.Browser = rod.New().ControlURL(u).MustConnect().Context(ctx) //.Trace(true) Trace调试打开
  201. utils.Sleep(1)
  202. lxrod.Browser.MustSetCookies()
  203. if lxrod.NoDefaultDevice {
  204. lxrod.Browser.NoDefaultDevice()
  205. }
  206. if !lxrod.NoByPass {
  207. //是否需要反反爬虫
  208. p = stealth.MustPage(lxrod.Browser)
  209. } else {
  210. p, err = lxrod.Browser.Page(proto.TargetCreateTarget{})
  211. if err != nil {
  212. return lxrod.Browser, p, taxerr.NewWebStuckTitle(true)
  213. }
  214. }
  215. // launcher.Open(lxrod.Browser.ServeMonitor(""))
  216. p.MustSetWindow(0, 0, 1600, 900).MustSetViewport(1600, 900, 1, false)
  217. if lxrod.MonitorDialog {
  218. DialogWatch(ctx, p) //为新打开的页面添加一个dialog监控
  219. }
  220. if !lxrod.PageEvent {
  221. lxrod.EachPageCreatedEvent(ctx, lxrod.Browser)
  222. }
  223. return lxrod.Browser, p, err
  224. }
  225. func (lxrod *Lxrod) NewSd(ctx context.Context) (b *rod.Browser, p *rod.Page, err error) {
  226. rod.Try(func() {
  227. lxrod.CloseBrowser()
  228. })
  229. utils.Sleep(1)
  230. // if viper.GetString("env") == string(variable.Development) { //直接启动浏览器
  231. lxrod.Launcher = launcher.New()
  232. // } else { //容器内启动
  233. // serviceURL := os.Getenv("serviceURL")
  234. // lxrod.Launcher, err = launcher.NewManaged(serviceURL)
  235. // if err != nil {
  236. //
  237. // err = taxerr.New("调用浏览器失败,请稍后重试!")
  238. // return lxrod.Browser, p, err
  239. // }
  240. // lxrod.Launcher.XVFB("--server-num=5", "--server-args=-screen 0 1600x900x16")
  241. // }
  242. lxrod.Launcher.Set("window-size", "1600,900").
  243. Set("no-sandbox").
  244. Set("ignore-certificate-errors").
  245. Set("ignore-certificate-errors-spki-list").
  246. Set("ignore-ssl-errors").
  247. Set("disable-features", "CalculateNativeWinOcclusion").
  248. //UserDataDir("user-data").
  249. Headless(lxrod.Headless)
  250. //if viper.GetString("env") == string(variable.Development) {
  251. // lxrod.Launcher.Leakless(false) //开发环境不使用用leakless
  252. //}
  253. // Leakless(lxrod.Leakless)
  254. // chromePath, ok := launcher.LookPath()
  255. // fmt.Println(ok)
  256. // fmt.Println(chromePath)
  257. // if ok {
  258. // lxrod.Launcher.Bin(chromePath)
  259. // }
  260. if lxrod.UseProxy {
  261. lxrod.Proxy, lxrod.ProxyAuth = GetLocalProxy(string(lxrod.Area))
  262. lxrod.Launcher.Proxy(lxrod.Proxy)
  263. }
  264. u, err := lxrod.Launcher.Launch()
  265. if err != nil {
  266. err = taxerr.New("调用浏览器失败,请稍后重试!")
  267. return lxrod.Browser, p, taxerr.NewWebStuckTitle(true)
  268. }
  269. // lxrod.Browser = rod.New().Client(lxrod.Launcher.MustClient()).MustConnect().Context(ctx).MustSetCookies() //.Trace(true) Trace调试打开
  270. lxrod.Browser = rod.New().ControlURL(u).MustConnect().Context(ctx) //.Trace(true) Trace调试打开
  271. utils.Sleep(1)
  272. lxrod.Browser.MustSetCookies()
  273. if lxrod.NoDefaultDevice {
  274. lxrod.Browser.NoDefaultDevice()
  275. }
  276. if !lxrod.NoByPass {
  277. //是否需要反反爬虫
  278. p = stealth.MustPage(lxrod.Browser)
  279. } else {
  280. p, err = lxrod.Browser.Page(proto.TargetCreateTarget{})
  281. if err != nil {
  282. return lxrod.Browser, p, taxerr.NewWebStuckTitle(true)
  283. }
  284. }
  285. // launcher.Open(lxrod.Browser.ServeMonitor(""))
  286. p.MustSetWindow(0, 0, 1600, 900).MustSetViewport(1600, 900, 1, false)
  287. if lxrod.MonitorDialog {
  288. DialogWatch(ctx, p) //为新打开的页面添加一个dialog监控
  289. }
  290. lxrod.EachPageCreatedEvent(ctx, lxrod.Browser)
  291. return lxrod.Browser, p, err
  292. }
  293. // 新建浏览器对象 易代账移除EachPageCreatedEvent否则新标签页打不开 by fengxianwei
  294. func (lxrod *Lxrod) NewByydz(ctx context.Context) (b *rod.Browser, p *rod.Page, err error) {
  295. rod.Try(func() {
  296. lxrod.CloseBrowser()
  297. })
  298. utils.Sleep(1)
  299. // if viper.GetString("env") == string(variable.Development) { //直接启动浏览器
  300. lxrod.Launcher = launcher.New()
  301. // } else { //容器内启动
  302. // serviceURL := os.Getenv("serviceURL")
  303. // lxrod.Launcher, err = launcher.NewManaged(serviceURL)
  304. // if err != nil {
  305. //
  306. // err = taxerr.New("调用浏览器失败,请稍后重试!")
  307. // return lxrod.Browser, p, err
  308. // }
  309. // lxrod.Launcher.XVFB("--server-num=5", "--server-args=-screen 0 1600x900x16")
  310. // }
  311. lxrod.Launcher.Set("window-size", "1600,900").
  312. Set("no-sandbox").
  313. Set("ignore-certificate-errors").
  314. Set("ignore-certificate-errors-spki-list").
  315. Set("ignore-ssl-errors").
  316. Set("disable-features", "CalculateNativeWinOcclusion").
  317. //UserDataDir("user-data").
  318. Headless(lxrod.Headless)
  319. //if viper.GetString("env") == string(variable.Development) {
  320. // lxrod.Launcher.Leakless(false) //开发环境不使用用leakless
  321. //}
  322. if lxrod.UseProxy {
  323. lxrod.Proxy, lxrod.ProxyAuth = GetLocalProxy(string(lxrod.Area))
  324. lxrod.Launcher.Proxy(lxrod.Proxy)
  325. }
  326. u, err := lxrod.Launcher.Launch()
  327. if err != nil {
  328. err = taxerr.New("调用浏览器失败,请稍后重试!")
  329. return lxrod.Browser, p, taxerr.NewWebStuckTitle(true)
  330. }
  331. lxrod.Browser = rod.New().ControlURL(u).MustConnect().Context(ctx) //.Trace(true) Trace调试打开
  332. utils.Sleep(1)
  333. lxrod.Browser.MustSetCookies()
  334. if lxrod.NoDefaultDevice {
  335. lxrod.Browser.NoDefaultDevice()
  336. }
  337. if !lxrod.NoByPass {
  338. //是否需要反反爬虫
  339. p = stealth.MustPage(lxrod.Browser)
  340. } else {
  341. p, err = lxrod.Browser.Page(proto.TargetCreateTarget{})
  342. if err != nil {
  343. return lxrod.Browser, p, taxerr.NewWebStuckTitle(true)
  344. }
  345. }
  346. p.MustSetWindow(0, 0, 1600, 900).MustSetViewport(1600, 900, 1, false)
  347. if lxrod.MonitorDialog {
  348. DialogWatch(ctx, p) //为新打开的页面添加一个dialog监控
  349. }
  350. return lxrod.Browser, p, err
  351. }
  352. // 跳过反爬虫检查
  353. func (lxrod *Lxrod) EachPageCreatedEvent(ctx context.Context, browser *rod.Browser) {
  354. if !lxrod.MonitorDialog && lxrod.NoByPass {
  355. return
  356. }
  357. go browser.EachEvent(func(e *proto.TargetTargetCreated) {
  358. defer func() {
  359. if r := recover(); r != nil {
  360. }
  361. }()
  362. if e.TargetInfo.Type != proto.TargetTargetInfoTypePage {
  363. return
  364. }
  365. page := browser.MustPageFromTargetID(e.TargetInfo.TargetID)
  366. if !lxrod.NoByPass {
  367. _, err := page.EvalOnNewDocument(stealth.JS)
  368. if err != nil {
  369. return
  370. }
  371. page.MustEvalOnNewDocument(stealth.JS)
  372. page.MustSetUserAgent(nil)
  373. utils.E(proto.RuntimeRunIfWaitingForDebugger{}.Call(page))
  374. }
  375. page.MustSetWindow(0, 0, 1600, 900).MustSetViewport(1600, 900, 1, false)
  376. if lxrod.MonitorDialog {
  377. DialogWatch(ctx, page) //为新打开的页面添加一个dialog监控
  378. }
  379. })()
  380. utils.E(proto.TargetSetAutoAttach{
  381. AutoAttach: true,
  382. WaitForDebuggerOnStart: true,
  383. Flatten: true,
  384. }.Call(browser))
  385. }
  386. func PageToClient(page *rod.Page, BaseURL string) (*http.Client, error) {
  387. c := lxhttp.NewHttpClient()
  388. e := rod.Try(func() {
  389. cookies := page.MustCookies()
  390. var cookiesArr []*http.Cookie
  391. for _, v := range cookies {
  392. var cookie http.Cookie
  393. cookie.Name = v.Name
  394. cookie.Value = v.Value
  395. cookiesArr = append(cookiesArr, &cookie)
  396. }
  397. clientURL, _ := url.Parse(BaseURL)
  398. c.Jar.SetCookies(clientURL, cookiesArr)
  399. })
  400. return c, e
  401. }
  402. func BrowserToClient(b *rod.Browser, BaseURL string) (*http.Client, error) {
  403. domainMap := map[string][]*http.Cookie{}
  404. c := lxhttp.NewHttpClient()
  405. e := rod.Try(func() {
  406. cookies := b.MustGetCookies()
  407. for _, v := range cookies {
  408. var cookie http.Cookie
  409. cookie.Name = v.Name
  410. cookie.Value = v.Value
  411. cookie.Path = v.Path
  412. cookie.Domain = v.Domain
  413. domainMap[v.Domain] = append(domainMap[v.Domain], &cookie)
  414. }
  415. for _, cookie := range domainMap {
  416. clientURL, _ := url.Parse(BaseURL)
  417. c.Jar.SetCookies(clientURL, cookie)
  418. }
  419. })
  420. return c, e
  421. }
  422. func BrowserToClientYunnan(b *rod.Browser, BaseURL string) (*http.Client, error) {
  423. domainMap := map[string][]*http.Cookie{}
  424. c := lxhttp.NewHttpClient()
  425. e := rod.Try(func() {
  426. cookies := b.MustGetCookies()
  427. for _, v := range cookies {
  428. var cookie http.Cookie
  429. cookie.Name = v.Name
  430. cookie.Value = v.Value
  431. cookie.Path = v.Path
  432. cookie.Domain = v.Domain
  433. domainMap[v.Domain] = append(domainMap[v.Domain], &cookie)
  434. }
  435. for _, cookie := range domainMap {
  436. clientURL, _ := url.Parse(BaseURL)
  437. c.Jar.SetCookies(clientURL, cookie)
  438. }
  439. u, auth := GetLocalProxy("yunnan")
  440. uu, _ := url.Parse(u)
  441. c.Transport = &http.Transport{Proxy: http.ProxyURL(uu), ProxyConnectHeader: http.Header{
  442. "Proxy-Authorization": []string{"Basic " + base64.StdEncoding.EncodeToString([]byte(auth))},
  443. }}
  444. })
  445. return c, e
  446. }
  447. func BrowserToClientByProxy(b *rod.Browser, BaseURL string) (*http.Client, error) {
  448. area := ""
  449. {
  450. u, _ := url.Parse(BaseURL)
  451. area = strings.Split(u.Host, ".")[1]
  452. }
  453. if area == "" {
  454. return lxhttp.NewHttpClient(), taxerr.TimeOut
  455. }
  456. domainMap := map[string][]*http.Cookie{}
  457. c := lxhttp.NewHttpClient()
  458. proxy, auth := GetLocalProxy(area)
  459. uu, _ := url.Parse(proxy)
  460. tr := &http.Transport{Proxy: http.ProxyURL(uu)}
  461. if auth != "" {
  462. tr.ProxyConnectHeader = http.Header{
  463. "Proxy-Authorization": []string{"Basic " + base64.StdEncoding.EncodeToString([]byte(auth))},
  464. }
  465. }
  466. c.Transport = tr
  467. e := rod.Try(func() {
  468. cookies := b.MustGetCookies()
  469. for _, v := range cookies {
  470. var cookie http.Cookie
  471. cookie.Name = v.Name
  472. cookie.Value = v.Value
  473. cookie.Path = v.Path
  474. cookie.Domain = v.Domain
  475. domainMap[v.Domain] = append(domainMap[v.Domain], &cookie)
  476. }
  477. for _, cookie := range domainMap {
  478. clientURL, _ := url.Parse(BaseURL)
  479. c.Jar.SetCookies(clientURL, cookie)
  480. }
  481. })
  482. return c, e
  483. }
  484. func (lxrod *Lxrod) NewByHjj(ctx context.Context) (b *rod.Browser, p *rod.Page, err error) {
  485. _ = rod.Try(func() {
  486. _ = lxrod.CloseBrowser()
  487. })
  488. lxrod.Launcher = launcher.New()
  489. lxrod.Launcher.Set("window-size", "1600,900").
  490. Set("no-sandbox").
  491. Set("ignore-certificate-errors").
  492. Set("ignore-certificate-errors-spki-list").
  493. Set("ignore-ssl-errors").
  494. Set("disable-features", "CalculateNativeWinOcclusion").
  495. Headless(lxrod.Headless)
  496. //lxrod.Launcher.UserDataDir("user-data")
  497. lxrod.Launcher.Flags["disable-blink-features"] = []string{"AutomationControlled"}
  498. u, err := lxrod.Launcher.Launch()
  499. if err != nil {
  500. err = taxerr.New("调用浏览器失败,请稍后重试!")
  501. return lxrod.Browser, p, err
  502. }
  503. err = rod.Try(func() {
  504. lxrod.Browser = rod.New().ControlURL(u).MustConnect().Context(ctx)
  505. utils.Sleep(1)
  506. lxrod.Browser.MustSetCookies()
  507. })
  508. if err != nil {
  509. return nil, nil, taxerr.NewWebStuckTitle(true)
  510. }
  511. lxrod.Browser.NoDefaultDevice()
  512. p = stealth.MustPage(lxrod.Browser)
  513. if lxrod.MonitorDialog {
  514. //为新打开的页面添加一个dialog监控
  515. DialogWatch(ctx, p)
  516. go lxrod.Browser.EachEvent(func(e *proto.TargetTargetCreated) {
  517. defer func() {
  518. if r := recover(); r != nil {
  519. }
  520. }()
  521. if e.TargetInfo.Type != proto.TargetTargetInfoTypePage {
  522. return
  523. }
  524. page := lxrod.Browser.MustPageFromTargetID(e.TargetInfo.TargetID)
  525. DialogWatch(ctx, page)
  526. })()
  527. }
  528. p = p.MustSetWindow(0, 0, 1600, 900).MustSetViewport(1600, 900, 1, false)
  529. return lxrod.Browser, p, err
  530. }
  531. // 新建浏览器对象
  532. func (lxrod *Lxrod) NewBeijing(ctx context.Context) (b *rod.Browser, p *rod.Page, err error) {
  533. rod.Try(func() {
  534. lxrod.CloseBrowser()
  535. os.RemoveAll("tmp/")
  536. })
  537. lxrod.Launcher = launcher.NewUserMode()
  538. u, err := lxrod.Launcher.
  539. // New().
  540. Leakless(true).
  541. UserDataDir("tmp/t").
  542. Set("disable-default-apps").
  543. Set("no-first-run").
  544. //Set("disable-plugins").
  545. Set("disable-popup-blocking").
  546. Set("disable-features", "CalculateNativeWinOcclusion").
  547. Headless(lxrod.Headless).
  548. Launch()
  549. if err != nil {
  550. return nil, nil, taxerr.NewUser("浏览器创建失败请稍后重试1")
  551. }
  552. utils.Sleep(3)
  553. err = rod.Try(func() {
  554. b = rod.New().ControlURL(u).Timeout(time.Second * 60).MustConnect().Context(ctx).NoDefaultDevice()
  555. })
  556. if err != nil {
  557. return nil, nil, taxerr.NewUser("浏览器创建失败请稍后重试2")
  558. }
  559. b.MustIncognito()
  560. p = b.MustPage("")
  561. lxrod.Browser = b
  562. go b.EachEvent(func(e *proto.TargetTargetCreated) {
  563. defer func() {
  564. if r := recover(); r != nil {
  565. }
  566. }()
  567. if e.TargetInfo.Type != proto.TargetTargetInfoTypePage {
  568. return
  569. }
  570. page := b.MustPageFromTargetID(e.TargetInfo.TargetID)
  571. page.MustSetWindow(0, 0, 1600, 900).MustSetViewport(1600, 900, 1, false)
  572. })()
  573. return b, p, err
  574. }
  575. func (lxrod *Lxrod) NewHuBei(ctx context.Context) (b *rod.Browser, p *rod.Page, err error) {
  576. rod.Try(func() {
  577. lxrod.CloseBrowser()
  578. })
  579. l := launcher.
  580. New().
  581. Set("window-size", "1600,900").
  582. Leakless(true).
  583. Set("disable-features", "CalculateNativeWinOcclusion").
  584. Headless(false)
  585. lxrod.Launcher = l
  586. //lxrod.Launcher.UserDataDir("user-data")
  587. l.Flags["disable-blink-features"] = []string{"AutomationControlled"}
  588. //if viper.GetString("env") == string(variable.Development) {
  589. // l.Leakless(false) //开发环境不使用用leakless
  590. //}
  591. u := l.MustLaunch()
  592. b = rod.New().ControlURL(u).MustConnect().NoDefaultDevice()
  593. p = stealth.MustPage(b)
  594. lxrod.Browser = b
  595. go b.EachEvent(func(e *proto.TargetTargetCreated) {
  596. defer func() {
  597. if r := recover(); r != nil {
  598. }
  599. }()
  600. if e.TargetInfo.Type != proto.TargetTargetInfoTypePage {
  601. return
  602. }
  603. page := b.MustPageFromTargetID(e.TargetInfo.TargetID)
  604. _, err := page.EvalOnNewDocument(stealth.JS)
  605. if err != nil {
  606. return
  607. }
  608. page.MustEvalOnNewDocument(stealth.JS)
  609. page.MustSetUserAgent(nil)
  610. utils.E(proto.RuntimeRunIfWaitingForDebugger{}.Call(page))
  611. page.MustSetWindow(0, 0, 1600, 900).MustSetViewport(1600, 900, 1, false)
  612. })()
  613. utils.E(proto.TargetSetAutoAttach{
  614. AutoAttach: true,
  615. WaitForDebuggerOnStart: true,
  616. Flatten: true,
  617. }.Call(b))
  618. return b, p, err
  619. }
  620. func (lxrod *Lxrod) NewNoParam() (b *rod.Browser, p *rod.Page, err error) {
  621. rod.Try(func() {
  622. lxrod.CloseBrowser()
  623. })
  624. l := launcher.
  625. New().
  626. Set("window-size", "1600,900").
  627. Leakless(true).
  628. Set("disable-features", "CalculateNativeWinOcclusion").
  629. Headless(false)
  630. lxrod.Launcher = l
  631. //lxrod.Launcher.UserDataDir("user-data")
  632. l.Flags["disable-blink-features"] = []string{"AutomationControlled"}
  633. //if viper.GetString("env") == string(variable.Development) {
  634. // l.Leakless(false) //开发环境不使用用leakless
  635. //}
  636. u := l.MustLaunch()
  637. b = rod.New().ControlURL(u).MustConnect().NoDefaultDevice()
  638. p = stealth.MustPage(b)
  639. lxrod.Browser = b
  640. go b.EachEvent(func(e *proto.TargetTargetCreated) {
  641. defer func() {
  642. if r := recover(); r != nil {
  643. }
  644. }()
  645. if e.TargetInfo.Type != proto.TargetTargetInfoTypePage {
  646. return
  647. }
  648. page := b.MustPageFromTargetID(e.TargetInfo.TargetID)
  649. _, err := page.EvalOnNewDocument(stealth.JS)
  650. if err != nil {
  651. return
  652. }
  653. page.MustEvalOnNewDocument(stealth.JS)
  654. page.MustSetUserAgent(nil)
  655. utils.E(proto.RuntimeRunIfWaitingForDebugger{}.Call(page))
  656. page.MustSetWindow(0, 0, 1600, 900).MustSetViewport(1600, 900, 1, false)
  657. })()
  658. utils.E(proto.TargetSetAutoAttach{
  659. AutoAttach: true,
  660. WaitForDebuggerOnStart: true,
  661. Flatten: true,
  662. }.Call(b))
  663. return b, p, err
  664. }
  665. // 最简单的浏览器创建
  666. func (lxrod *Lxrod) NewLowBrowser(ctx context.Context) (b *rod.Browser, p *rod.Page, err error) {
  667. rod.Try(func() {
  668. if lxrod.Browser != nil {
  669. lxrod.CloseBrowser()
  670. utils.Sleep(5)
  671. }
  672. })
  673. l := launcher.New().
  674. Headless(false).
  675. Set("high-dpi-support", "1").
  676. Set("disable-features", "CalculateNativeWinOcclusion").
  677. Set("force-device-scale-factor", "1")
  678. l.Flags["disable-blink-features"] = []string{"AutomationControlled"}
  679. lxrod.Launcher = l
  680. //lxrod.Launcher.UserDataDir("user-data")
  681. //if lxrod.Area == "hebei" {
  682. // lxrod.Launcher.UserDataDir("user-data")
  683. //}
  684. if lxrod.UseProxy {
  685. lxrod.Proxy, lxrod.ProxyAuth = GetLocalProxy(string(lxrod.Area))
  686. lxrod.Launcher.Proxy(lxrod.Proxy)
  687. }
  688. wsURL, err := l.Launch()
  689. lxrod.WsURL = wsURL
  690. if err != nil {
  691. return nil, nil, taxerr.NewWebStuckTitle(true)
  692. }
  693. b = rod.New().ControlURL(wsURL).Context(ctx).MustConnect()
  694. utils.Sleep(1)
  695. b = b.MustSetCookies()
  696. if lxrod.UseProxy && lxrod.ProxyAuth != "" {
  697. auths := strings.Split(lxrod.ProxyAuth, ":")
  698. go b.HandleAuth(auths[0], auths[1])()
  699. }
  700. p = b.MustPage().MustSetWindow(0, 0, 1600, 900).MustSetViewport(1600, 900, 1, false)
  701. if lxrod.MonitorDialog && lxrod.NoEachEventForCreated {
  702. //为新打开的页面添加一个dialog监控
  703. DialogWatch(ctx, p)
  704. go b.EachEvent(func(e *proto.TargetTargetCreated) {
  705. defer func() {
  706. if r := recover(); r != nil {
  707. }
  708. }()
  709. if e.TargetInfo.Type != proto.TargetTargetInfoTypePage {
  710. return
  711. }
  712. page := b.MustPageFromTargetID(e.TargetInfo.TargetID)
  713. DialogWatch(ctx, page)
  714. })()
  715. }
  716. lxrod.Browser = b
  717. return b, p, nil
  718. }
  719. // NewBrowserBank360 打开 360 急速浏览器。适用于既要 ocx 密码输入又要 chrome 采集的银行任务,
  720. // 如承德银行。运行前需要先安装 360 急速浏览器,然后将 360 急速浏览器的安装目录添加到环境变量中。
  721. // 对于银行采集服务器,这个目录一般是:
  722. //
  723. // "C:\\Users\\taxrobot\\Desktop\\360Chrome1\\"
  724. func (lxrod *Lxrod) NewBrowserBank360(ctx context.Context) (b *rod.Browser, p *rod.Page, err error) {
  725. rod.Try(func() {
  726. lxrod.CloseBrowser()
  727. })
  728. bin, err := exec.LookPath("360chromeX.exe")
  729. if err != nil {
  730. return nil, nil, taxerr.NewUser("请先安装360极速浏览器(" + err.Error() + ")")
  731. }
  732. l := launcher.New().
  733. Headless(false).
  734. Bin(bin).
  735. //Bin("C:\\Program Files (x86)\\税局小助手\\360Chrome\\360chromeX.exe").
  736. Set("high-dpi-support", "1").
  737. Set("disable-features", "CalculateNativeWinOcclusion").
  738. Set("force-device-scale-factor", "1")
  739. l.Flags["disable-blink-features"] = []string{"AutomationControlled"}
  740. lxrod.Launcher = l
  741. wsURL, err := l.Launch()
  742. lxrod.WsURL = wsURL
  743. if err != nil {
  744. return nil, nil, taxerr.NewWebStuckTitle(true)
  745. }
  746. b = rod.New().ControlURL(wsURL).Context(ctx).MustConnect()
  747. p = b.MustPage().MustSetWindow(0, 0, 1600, 900).MustSetViewport(1600, 900, 1, false)
  748. if lxrod.MonitorDialog {
  749. //为新打开的页面添加一个dialog监控
  750. DialogWatch(ctx, p)
  751. go b.EachEvent(func(e *proto.TargetTargetCreated) {
  752. defer func() {
  753. if r := recover(); r != nil {
  754. }
  755. }()
  756. if e.TargetInfo.Type != proto.TargetTargetInfoTypePage {
  757. return
  758. }
  759. page := b.MustPageFromTargetID(e.TargetInfo.TargetID)
  760. DialogWatch(ctx, page)
  761. })()
  762. }
  763. lxrod.Browser = b
  764. return b, p, nil
  765. }
  766. // 最简单的浏览器创建2
  767. func (lxrod *Lxrod) NewLowBrowser2(ctx context.Context) (b *rod.Browser, p *rod.Page, err error) {
  768. rod.Try(func() {
  769. lxrod.CloseBrowser()
  770. })
  771. l := launcher.New().
  772. Headless(false).
  773. Set("high-dpi-support", "1").
  774. Set("disable-features", "CalculateNativeWinOcclusion").
  775. Set("force-device-scale-factor", "1")
  776. l.Flags["disable-blink-features"] = []string{"AutomationControlled"}
  777. lxrod.Launcher = l
  778. //lxrod.Launcher.UserDataDir("user-data")
  779. wsURL, err := l.Launch()
  780. if err != nil {
  781. return nil, nil, taxerr.NewWebStuckTitle(true)
  782. }
  783. b = rod.New().ControlURL(wsURL).Context(ctx).MustConnect()
  784. p = b.MustPage().MustSetWindow(0, 0, 1600, 900).MustSetViewport(1600, 900, 1, false)
  785. lxrod.Browser = b
  786. if lxrod.MonitorDialog {
  787. DialogWatch(ctx, p) //为新打开的页面添加一个dialog监控
  788. }
  789. if lxrod.UseProxy {
  790. lxrod.Proxy, lxrod.ProxyAuth = GetLocalProxy(string(lxrod.Area))
  791. lxrod.Launcher.Proxy(lxrod.Proxy)
  792. }
  793. return b, p, nil
  794. }
  795. // 自定义鼠标操作 方便升降版本
  796. type Mouse struct {
  797. Mouse *rod.Mouse
  798. }
  799. func (m *Mouse) MustMove(x, y float64) *Mouse {
  800. m.Mouse.MustMoveTo(x, y)
  801. return m
  802. }
  803. func (m *Mouse) MustDown(button proto.InputMouseButton) *Mouse {
  804. m.Mouse.MustDown(button)
  805. return m
  806. }
  807. func (m *Mouse) MustUp(button proto.InputMouseButton) *Mouse {
  808. m.Mouse.MustUp(button)
  809. return m
  810. }
  811. func (m *Mouse) MustClick(button proto.InputMouseButton) *Mouse {
  812. m.Mouse.MustClick(button)
  813. return m
  814. }
  815. func ShenzhenProxy() string {
  816. // 获取私密代理IP API
  817. api := "https://dps.kdlapi.com/api/getdps"
  818. // 请求参数
  819. params := url.Values{}
  820. params.Set("secret_id", "odr5kxfzzky69wbtuhzh")
  821. params.Set("signature", "qwndesfg2ouix111a8rfzyixou7q9nr3")
  822. params.Set("num", strconv.Itoa(1)) // 提取数量
  823. // 构建完整的URL,包括参数
  824. fullURL := api + "?" + params.Encode()
  825. // 发送GET请求
  826. response, err := http.Get(fullURL)
  827. if err != nil {
  828. fmt.Println("Error:", err)
  829. return ""
  830. }
  831. defer response.Body.Close()
  832. // 读取响应内容
  833. body, err := io.ReadAll(response.Body)
  834. if err != nil {
  835. fmt.Println("Error reading response body:", err)
  836. return ""
  837. }
  838. // 输出响应结果
  839. return "http://" + string(body)
  840. }
  841. // 备用
  842. func (lxrod *Lxrod) BeijingNew(ctx context.Context) (b *rod.Browser, p *rod.Page, err error) {
  843. _ = rod.Try(func() {
  844. lxrod.CloseBrowser()
  845. })
  846. l := launcher.New().Set("window-size", "1600,900").
  847. Delete("enable-automation").
  848. Leakless(true).
  849. Headless(false).Set("disable-features", "CalculateNativeWinOcclusion")
  850. l.Flags["disable-blink-features"] = []string{"AutomationControlled"}
  851. u := l.MustLaunch()
  852. b = rod.New().ControlURL(u).MustConnect()
  853. p = b.MustPage("")
  854. lxrod.Browser = b
  855. return b, p, nil
  856. }
  857. // GetLocalProxy 获取所有地区代理 部分地区是使用的我们自己的代理池
  858. func GetLocalProxy(Area string) (string, string) {
  859. // 都换成5879
  860. if Area == "xizang" /*|| Area == "yunnan"*/ || Area == "hebei" || Area == "liaoning" || Area == "chongqing" || Area == "sichuan" {
  861. return `http://8.141.85.129:5879`, "lxuser:Aa123456"
  862. }
  863. if Area == "yunnan" {
  864. return "http://106.58.178.172:27237", "13280888700:nPDZ0RYX"
  865. }
  866. if Area == "shenzhen" {
  867. return ShenzhenProxy(), "d2879234360:ikdnhzbk"
  868. }
  869. return `http://8.141.85.129:5879`, "lxuser:Aa123456"
  870. }