用rod获取百度搜索结果的例子
package main import ( "fmt" "time" "github.com/ysmood/rod" "github.com/ysmood/rod/lib/input" "github.com/ysmood/rod/lib/launcher" ) func Example_reuse_sessions() { url := launcher.NewUserMode().Launch() browser := rod.New().ControlURL(url).Connect() page := browser.Timeout(time.Second * 15).Page("https://www.baidu.com") page.Window(0, 0, 1920, 1080) // use css selector to get the search input element and input "git" page.Element("#kw").Input("测试").Press(input.Enter) // wait until css selector get the element then get the text content of it text := page.Element(`#\31 > div.c-abstract`).Text() //这里的选择器selector是从chrome控制台中copy的。 fmt.Println(text) fmt.Println("done") // Skip // Output: done } func main() { Example_reuse_sessions() for { } }
比较简洁、直观。
补充:用带iframe及alert的那个内网站点测试一下,果然很爽
package main import ( "fmt" "time" "github.com/ysmood/rod" "github.com/ysmood/rod/lib/input" "github.com/ysmood/rod/lib/launcher" ) func Example_reuse_sessions() { //page.WindowMaximize() //获取地址栏url看看 url := launcher.NewUserMode().Launch() browser := rod.New().ControlURL(url).Connect() for _, p := range browser.Pages() { uri := p.Eval(`() => window.location.href`).String() fmt.Println(uri) } page := browser.Pages()[0] page.Navigate("http://192.168.132.XX/login/Login.jsp?logintype=1") page.WaitIdle() page.Element("#loginid").Input("admin") page.Element("#userpassword").Input("1234").Press(input.Enter) //page.Element("#login").Click() page.WaitIdle() //这里不能用time.sleep延时 //再次获取地址栏url看看 for _, p := range browser.Pages() { uri := p.Eval(`() => window.location.href`).String() fmt.Println(uri) } fmt.Println(page.Element("#_ButtonOK_0").Text()) page.Element("#_ButtonCancel_0").Click() //正式开始作业,处理iframe for i := 0; i < 5; i++ { Do() } } func Do() { //page.WindowMaximize() //获取地址栏url看看 url := launcher.NewUserMode().Launch() browser := rod.New().ControlURL(url).Connect() for _, p := range browser.Pages() { uri := p.Eval(`() => window.location.href`).String() fmt.Println(uri) } page := browser.Pages()[0] page.Navigate("http://192.168.132.80/wui/main.jsp?templateId=3") page.WaitIdle() //正式开始作业,处理iframe frame01 := page.Timeout(6 * time.Second).Element("[name=mainFrame]").Frame() fmt.Println(frame01.Element("#_contenttable_655 > tbody > tr > td:nth-child(2) > table > tbody > tr:nth-child(1) > td:nth-child(2) > a > font > font > span").Text()) frame01.Element("#_contenttable_655 > tbody > tr > td:nth-child(2) > table > tbody > tr:nth-child(1) > td:nth-child(2) > a > font > font > span").Click() page.WaitIdle() //点击后会弹出新窗口,所以这句或许应改成page.WaitPage() page = browser.Pages()[0] frame01 = page.Element("[name=bodyiframe]").Frame() frame01.WaitIdle() fmt.Println(frame01.Element("#flowbody > table > tbody > tr > td > form > div:nth-child(23) > font").Text()) fmt.Println("here") frame02 := frame01.Element("#cke_contents_remark > iframe").Frame() frame02.WaitIdle() fmt.Println(frame02.Element("body").Text()) //frame02.Element("body").Click().Input("已审批").Press(input.Enter) frame02.Element("body").Click().Input("已审批") //可以不加Click() page.Element("#toolbarmenu > td:nth-child(1) > table > tbody > tr:nth-child(2) > td.x-btn-mc > em > button").Click() page.HandleDialog(true, "") //之前不知道用这句,向页面body直接.Press(input.Enter)竟然也可以关掉alert page.Close() //也许应加上go关键词,但代码能用就行了。 fmt.Println("done") } func main() { Example_reuse_sessions() }
上面是初学时写的例子,实际运行中不太可靠。后来修改为类似下面的例子。在学习过程中还得到了ysmood本人的热心帮助,深表感谢!
package main import ( "fmt" "time" "github.com/ysmood/rod" "github.com/ysmood/rod/lib/input" "github.com/ysmood/rod/lib/launcher" "github.com/ysmood/rod/lib/proto" ) // Shows how to subscribe events. //var e9 = &proto.PageLoadEventFired{} //var backoff = kit.BackoffSleeper(1*time.Second, 8*time.Second, nil) func main() { url := launcher.New(). Headless(false). // run chrome on foreground, you can also use env "rod=show" //Delete("enable-automation"). //可以让chrome不显示那句"chrome正受到自动测试软件的控制"。 Devtools(false). // open devtools for each new tab Launch() browser := rod.New(). ControlURL(url). Slowmotion(300 * time.Millisecond). // each input action will take 2 second Connect(). Timeout(30 * time.Second) //defer browser.Close() page01 := browser.Pages()[0] proto.PageAddScriptToEvaluateOnNewDocument{ Source: `Object.defineProperties(navigator, {webdriver: {get: () => undefined}})`, //修改window.navigator.webdriver的值 }.Call(page01) //page01.Eval(`() => Object.defineProperties(navigator, {webdriver: {get: () => undefined}})`) //这句应该是晚了 //page01.WaitIdle() page01.WindowMaximize() page01.Navigate("http://192.168.132.80/login/Login.jsp?logintype=1").WaitLoad() //登录 page01.Element("#loginid").Input("admin") page01.Element("#userpassword").Input("1234").Press(input.Enter) page01.WaitLoad() //这里,登录后,会302跳转 page01.Element("#_ButtonCancel_0").WaitVisible().Click() //关闭第一个页面中的div对话框 //在当前登录后主页基础上,开始循环处理 for i := 1; i < 5; i++ { dowork(page01) } } func dowork(page01 *rod.Page) { frame01_01 := page01.Element("[name=mainFrame]").Frame() //第一个页面中的第一个frame frame01_01.WaitLoad() frame01_01.Element("#more_655").Click() //这里,网页上的JS会弹出第二个页面page02 waitpage02 := page01.WaitPage() //等待页面创建完成 page02 := waitpage02() page02.WaitLoad() //time.Sleep(time.Duration(2) * time.Second) waitpage03 := page02.WaitPage() //等待第三个页面创建完成 page02.Element("#_xTable > div:nth-child(1) > div.table > table > tbody > tr:nth-child(1) > td:nth-child(6) > a").Press(input.Enter) //这里,网页上的JS会弹出第三个页面page03 page03 := waitpage03() page03.WaitLoad() frame03_01 := page03.Element("[name=bodyiframe]").Frame() frame03_01.WaitLoad() fmt.Println(frame03_01.Element("#flowbody > table > tbody > tr > td > form > div:nth-child(23) > font").Text()) //time.Sleep(time.Duration(2) * time.Second) frame03_02 := frame03_01.Element("#cke_contents_remark > iframe").Frame() frame03_02.WaitLoad() frame03_02.Element("body").Press(input.Enter).Input("已审批") //可以不用.Click() wait := page03.WaitRequestIdle() page03.Element("#toolbarmenu > td:nth-child(1) > table > tbody > tr:nth-child(2) > td.x-btn-mc > em > button").Press(input.Enter).Click() wait() page03.HandleDialog(true, "") //之前不知道用这句,向页面body直接.Press(input.Enter)竟然也可以关掉alert page03.Close() page02.Close() }