package lxrod import ( "context" "encoding/base64" "fmt" "git.listensoft.net/tool/jspkit/common/lxhttp" "git.listensoft.net/tool/jspkit/common/variable" "git.listensoft.net/tool/jspkit/taxerr" "github.com/go-rod/stealth" "io" "net/http" "net/url" "os" "os/exec" "strconv" "strings" "time" "github.com/go-rod/rod" "github.com/go-rod/rod/lib/launcher" "github.com/go-rod/rod/lib/proto" "github.com/go-rod/rod/lib/utils" ) var ( LastAlertMsg = make(chan string, 100) ) // 只允许task.go 初始化一次 type Lxrod struct { Area variable.Area Browser *rod.Browser Launcher *launcher.Launcher NoByPass bool //添加反反爬虫代码 原理就是执行一段js去掉window属性中关于自动化的代码 Headless bool //headless 默认显示浏览器 为true是不显示浏览器 MonitorDialog bool //默认监控alert然后去点击true 如果要自己处理 设置为true不添加监控 PageEvent bool //默认每个页面的监听事件 设置为true不添加监控 UseProxy bool //代理 Leakless bool NoDefaultDevice bool Proxy string ProxyAuth string WsURL string // rod的ws地址 NoEachEventForCreated bool LoginErrImg string } // 关闭浏览器 统一控制 func (lr *Lxrod) CloseBrowser() (err error) { if lr.Browser != nil { return rod.Try(func() { if lr.Browser != nil { lr.Browser.Close() go rod.Try(func() { lr.Launcher.Cleanup() lr.Launcher.Kill() }) } }) } return nil } // 关闭浏览器 统一控制 func (lr *Lxrod) CloseBrowserNew() { if lr.Browser != nil { _ = lr.Browser.Close() lr.Launcher.Cleanup() } } func GetAlertMsg() string { select { case v := <-LastAlertMsg: return v case <-time.After(time.Second * 8): return "" } } func ClickDialog(p *rod.Page, h func(bool, string)) { //默认添加点击alert事件 go func() { defer func() { if err := recover(); err != nil { rod.Try(func() { h(true, "确定") }) } }() h(true, "确定") //dialog 浏览器语言中文默认是确定 alert浏览器语言英文默认是ok }() } // 监听 alert confirm 等事件打开 func DialogWatch(ctx context.Context, page *rod.Page) { defer func() { if r := recover(); r != nil { } }() _, h := page.MustHandleDialog() go page.EachEvent(func(e *proto.PageJavascriptDialogOpening) { defer func() { if r := recover(); r != nil { } }() if strings.Contains(page.MustInfo().URL, `henan`) { if strings.Contains(e.Message, `请重新登录`) || strings.Contains(e.Message, `访问异常`) { page.Browser().MustSetCookies() page.MustNavigate("") } } if strings.Contains(page.MustInfo().URL, `jiangxi`) { if strings.Contains(e.Message, "纳税人识别号未注册电子税务局") { //LastAlertMsgJiangXi <- e.Message } } LastAlertMsg <- e.Message ClickDialog(page, h) utils.Sleep(5) if len(LastAlertMsg) > 0 { _ = <-LastAlertMsg } else { } })() } // 新建浏览器对象-青岛 func (lxrod *Lxrod) Newqd(ctx context.Context) (b *rod.Browser, p *rod.Page, err error) { rod.Try(func() { lxrod.CloseBrowser() }) utils.Sleep(1) lxrod.Launcher = launcher.New() lxrod.Launcher.Set("window-size", "1600,900"). Set("no-sandbox"). Set("ignore-certificate-errors"). Set("ignore-certificate-errors-spki-list"). Set("ignore-ssl-errors"). Set("disable-features", "CalculateNativeWinOcclusion"). Headless(lxrod.Headless) //lxrod.Launcher.UserDataDir("user-data") //if viper.GetString("env") == string(variable.Development) { // lxrod.Launcher.Leakless(false) //开发环境不使用用leakless //} lxrod.Launcher.Flags["disable-blink-features"] = []string{"AutomationControlled"} u, err := lxrod.Launcher.Launch() if err != nil { err = taxerr.New("调用浏览器失败,请稍后重试!") return lxrod.Browser, p, taxerr.NewWebStuckTitle(true) } b = rod.New().ControlURL(u).MustConnect().Context(ctx).NoDefaultDevice() //.Trace(true) Trace调试打开 utils.Sleep(1) b.MustSetCookies() p = b.MustPage("").MustSetWindow(0, 0, 1600, 900).MustSetViewport(1600, 900, 1, false) lxrod.Browser = b return lxrod.Browser, p, err } // 新建浏览器对象 func (lxrod *Lxrod) New(ctx context.Context) (b *rod.Browser, p *rod.Page, err error) { rod.Try(func() { lxrod.CloseBrowser() }) utils.Sleep(1) // if viper.GetString("env") == string(variable.Development) { //直接启动浏览器 lxrod.Launcher = launcher.New() // } else { //容器内启动 // serviceURL := os.Getenv("serviceURL") // lxrod.Launcher, err = launcher.NewManaged(serviceURL) // if err != nil { // // err = taxerr.New("调用浏览器失败,请稍后重试!") // return lxrod.Browser, p, err // } // lxrod.Launcher.XVFB("--server-num=5", "--server-args=-screen 0 1600x900x16") // } lxrod.Launcher.Set("window-size", "1600,900"). Set("no-sandbox"). Set("ignore-certificate-errors"). Set("ignore-certificate-errors-spki-list"). Set("ignore-ssl-errors"). Set("disable-features", "CalculateNativeWinOcclusion"). //UserDataDir("user-data"). Headless(lxrod.Headless) //if lxrod.Area == "hebei" { // lxrod.Launcher.UserDataDir("user-data") //} //if lxrod.Area == "hebei" { lxrod.Launcher.Flags["disable-blink-features"] = []string{"AutomationControlled"} //} //if viper.GetString("env") == string(variable.Development) { // //lxrod.Launcher.Leakless(false) //开发环境不使用用leakless todo 进程老是结束不掉 //} // Leakless(lxrod.Leakless) // chromePath, ok := launcher.LookPath() // fmt.Println(ok) // fmt.Println(chromePath) // if ok { // lxrod.Launcher.Bin(chromePath) // } if lxrod.UseProxy { lxrod.Proxy, lxrod.ProxyAuth = GetLocalProxy(string(lxrod.Area)) lxrod.Launcher.Proxy(lxrod.Proxy) } u, err := lxrod.Launcher.Launch() lxrod.WsURL = u if err != nil { err = taxerr.New("调用浏览器失败,请稍后重试!") return lxrod.Browser, p, taxerr.NewWebStuckTitle(true) } // lxrod.Browser = rod.New().Client(lxrod.Launcher.MustClient()).MustConnect().Context(ctx).MustSetCookies() //.Trace(true) Trace调试打开 lxrod.Browser = rod.New().ControlURL(u).MustConnect().Context(ctx) //.Trace(true) Trace调试打开 utils.Sleep(1) lxrod.Browser.MustSetCookies() if lxrod.NoDefaultDevice { lxrod.Browser.NoDefaultDevice() } if !lxrod.NoByPass { //是否需要反反爬虫 p = stealth.MustPage(lxrod.Browser) } else { p, err = lxrod.Browser.Page(proto.TargetCreateTarget{}) if err != nil { return lxrod.Browser, p, taxerr.NewWebStuckTitle(true) } } // launcher.Open(lxrod.Browser.ServeMonitor("")) p.MustSetWindow(0, 0, 1600, 900).MustSetViewport(1600, 900, 1, false) if lxrod.MonitorDialog { DialogWatch(ctx, p) //为新打开的页面添加一个dialog监控 } if !lxrod.PageEvent { lxrod.EachPageCreatedEvent(ctx, lxrod.Browser) } return lxrod.Browser, p, err } func (lxrod *Lxrod) NewSd(ctx context.Context) (b *rod.Browser, p *rod.Page, err error) { rod.Try(func() { lxrod.CloseBrowser() }) utils.Sleep(1) // if viper.GetString("env") == string(variable.Development) { //直接启动浏览器 lxrod.Launcher = launcher.New() // } else { //容器内启动 // serviceURL := os.Getenv("serviceURL") // lxrod.Launcher, err = launcher.NewManaged(serviceURL) // if err != nil { // // err = taxerr.New("调用浏览器失败,请稍后重试!") // return lxrod.Browser, p, err // } // lxrod.Launcher.XVFB("--server-num=5", "--server-args=-screen 0 1600x900x16") // } lxrod.Launcher.Set("window-size", "1600,900"). Set("no-sandbox"). Set("ignore-certificate-errors"). Set("ignore-certificate-errors-spki-list"). Set("ignore-ssl-errors"). Set("disable-features", "CalculateNativeWinOcclusion"). //UserDataDir("user-data"). Headless(lxrod.Headless) //if viper.GetString("env") == string(variable.Development) { // lxrod.Launcher.Leakless(false) //开发环境不使用用leakless //} // Leakless(lxrod.Leakless) // chromePath, ok := launcher.LookPath() // fmt.Println(ok) // fmt.Println(chromePath) // if ok { // lxrod.Launcher.Bin(chromePath) // } if lxrod.UseProxy { lxrod.Proxy, lxrod.ProxyAuth = GetLocalProxy(string(lxrod.Area)) lxrod.Launcher.Proxy(lxrod.Proxy) } u, err := lxrod.Launcher.Launch() if err != nil { err = taxerr.New("调用浏览器失败,请稍后重试!") return lxrod.Browser, p, taxerr.NewWebStuckTitle(true) } // lxrod.Browser = rod.New().Client(lxrod.Launcher.MustClient()).MustConnect().Context(ctx).MustSetCookies() //.Trace(true) Trace调试打开 lxrod.Browser = rod.New().ControlURL(u).MustConnect().Context(ctx) //.Trace(true) Trace调试打开 utils.Sleep(1) lxrod.Browser.MustSetCookies() if lxrod.NoDefaultDevice { lxrod.Browser.NoDefaultDevice() } if !lxrod.NoByPass { //是否需要反反爬虫 p = stealth.MustPage(lxrod.Browser) } else { p, err = lxrod.Browser.Page(proto.TargetCreateTarget{}) if err != nil { return lxrod.Browser, p, taxerr.NewWebStuckTitle(true) } } // launcher.Open(lxrod.Browser.ServeMonitor("")) p.MustSetWindow(0, 0, 1600, 900).MustSetViewport(1600, 900, 1, false) if lxrod.MonitorDialog { DialogWatch(ctx, p) //为新打开的页面添加一个dialog监控 } lxrod.EachPageCreatedEvent(ctx, lxrod.Browser) return lxrod.Browser, p, err } // 新建浏览器对象 易代账移除EachPageCreatedEvent否则新标签页打不开 by fengxianwei func (lxrod *Lxrod) NewByydz(ctx context.Context) (b *rod.Browser, p *rod.Page, err error) { rod.Try(func() { lxrod.CloseBrowser() }) utils.Sleep(1) // if viper.GetString("env") == string(variable.Development) { //直接启动浏览器 lxrod.Launcher = launcher.New() // } else { //容器内启动 // serviceURL := os.Getenv("serviceURL") // lxrod.Launcher, err = launcher.NewManaged(serviceURL) // if err != nil { // // err = taxerr.New("调用浏览器失败,请稍后重试!") // return lxrod.Browser, p, err // } // lxrod.Launcher.XVFB("--server-num=5", "--server-args=-screen 0 1600x900x16") // } lxrod.Launcher.Set("window-size", "1600,900"). Set("no-sandbox"). Set("ignore-certificate-errors"). Set("ignore-certificate-errors-spki-list"). Set("ignore-ssl-errors"). Set("disable-features", "CalculateNativeWinOcclusion"). //UserDataDir("user-data"). Headless(lxrod.Headless) //if viper.GetString("env") == string(variable.Development) { // lxrod.Launcher.Leakless(false) //开发环境不使用用leakless //} if lxrod.UseProxy { lxrod.Proxy, lxrod.ProxyAuth = GetLocalProxy(string(lxrod.Area)) lxrod.Launcher.Proxy(lxrod.Proxy) } u, err := lxrod.Launcher.Launch() if err != nil { err = taxerr.New("调用浏览器失败,请稍后重试!") return lxrod.Browser, p, taxerr.NewWebStuckTitle(true) } lxrod.Browser = rod.New().ControlURL(u).MustConnect().Context(ctx) //.Trace(true) Trace调试打开 utils.Sleep(1) lxrod.Browser.MustSetCookies() if lxrod.NoDefaultDevice { lxrod.Browser.NoDefaultDevice() } if !lxrod.NoByPass { //是否需要反反爬虫 p = stealth.MustPage(lxrod.Browser) } else { p, err = lxrod.Browser.Page(proto.TargetCreateTarget{}) if err != nil { return lxrod.Browser, p, taxerr.NewWebStuckTitle(true) } } p.MustSetWindow(0, 0, 1600, 900).MustSetViewport(1600, 900, 1, false) if lxrod.MonitorDialog { DialogWatch(ctx, p) //为新打开的页面添加一个dialog监控 } return lxrod.Browser, p, err } // 跳过反爬虫检查 func (lxrod *Lxrod) EachPageCreatedEvent(ctx context.Context, browser *rod.Browser) { if !lxrod.MonitorDialog && lxrod.NoByPass { return } go browser.EachEvent(func(e *proto.TargetTargetCreated) { defer func() { if r := recover(); r != nil { } }() if e.TargetInfo.Type != proto.TargetTargetInfoTypePage { return } page := browser.MustPageFromTargetID(e.TargetInfo.TargetID) if !lxrod.NoByPass { _, err := page.EvalOnNewDocument(stealth.JS) if err != nil { return } page.MustEvalOnNewDocument(stealth.JS) page.MustSetUserAgent(nil) utils.E(proto.RuntimeRunIfWaitingForDebugger{}.Call(page)) } page.MustSetWindow(0, 0, 1600, 900).MustSetViewport(1600, 900, 1, false) if lxrod.MonitorDialog { DialogWatch(ctx, page) //为新打开的页面添加一个dialog监控 } })() utils.E(proto.TargetSetAutoAttach{ AutoAttach: true, WaitForDebuggerOnStart: true, Flatten: true, }.Call(browser)) } func PageToClient(page *rod.Page, BaseURL string) (*http.Client, error) { c := lxhttp.NewHttpClient() e := rod.Try(func() { cookies := page.MustCookies() var cookiesArr []*http.Cookie for _, v := range cookies { var cookie http.Cookie cookie.Name = v.Name cookie.Value = v.Value cookiesArr = append(cookiesArr, &cookie) } clientURL, _ := url.Parse(BaseURL) c.Jar.SetCookies(clientURL, cookiesArr) }) return c, e } func BrowserToClient(b *rod.Browser, BaseURL string) (*http.Client, error) { domainMap := map[string][]*http.Cookie{} c := lxhttp.NewHttpClient() e := rod.Try(func() { cookies := b.MustGetCookies() for _, v := range cookies { var cookie http.Cookie cookie.Name = v.Name cookie.Value = v.Value cookie.Path = v.Path cookie.Domain = v.Domain domainMap[v.Domain] = append(domainMap[v.Domain], &cookie) } for _, cookie := range domainMap { clientURL, _ := url.Parse(BaseURL) c.Jar.SetCookies(clientURL, cookie) } }) return c, e } func BrowserToClientYunnan(b *rod.Browser, BaseURL string) (*http.Client, error) { domainMap := map[string][]*http.Cookie{} c := lxhttp.NewHttpClient() e := rod.Try(func() { cookies := b.MustGetCookies() for _, v := range cookies { var cookie http.Cookie cookie.Name = v.Name cookie.Value = v.Value cookie.Path = v.Path cookie.Domain = v.Domain domainMap[v.Domain] = append(domainMap[v.Domain], &cookie) } for _, cookie := range domainMap { clientURL, _ := url.Parse(BaseURL) c.Jar.SetCookies(clientURL, cookie) } u, auth := GetLocalProxy("yunnan") uu, _ := url.Parse(u) c.Transport = &http.Transport{Proxy: http.ProxyURL(uu), ProxyConnectHeader: http.Header{ "Proxy-Authorization": []string{"Basic " + base64.StdEncoding.EncodeToString([]byte(auth))}, }} }) return c, e } func BrowserToClientByProxy(b *rod.Browser, BaseURL string) (*http.Client, error) { area := "" { u, _ := url.Parse(BaseURL) area = strings.Split(u.Host, ".")[1] } if area == "" { return lxhttp.NewHttpClient(), taxerr.TimeOut } domainMap := map[string][]*http.Cookie{} c := lxhttp.NewHttpClient() proxy, auth := GetLocalProxy(area) uu, _ := url.Parse(proxy) tr := &http.Transport{Proxy: http.ProxyURL(uu)} if auth != "" { tr.ProxyConnectHeader = http.Header{ "Proxy-Authorization": []string{"Basic " + base64.StdEncoding.EncodeToString([]byte(auth))}, } } c.Transport = tr e := rod.Try(func() { cookies := b.MustGetCookies() for _, v := range cookies { var cookie http.Cookie cookie.Name = v.Name cookie.Value = v.Value cookie.Path = v.Path cookie.Domain = v.Domain domainMap[v.Domain] = append(domainMap[v.Domain], &cookie) } for _, cookie := range domainMap { clientURL, _ := url.Parse(BaseURL) c.Jar.SetCookies(clientURL, cookie) } }) return c, e } func (lxrod *Lxrod) NewByHjj(ctx context.Context) (b *rod.Browser, p *rod.Page, err error) { _ = rod.Try(func() { _ = lxrod.CloseBrowser() }) lxrod.Launcher = launcher.New() lxrod.Launcher.Set("window-size", "1600,900"). Set("no-sandbox"). Set("ignore-certificate-errors"). Set("ignore-certificate-errors-spki-list"). Set("ignore-ssl-errors"). Set("disable-features", "CalculateNativeWinOcclusion"). Headless(lxrod.Headless) //lxrod.Launcher.UserDataDir("user-data") lxrod.Launcher.Flags["disable-blink-features"] = []string{"AutomationControlled"} u, err := lxrod.Launcher.Launch() if err != nil { err = taxerr.New("调用浏览器失败,请稍后重试!") return lxrod.Browser, p, err } err = rod.Try(func() { lxrod.Browser = rod.New().ControlURL(u).MustConnect().Context(ctx) utils.Sleep(1) lxrod.Browser.MustSetCookies() }) if err != nil { return nil, nil, taxerr.NewWebStuckTitle(true) } lxrod.Browser.NoDefaultDevice() p = stealth.MustPage(lxrod.Browser) if lxrod.MonitorDialog { //为新打开的页面添加一个dialog监控 DialogWatch(ctx, p) go lxrod.Browser.EachEvent(func(e *proto.TargetTargetCreated) { defer func() { if r := recover(); r != nil { } }() if e.TargetInfo.Type != proto.TargetTargetInfoTypePage { return } page := lxrod.Browser.MustPageFromTargetID(e.TargetInfo.TargetID) DialogWatch(ctx, page) })() } p = p.MustSetWindow(0, 0, 1600, 900).MustSetViewport(1600, 900, 1, false) return lxrod.Browser, p, err } // 新建浏览器对象 func (lxrod *Lxrod) NewBeijing(ctx context.Context) (b *rod.Browser, p *rod.Page, err error) { rod.Try(func() { lxrod.CloseBrowser() os.RemoveAll("tmp/") }) lxrod.Launcher = launcher.NewUserMode() u, err := lxrod.Launcher. // New(). Leakless(true). UserDataDir("tmp/t"). Set("disable-default-apps"). Set("no-first-run"). //Set("disable-plugins"). Set("disable-popup-blocking"). Set("disable-features", "CalculateNativeWinOcclusion"). Headless(lxrod.Headless). Launch() if err != nil { return nil, nil, taxerr.NewUser("浏览器创建失败请稍后重试1") } utils.Sleep(3) err = rod.Try(func() { b = rod.New().ControlURL(u).Timeout(time.Second * 60).MustConnect().Context(ctx).NoDefaultDevice() }) if err != nil { return nil, nil, taxerr.NewUser("浏览器创建失败请稍后重试2") } b.MustIncognito() p = b.MustPage("") lxrod.Browser = b go b.EachEvent(func(e *proto.TargetTargetCreated) { defer func() { if r := recover(); r != nil { } }() if e.TargetInfo.Type != proto.TargetTargetInfoTypePage { return } page := b.MustPageFromTargetID(e.TargetInfo.TargetID) page.MustSetWindow(0, 0, 1600, 900).MustSetViewport(1600, 900, 1, false) })() return b, p, err } func (lxrod *Lxrod) NewHuBei(ctx context.Context) (b *rod.Browser, p *rod.Page, err error) { rod.Try(func() { lxrod.CloseBrowser() }) l := launcher. New(). Set("window-size", "1600,900"). Leakless(true). Set("disable-features", "CalculateNativeWinOcclusion"). Headless(false) lxrod.Launcher = l //lxrod.Launcher.UserDataDir("user-data") l.Flags["disable-blink-features"] = []string{"AutomationControlled"} //if viper.GetString("env") == string(variable.Development) { // l.Leakless(false) //开发环境不使用用leakless //} u := l.MustLaunch() b = rod.New().ControlURL(u).MustConnect().NoDefaultDevice() p = stealth.MustPage(b) lxrod.Browser = b go b.EachEvent(func(e *proto.TargetTargetCreated) { defer func() { if r := recover(); r != nil { } }() if e.TargetInfo.Type != proto.TargetTargetInfoTypePage { return } page := b.MustPageFromTargetID(e.TargetInfo.TargetID) _, err := page.EvalOnNewDocument(stealth.JS) if err != nil { return } page.MustEvalOnNewDocument(stealth.JS) page.MustSetUserAgent(nil) utils.E(proto.RuntimeRunIfWaitingForDebugger{}.Call(page)) page.MustSetWindow(0, 0, 1600, 900).MustSetViewport(1600, 900, 1, false) })() utils.E(proto.TargetSetAutoAttach{ AutoAttach: true, WaitForDebuggerOnStart: true, Flatten: true, }.Call(b)) return b, p, err } func (lxrod *Lxrod) NewNoParam() (b *rod.Browser, p *rod.Page, err error) { rod.Try(func() { lxrod.CloseBrowser() }) l := launcher. New(). Set("window-size", "1600,900"). Leakless(true). Set("disable-features", "CalculateNativeWinOcclusion"). Headless(false) lxrod.Launcher = l //lxrod.Launcher.UserDataDir("user-data") l.Flags["disable-blink-features"] = []string{"AutomationControlled"} //if viper.GetString("env") == string(variable.Development) { // l.Leakless(false) //开发环境不使用用leakless //} u := l.MustLaunch() b = rod.New().ControlURL(u).MustConnect().NoDefaultDevice() p = stealth.MustPage(b) lxrod.Browser = b go b.EachEvent(func(e *proto.TargetTargetCreated) { defer func() { if r := recover(); r != nil { } }() if e.TargetInfo.Type != proto.TargetTargetInfoTypePage { return } page := b.MustPageFromTargetID(e.TargetInfo.TargetID) _, err := page.EvalOnNewDocument(stealth.JS) if err != nil { return } page.MustEvalOnNewDocument(stealth.JS) page.MustSetUserAgent(nil) utils.E(proto.RuntimeRunIfWaitingForDebugger{}.Call(page)) page.MustSetWindow(0, 0, 1600, 900).MustSetViewport(1600, 900, 1, false) })() utils.E(proto.TargetSetAutoAttach{ AutoAttach: true, WaitForDebuggerOnStart: true, Flatten: true, }.Call(b)) return b, p, err } // 最简单的浏览器创建 func (lxrod *Lxrod) NewLowBrowser(ctx context.Context) (b *rod.Browser, p *rod.Page, err error) { rod.Try(func() { if lxrod.Browser != nil { lxrod.CloseBrowser() utils.Sleep(5) } }) l := launcher.New(). Headless(false). Set("high-dpi-support", "1"). Set("disable-features", "CalculateNativeWinOcclusion"). Set("force-device-scale-factor", "1") l.Flags["disable-blink-features"] = []string{"AutomationControlled"} lxrod.Launcher = l //lxrod.Launcher.UserDataDir("user-data") //if lxrod.Area == "hebei" { // lxrod.Launcher.UserDataDir("user-data") //} if lxrod.UseProxy { lxrod.Proxy, lxrod.ProxyAuth = GetLocalProxy(string(lxrod.Area)) lxrod.Launcher.Proxy(lxrod.Proxy) } wsURL, err := l.Launch() lxrod.WsURL = wsURL if err != nil { return nil, nil, taxerr.NewWebStuckTitle(true) } b = rod.New().ControlURL(wsURL).Context(ctx).MustConnect() utils.Sleep(1) b = b.MustSetCookies() if lxrod.UseProxy && lxrod.ProxyAuth != "" { auths := strings.Split(lxrod.ProxyAuth, ":") go b.HandleAuth(auths[0], auths[1])() } p = b.MustPage().MustSetWindow(0, 0, 1600, 900).MustSetViewport(1600, 900, 1, false) if lxrod.MonitorDialog && lxrod.NoEachEventForCreated { //为新打开的页面添加一个dialog监控 DialogWatch(ctx, p) go b.EachEvent(func(e *proto.TargetTargetCreated) { defer func() { if r := recover(); r != nil { } }() if e.TargetInfo.Type != proto.TargetTargetInfoTypePage { return } page := b.MustPageFromTargetID(e.TargetInfo.TargetID) DialogWatch(ctx, page) })() } lxrod.Browser = b return b, p, nil } // NewBrowserBank360 打开 360 急速浏览器。适用于既要 ocx 密码输入又要 chrome 采集的银行任务, // 如承德银行。运行前需要先安装 360 急速浏览器,然后将 360 急速浏览器的安装目录添加到环境变量中。 // 对于银行采集服务器,这个目录一般是: // // "C:\\Users\\taxrobot\\Desktop\\360Chrome1\\" func (lxrod *Lxrod) NewBrowserBank360(ctx context.Context) (b *rod.Browser, p *rod.Page, err error) { rod.Try(func() { lxrod.CloseBrowser() }) bin, err := exec.LookPath("360chromeX.exe") if err != nil { return nil, nil, taxerr.NewUser("请先安装360极速浏览器(" + err.Error() + ")") } l := launcher.New(). Headless(false). Bin(bin). //Bin("C:\\Program Files (x86)\\税局小助手\\360Chrome\\360chromeX.exe"). Set("high-dpi-support", "1"). Set("disable-features", "CalculateNativeWinOcclusion"). Set("force-device-scale-factor", "1") l.Flags["disable-blink-features"] = []string{"AutomationControlled"} lxrod.Launcher = l wsURL, err := l.Launch() lxrod.WsURL = wsURL if err != nil { return nil, nil, taxerr.NewWebStuckTitle(true) } b = rod.New().ControlURL(wsURL).Context(ctx).MustConnect() p = b.MustPage().MustSetWindow(0, 0, 1600, 900).MustSetViewport(1600, 900, 1, false) if lxrod.MonitorDialog { //为新打开的页面添加一个dialog监控 DialogWatch(ctx, p) go b.EachEvent(func(e *proto.TargetTargetCreated) { defer func() { if r := recover(); r != nil { } }() if e.TargetInfo.Type != proto.TargetTargetInfoTypePage { return } page := b.MustPageFromTargetID(e.TargetInfo.TargetID) DialogWatch(ctx, page) })() } lxrod.Browser = b return b, p, nil } // 最简单的浏览器创建2 func (lxrod *Lxrod) NewLowBrowser2(ctx context.Context) (b *rod.Browser, p *rod.Page, err error) { rod.Try(func() { lxrod.CloseBrowser() }) l := launcher.New(). Headless(false). Set("high-dpi-support", "1"). Set("disable-features", "CalculateNativeWinOcclusion"). Set("force-device-scale-factor", "1") l.Flags["disable-blink-features"] = []string{"AutomationControlled"} lxrod.Launcher = l //lxrod.Launcher.UserDataDir("user-data") wsURL, err := l.Launch() if err != nil { return nil, nil, taxerr.NewWebStuckTitle(true) } b = rod.New().ControlURL(wsURL).Context(ctx).MustConnect() p = b.MustPage().MustSetWindow(0, 0, 1600, 900).MustSetViewport(1600, 900, 1, false) lxrod.Browser = b if lxrod.MonitorDialog { DialogWatch(ctx, p) //为新打开的页面添加一个dialog监控 } if lxrod.UseProxy { lxrod.Proxy, lxrod.ProxyAuth = GetLocalProxy(string(lxrod.Area)) lxrod.Launcher.Proxy(lxrod.Proxy) } return b, p, nil } // 自定义鼠标操作 方便升降版本 type Mouse struct { Mouse *rod.Mouse } func (m *Mouse) MustMove(x, y float64) *Mouse { m.Mouse.MustMoveTo(x, y) return m } func (m *Mouse) MustDown(button proto.InputMouseButton) *Mouse { m.Mouse.MustDown(button) return m } func (m *Mouse) MustUp(button proto.InputMouseButton) *Mouse { m.Mouse.MustUp(button) return m } func (m *Mouse) MustClick(button proto.InputMouseButton) *Mouse { m.Mouse.MustClick(button) return m } func ShenzhenProxy() string { // 获取私密代理IP API api := "https://dps.kdlapi.com/api/getdps" // 请求参数 params := url.Values{} params.Set("secret_id", "odr5kxfzzky69wbtuhzh") params.Set("signature", "qwndesfg2ouix111a8rfzyixou7q9nr3") params.Set("num", strconv.Itoa(1)) // 提取数量 // 构建完整的URL,包括参数 fullURL := api + "?" + params.Encode() // 发送GET请求 response, err := http.Get(fullURL) if err != nil { fmt.Println("Error:", err) return "" } defer response.Body.Close() // 读取响应内容 body, err := io.ReadAll(response.Body) if err != nil { fmt.Println("Error reading response body:", err) return "" } // 输出响应结果 return "http://" + string(body) } // 备用 func (lxrod *Lxrod) BeijingNew(ctx context.Context) (b *rod.Browser, p *rod.Page, err error) { _ = rod.Try(func() { lxrod.CloseBrowser() }) l := launcher.New().Set("window-size", "1600,900"). Delete("enable-automation"). Leakless(true). Headless(false).Set("disable-features", "CalculateNativeWinOcclusion") l.Flags["disable-blink-features"] = []string{"AutomationControlled"} u := l.MustLaunch() b = rod.New().ControlURL(u).MustConnect() p = b.MustPage("") lxrod.Browser = b return b, p, nil } // GetLocalProxy 获取所有地区代理 部分地区是使用的我们自己的代理池 func GetLocalProxy(Area string) (string, string) { // 都换成5879 if Area == "xizang" /*|| Area == "yunnan"*/ || Area == "hebei" || Area == "liaoning" || Area == "chongqing" || Area == "sichuan" { return `http://8.141.85.129:5879`, "lxuser:Aa123456" } if Area == "yunnan" { return "http://106.58.178.172:27237", "13280888700:nPDZ0RYX" } if Area == "shenzhen" { return ShenzhenProxy(), "d2879234360:ikdnhzbk" } return `http://8.141.85.129:5879`, "lxuser:Aa123456" }