一、 前言
相信大家对于Selenium这个库并不陌生, 一个叱咤风云十年之久的UI自动化框架 很多人都会或多或少的使用过它 python或是java
今天也突发奇想,selenium既然已经支持了如此多的语言 那么Go语言中是否存在这个 *** 作浏览器的库呢?
抱着疑惑 打开了github.com
tebeka/selenium 1.8K的星目前使用率排行第一的三方库
不出意外那就是要出意外
1.8K的使用率代表的就是教程极少只能通过github官方文档 或源码去进行学习 接下来将分享我在本次学习过程中 趟过的坑 以及和python方法进行对比 加深认知
1. 安装selenium-go
go get github.com/tebeka/selenium
2. 安装重要依赖
首先需要安装seleniu-server.jar的依赖包 这个包将完成selenium的通信工作,
如不安装 在运行过程中 将出现 405报错
selenium-server-standalone-3.141.59.jar
下载地址 [https://github.com/adamhooper/selenium-server-standalone-jar/tree/master/jar](https://github.com/adamhooper/selenium-server-standalone-jar/tree/master/jar)
2. 安装webdriver:
selenium依赖驱动 大家在百度下载和各自浏览器相匹配的版本即可
Chrome:chromedriver.exe
firefox: geckodriver.exe
三、使用
写注释是一个好的习惯
package main
import (
"fmt"
"github.com/tebeka/selenium"
"os"
"reflect"
"time"
)
const (
// seleniumJar包存放位置
SeleniumPath = "F:\tools\geckodriver\selenium-server-standalone-3.141.59.jar"
// 驱动存放位置
FireFox = "F:\tools\geckodriver\geckodriver.exe"
// 打开 *** 作浏览器的名称(名称与驱动一致)
BrowserName = "firefox"
// 端口
Port = 9091
)
// 用于管理服务配置
type ServiceConfig struct {
SeleniumPath string
Port int
Config []selenium.ServiceOption
SetDebug bool
}
// 用于管理步骤
type CaseMrg struct {
BySelect, Element string
MethodName string
Timeout time.Duration
Value []reflect.Value
}
// 用于管理driver
type WebDriver struct {
Driver selenium.WebDriver
}
// 添加服务选项
func (s *ServiceConfig) AddServiceOption(opt ...selenium.ServiceOption) {
s.Config = append(s.Config, opt...)
}
// Get方法
func (d WebDriver) Get(url string) error {
return d.Driver.Get(url)
}
// 退出浏览器方法
func (d WebDriver) QuitBrowser() error {
return d.Driver.Quit()
}
// 构造函数 初始化配置
func NewServiceConfig(seleniumPath string, Port int, setDebug bool) ServiceConfig {
return ServiceConfig{
SeleniumPath: seleniumPath,
Port: Port,
Config: append(([]selenium.ServiceOption)(nil)),
SetDebug: setDebug,
}
}
// 构造函数 初始化服务
func NewService(config ServiceConfig) *selenium.Service {
selenium.SetDebug(config.SetDebug)
service, err := selenium.NewSeleniumService(config.SeleniumPath, config.Port, config.Config...)
if err != nil {
panic(err)
}
return service
}
// 构造函数 初始化driver,和服务
func NewWebDriver(config ServiceConfig, browser string) (service *selenium.Service, w WebDriver, err error) {
service = NewService(config)
opt := selenium.Capabilities{"browserName": browser}
w.Driver, err = selenium.NewRemote(opt, fmt.Sprintf("http://localhost:%d/wd/hub", config.Port))
if err != nil {
panic(err)
}
return service, w, nil
}
/* 轮询等待 二次封装
等待元素可见与python中的wait.until一致
WebDriverWait(self.driver, timeout=timeout).until(lambda x: x.find_element(("id", el)), message=msg)
*/
func WaitElementTimeout(d WebDriver, timeout time.Duration, by, value string) error {
var IsElementDisplay = func(wd selenium.WebDriver) (bool, error) {
ele, err := wd.FindElement(by, value)
if err != nil {
return false, err
}
b, errs := ele.IsDisplayed()
if errs != nil {
return false, err
}
return b, nil
}
if err := d.Driver.WaitWithTimeoutAndInterval(IsElementDisplay, timeout, 500*time.Millisecond); err != nil {
return err
}
return nil
}
// 管理步骤
func NewSliceMrg(names []string, BySelect, Ele []string, timeout time.Duration) []CaseMrg{
DataList := make([]CaseMrg, 0)
if len(names) >= 1 {
for i, v := range names {
d := CaseMrg{
BySelect: BySelect[i],
Element: Ele[i],
MethodName: v,
Timeout: timeout,
Value: []reflect.Value{reflect.ValueOf(BySelect[i]), reflect.ValueOf(Ele[i])},
}
DataList = append(DataList, d)
}
}
return DataList
}
// 通过反射拿到方法名称然后执行
func exeCommand(v reflect.Value, methodsName string, val []reflect.Value) []reflect.Value {
m := v.MethodByName(methodsName)
return m.Call(val)
}
// 执行用例
func Run(d WebDriver, dr CaseMrg) error {
// 反射
rfv := reflect.ValueOf(d.Driver)
// 等待元素出现
if err := WaitElementTimeout(d, 50*time.Second, dr.BySelect, dr.Element); err != nil {
fmt.Println("等待超時:", err)
time.Sleep(10 * time.Second)
return err
}
// 执行
result := exeCommand(rfv, dr.MethodName, dr.Value)
// 打印返回数据(selenium.Element func)
fmt.Println(result[0])
return nil
}
func main() {
// 测试一下. 首先配置服务选项
opt := []selenium.ServiceOption{
selenium.Output(os.Stderr), // 内容输出 这里是标准输出到控制台
selenium.GeckoDriver(FireFox), // 配置火狐驱动地址 chrome参考官网
}
// chrome请参考一下官方文档. 有部份不同
config := NewServiceConfig(SeleniumPath, Port, false) // 创建服务配置
config.AddServiceOption(opt...) // 添加
service, driver, _ := NewWebDriver(config, BrowserName) // 创建驱动
defer service.Stop() // 延时停止服务
const url = "https://www.baidu.com" // 请求地址
driver.Get(url) // 打开浏览器并加载地址
defer driver.QuitBrowser() // 延时关闭浏览器
s := NewSliceMrg([]string{"FindElement"}, []string{selenium.ByID}, []string{"kw"}, 20) // 多步骤管理
for _, v := range s {
// 执行步骤
if err := Run(driver, v); err != nil {
fmt.Println(err)
}
}
}
四、总结
相对来说,Go语言社区活跃并无python社区人数多 且该库使用率不高(目前selenium-go排行最高)与其生态有关 导致教程皆是基础教程 所以如果想要了解更多的应用 建议从官方库以及源码解读入手,同时该框架暂不支持鼠标事件(或者我暂时还没看到) 希望未来可以更加完善
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)