golang Selenium WebDriver 使用记录
🕛 Wed, 31 Oct 2018 by GolangNote
Selenium WebDriver 直接通过浏览器自动化的本地接口来调用浏览器,以达到模拟浏览器行为的操作,如点击、选择、鼠标移动等。下面是记录个人使用golang 驱动的记录。
下载Selenium 驱动
Selenium 官网 https://www.seleniumhq.org 208 在那可以下载对应浏览器的驱动。你可以下载一个jar 包 Selenium Standalone Server
这个比较方便,可以运行在多个不同平台,但需要计算机有java 运行环境。
也可以根据自己的需求下载特定浏览器的驱动,如The Internet Explorer Driver Server
、Mozilla GeckoDriver
、Google Chrome Driver
等,这都是二进制文件,可以单独运行,不依赖java 环境。
选择 golang 驱动
这个库是目前比较完善的golang Selenium 驱动 https://github.com/tebeka/selenium 240,但官方没有IeDriverService
,这里我做一个补充,在service.go
里面添加一个函数:
func NewIeDriverService(path string, port int, opts ...ServiceOption) (*Service, error) {
cmd := exec.Command(path, "--port="+strconv.Itoa(port))
s, err := newService(cmd, port, opts...)
if err != nil {
return nil, err
}
if err := s.start(port); err != nil {
return nil, err
}
return s, nil
}
这样就可以在外部调用:
service, err := selenium.NewIeDriverService("IEDriverServer.exe", port, opts...)
if err != nil {
panic(err)
}
使用动态端口
因为启动 DriverService
需要占用一个端口,防止指定端口已经被占用,可以用下面的函数来动态获取一个可用端口。
func pickUnusedPort() (int, error) {
addr, err := net.ResolveTCPAddr("tcp", "127.0.0.1:0")
if err != nil {
return 0, err
}
l, err := net.ListenTCP("tcp", addr)
if err != nil {
return 0, err
}
port := l.Addr().(*net.TCPAddr).Port
if err := l.Close(); err != nil {
return 0, err
}
return port, nil
}
完整例子
下面是在官方例子上做了一点修改,使用ieDriver
的例子:
package main
import (
"fmt"
"github.com/tebeka/selenium"
"net"
"os"
"time"
)
func pickUnusedPort() (int, error) {
addr, err := net.ResolveTCPAddr("tcp", "127.0.0.1:0")
if err != nil {
return 0, err
}
l, err := net.ListenTCP("tcp", addr)
if err != nil {
return 0, err
}
port := l.Addr().(*net.TCPAddr).Port
if err := l.Close(); err != nil {
return 0, err
}
return port, nil
}
func main() {
port, err := pickUnusedPort()
fmt.Println("port", port)
opts := []selenium.ServiceOption{
selenium.Output(os.Stderr),
}
selenium.SetDebug(false)
service, err := selenium.NewIeDriverService("IEDriverServer.exe", port, opts...)
if err != nil {
panic(err)
}
defer service.Stop()
fmt.Println("here 1")
// 起新线程在新标签页打开窗口
go func() {
caps := selenium.Capabilities{"browserName": "internet explorer"}
wd, err := selenium.NewRemote(caps, fmt.Sprintf("http://localhost:%d", port))
if err != nil {
panic(err)
}
defer wd.Quit()
if err := wd.Get("https://www.baidu.com"); err != nil {
panic(err)
}
time.Sleep(time.Second * 10)
// 在窗口调用js 脚本
wd.ExecuteScript(`window.open("https://www.qq.com", "_blank");`, nil)
time.Sleep(time.Second * 20)
}()
// 打开一个在一个标签页里打开一个窗口
caps := selenium.Capabilities{"browserName": "internet explorer"}
wd, err := selenium.NewRemote(caps, fmt.Sprintf("http://localhost:%d", port))
if err != nil {
panic(err)
}
defer wd.Quit()
// Navigate to the simple playground interface.
if err := wd.Get("http://play.golang.org/?simple=1"); err != nil {
panic(err)
}
// Get a reference to the text box containing code.
elem, err := wd.FindElement(selenium.ByCSSSelector, "#code")
if err != nil {
panic(err)
}
// Remove the boilerplate code already in the text box.
if err := elem.Clear(); err != nil {
panic(err)
}
// Enter some new code in text box.
err = elem.SendKeys(`
package main
import "fmt"
func main() {
fmt.Println("Hello WebDriver!\n")
}
`)
if err != nil {
panic(err)
}
// Click the run button.
btn, err := wd.FindElement(selenium.ByCSSSelector, "#run")
if err != nil {
panic(err)
}
if err := btn.Click(); err != nil {
panic(err)
}
// Wait for the program to finish running and get the output.
outputDiv, err := wd.FindElement(selenium.ByCSSSelector, "#output")
if err != nil {
panic(err)
}
var output string
for {
output, err = outputDiv.Text()
if err != nil {
panic(err)
}
if output != "Waiting for remote server..." {
break
}
time.Sleep(time.Second * 1)
}
fmt.Println("waiting....")
time.Sleep(time.Second * 80)
// Example Output:
// Hello WebDriver!
//
// Program exited.
}
注意问题
如果用 Selenium Standalone Server
启动 NewRemote
时,路径不同,应设为:
wd, err := selenium.NewRemote(caps, fmt.Sprintf("http://localhost:%d/wd/hub", port))
本文网址: https://golangnote.com/topic/230.html (转载注明出处)
关于GolangNote:记录在工作中使用golang 遇到、面临的相关问题及解决方法。如果你在这里获得一些知识或信息,解决你的编程问题,请考虑捐赠给不幸的人或者你喜欢的慈善机构,除捐赠外,种植树木、志愿服务或减少排碳的行为也很有益处。如果你有任何问题可以在下面 留言
Be the first to comment!
Relative Articles
Recent Go Articles
- Golang 把cookie 字符串解析为cookie 结构
- Golang 计算字符串中包含某个或某些字符集的个数
- 使用Golang 对文件增删写读操作备忘
- Go Modules 使用备忘
- 使用Golang 简单删除图片exif 信息
- 谷歌翻译的 golang 库推荐
- Go 1.13.2 与1.13.3 紧急更新
- golang 人脸检测识别库
- Go build 错误 “stackcheck redeclared in this block previous declaration”的解决方法
- Golang phantomjs 动态代理实现
- Golang chrome debug protocol 库推荐
- Golang 随机打乱数组/Slice
- Golang sync.WaitGroup 的 Wait 超时处理
- Golang实现简单的Socks5代理
- Golang 用snappy + Base64 简单压缩加密进行网络传输
- Golang http IPv4/IPv6 服务
- golang 全角半角相互转换
- 在自己的网站部署TLS 1.3
- Golang 实现/打印菜单树
- Golang telegram 机器人小试
Top Go Articles
- golang 实现简单的socket 服务端/客户端
- Golang 字符串毫秒转时间格式
- goji + mysql 例子
- 用Go net 工具包获取DNS 信息
- 推荐几款开源免费的用golang写的论坛程序
- GoLang 获取变量类型
- Golang Web 自动安装、更新Let’s Encrypt 免费证书
- golang Selenium WebDriver 使用记录
- Golang Leveldb 基本使用的例子
- go 实现图片服务器缓存
- Golang io.ReadCloser 和[]byte 相互转化的方法
- Golang WebAssembly 了解一下
- groupcache 使用入门
- Golang 随机打乱数组/Slice
- GoLang 遍历目录的不同方法
- Golang byte to string 的方法实践
- Golang 合并byte 的性能比较
- GoLang 实现python timedelta 函数功能
- golang leveldb 区间查找
- Golang http.Post 用最小的内存发送大文件