基础用法
开启一个新的chrome 的浏览器会话框
获取当前页面的标签
wd.Title()
刷新浏览器页面
if err := wd.Refresh(); err != nil {
panic(err)
}
登录按钮
type = "submit" 类型唯一 筛选选择登录元素
span 元素无法登录 需要<button> 元素的xpath 实现点击操作
submitElem, _ := wd.FindElement(selenium.ByXPATH, "//*[@id=\"root\"]/section/main/section/main/div/div/form/div[4]/div/div/span/button")
submitElem.Click()
验证码 获取验证码的css 唯一的css
便签页样式唯一 class
captchaElem, err := wd.FindElement(selenium.ByCSSSelector, ".login-captcha")
a 标签 点击a 标签的链接
基于xpath 实现
siteAdminElem, _ := wd.FindElement(selenium.ByXPATH, "//*[@id=\"/merchants$Menu\"]/li[1]/a")
siteAdminElem.Click()
基于css 样式选择器实现 点击弹窗按钮
IknowElem, _ := wd.FindElement(selenium.ByCSSSelector, ".ant-modal-confirm-btns")
IknowElem.Click()
登录网页并输入验证码
package selenium
import (
"fmt"
"github.com/otiai10/gosseract/v2"
"github.com/tebeka/selenium"
"image"
"image/png"
"log"
"os"
"time"
)
const (
adminURL = "https:///"
username = ""
password = ""
captchaFile = "D:\\projects\\server\\captcha.png"
fullPageScreenshotFile = "D:\\projects\\server\\full_page_screenshot.png"
)
func GetAdminLinkTools() {
var opts []selenium.ServiceOption
selenium.SetDebug(true)
service, err := selenium.NewChromeDriverService("D:\\projects\\server\\chromedriver.exe", 4444, opts...)
if err != nil {
log.Printf("ChromeDriver server启动错误: %v", err)
return
}
defer service.Stop()
// 配置 Chrome 浏览器选项以无痕模式启动
chromeCaps := selenium.Capabilities{
"browserName": "chrome",
"goog:chromeOptions": map[string]interface{}{
"args": []string{
"--incognito",
},
},
}
// 最大化浏览器窗口
wd, err := selenium.NewRemote(chromeCaps, "http://localhost:4444/wd/hub")
if err != nil {
log.Printf("WebDriver 连接失败: %v", err)
return
}
err = wd.MaximizeWindow("")
defer wd.Quit()
// 打开管理后台
if err := wd.Get(adminURL); err != nil {
log.Printf("总后台登录首页打开失败:https://web.3333c.vip : %v", err)
return
}
time.Sleep(3 * time.Second)
// 刷新页面
if err := wd.Refresh(); err != nil {
panic(err)
}
time.Sleep(2 * time.Second)
// 输入用户名
usernameElem, _ := wd.FindElement(selenium.ByID, "username")
usernameElem.SendKeys(username)
// 输入密码
passwordElem, _ := wd.FindElement(selenium.ByID, "password")
passwordElem.SendKeys(password)
// 查找验证码图像元素 基于css 样式选择器 样式唯一
captchaElem, err := wd.FindElement(selenium.ByCSSSelector, ".login-captcha")
if err != nil {
panic(err)
}
// 获取验证码图像的位置和大小
loc, err := captchaElem.Location()
if err != nil {
fmt.Printf("Error getting captcha location: %v\n", err)
return
}
size, err := captchaElem.Size()
if err != nil {
fmt.Printf("Error getting captcha size: %v\n", err)
return
}
captchaUrl, _ := captchaElem.GetAttribute("src")
fmt.Printf("验证码图片链接: %s\n", captchaUrl)
fmt.Printf("截取验证码的坐标位置:%v\n,\n", loc)
// 获取整个页面截图
screenshot, err := wd.Screenshot()
if err != nil {
log.Fatalf("截图整个登录页面出错: %v", err)
}
// 保存整个页面截图到文件
if err := os.WriteFile(fullPageScreenshotFile, screenshot, 0644); err != nil {
log.Fatalf("Error saving the full page screenshot: %v", err)
}
fmt.Printf("成功截图整个登录页面 %s\n", fullPageScreenshotFile)
// 打开保存的整个页面截图文件
file, err := os.Open(fullPageScreenshotFile)
if err != nil {
log.Fatalf("打开整个登录页面截图报错: %v", err)
}
defer file.Close()
// 解码整个页面截图
img, err := png.Decode(file)
if err != nil {
log.Fatalf("全页面登录页解码报错: %v", err)
}
// 裁剪出验证码区域
bounds := image.Rect(loc.X, loc.Y, loc.X+size.Width, loc.Y+size.Height)
captchaImg := img.(interface {
SubImage(r image.Rectangle) image.Image
}).SubImage(bounds)
// 保存裁剪后的验证码图像到文件
captchaOutputFile, err := os.Create(captchaFile)
if err != nil {
log.Fatalf("保存截取后的验证码图像到文件报错Error: %v", err)
}
defer captchaOutputFile.Close()
if err := png.Encode(captchaOutputFile, captchaImg); err != nil {
log.Fatalf("验证码图像解码报错Error: %v", err)
}
fmt.Printf("验证码图像成功保存到文件:%s\n", captchaFile)
// 使用 OCR 识别验证码
client := gosseract.NewClient()
defer client.Close()
client.SetImage(captchaFile)
captchaText, err := client.Text()
if err != nil {
fmt.Printf("Error recognizing captcha: %v\n", err)
return
}
fmt.Printf("Recognized captcha text: %s\n", captchaText)
time.Sleep(15 * time.Second)
}
go selenium OCR 解析验证码
func GetCaptchaCode() (string, error) {
imageData, err := os.ReadFile(captchaFile)
if err != nil {
panic(err)
}
base64Image := base64.StdEncoding.EncodeToString(imageData)
data := url.Values{}
data.Set("image", base64Image)
data.Set("probability", "false")
data.Set("png_fix", "false")
resp, err := http.PostForm(ApiOCRUrl, data)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
panic(err)
}
fmt.Println("验证码json: " + string(body))
// 定义一个结构体或map 来存储解析后的 JSON 数据
var result map[string]interface{}
err = json.Unmarshal(body, &result)
if err != nil {
panic(err)
}
// 提取验证码对应的data 字段的值
if data, ok := result["data"].(string); ok {
fmt.Println("验证码:", data)
return data, err
} else {
fmt.Println("OCR解析验证码错误")
}
return "获取OCR验证码错误", nil
}