Selenium WebDriver 直接通过浏览器自动化的本地接口来调用浏览器,以达到模拟浏览器行为的操作,如点击、选择、鼠标移动等。下面是记录个人使用golang 驱动的记录。
下载Selenium 驱动
Selenium 官网 https://www.seleniumhq.org 在那可以下载对应浏览器的驱动。你可以下载一个jar 包 Selenium Standalone Server
这个比较方便,可以运行在多个不同平台,但需要计算机有java 运行环境。
也可以根据自己的需求下载特定浏览器的驱动,如 The Internet Explorer Driver Server
、Mozilla GeckoDriver
、Google Chrome Driver
等,这都是二进制文件,可以单独运行,不依赖java 环境。
选择 golang 驱动
这个库是目前比较完善的 golang Selenium 驱动 https://github.com/tebeka/selenium,但官方没有IeDriverService
,这里我做一个补充,在 service.go
里面添加一个函数:
1
2
3
4
5
6
7
8
9
10
11
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
}
这样就可以在外部调用:
1
2
3
4
service, err := selenium.NewIeDriverService("IEDriverServer.exe", port, opts...)
if err != nil {
panic(err)
}
使用动态端口
因为启动 DriverService
需要占用一个端口,防止指定端口已经被占用,可以用下面的函数来动态获取一个可用端口。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
的例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
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
时,路径不同,应设为:
1
wd, err := selenium.NewRemote(caps, fmt.Sprintf("http://localhost:%d/wd/hub", port))
本文网址: https://golangnote.com/topic/230.html 转摘请注明来源