首先,你需要安装Go编译器。如果你还没有安装,可以访问 Go官网 进行安装。
接下来,我们需要安装Golang的Selenium客户端和OpenCV的Go绑定。
sh
go get -u github.com/tebeka/selenium
go get -u gocv.io/x/gocv
验证码页面
验证码页面地址:https://dun.163.com/trial/jigsaw
代码实现
1. 初始化Selenium
我们首先启动Selenium WebDriver并导航到验证码页面。
go
package main
import (
"fmt"
"log"
"time"
"github.com/tebeka/selenium"
)
const (
seleniumPath = "path/to/selenium-server-standalone.jar"
chromeDriverPath = "path/to/chromedriver"
port = 8080
)
func main() {
opts := []selenium.ServiceOption{
// selenium.StartFrameBuffer(), // Start an X frame buffer for the browser to run in.
// selenium.GeckoDriver(geckoDriverPath), // Specify the path to GeckoDriver in order to use Firefox.
selenium.ChromeDriver(chromeDriverPath), // Specify the path to ChromeDriver in order to use Chrome.
// selenium.Output(os.Stderr), // Output debug information to STDERR.
}
service, err := selenium.NewSeleniumService(seleniumPath, port, opts...)
if err != nil {
log.Println(err)
return
}
defer service.Stop()
caps := selenium.Capabilities{"browserName": "chrome"}
driver, err := selenium.NewRemote(caps, fmt.Sprintf("http://localhost:%d/wd/hub", port))
if err != nil {
log.Println(err)
return
}
defer driver.Quit()
if err := driver.Get("https://dun.163.com/trial/jigsaw"); err != nil {
log.Println(err)
return
}
time.Sleep(3 * time.Second)
// 后续的验证码处理代码将放在这里
}
2. 获取验证码图片
获取验证码图片并保存到本地,以便使用OpenCV进行图像处理。
go
import (
"io/ioutil"
"net/http"
"os"
)
func getImage(driver selenium.WebDriver, selector, filePath string) error {
elem, err := driver.FindElement(selenium.ByCSSSelector, selector)
if err != nil {
return err
}
imgURL, err := elem.GetAttribute("src")
if err != nil {
return err
}
resp, err := http.Get(imgURL)
if err != nil {
return err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
return ioutil.WriteFile(filePath, body, 0644)
}
func main() {
// 初始化代码同上...
getImage(driver, ".yidun_bg-img", "bg.png")
getImage(driver, ".yidun_jigsaw", "puzzle.png")
// 后续的验证码处理代码将放在这里
}
3. 使用OpenCV匹配图像
使用OpenCV找到拼图缺口的位置。
go
import (
"gocv.io/x/gocv"
)
func getSlideDistance() (float64, error) {
bgImage := gocv.IMRead("bg.png", gocv.IMReadColor)
if bgImage.Empty() {
return 0, fmt.Errorf("error reading background image")
}
defer bgImage.Close()
puzzleImage := gocv.IMRead("puzzle.png", gocv.IMReadColor)
if puzzleImage.Empty() {
return 0, fmt.Errorf("error reading puzzle image")
}
defer puzzleImage.Close()
result := gocv.NewMat()
defer result.Close()
gocv.MatchTemplate(bgImage, puzzleImage, &result, gocv.TmCcoeffNormed, gocv.NewMat())
_, _, _, maxLoc := gocv.MinMaxLoc(result)
return maxLoc.X, nil
}
func main() {
// 初始化代码同上...
getImage(driver, ".yidun_bg-img", "bg.png")
getImage(driver, ".yidun_jigsaw", "puzzle.png")
distance, err := getSlideDistance()
if err != nil {
log.Println(err)
return
}
fmt.Printf("Slide distance: %f\n", distance)
// 后续的验证码处理代码将放在这里
}
4. 模拟滑动行为
模拟人类滑动行为,以避免被检测为机器人。
go
import (
"math"
"math/rand"
"time"
)
func slidePuzzle(driver selenium.WebDriver, distance float64) error {
slider, err := driver.FindElement(selenium.ByCSSSelector, ".yidun_slider")
if err != nil {
return err
}
rect, err := slider.Rect()
if err != nil {
return err
}
startX := rect.X + rect.Width/2
startY := rect.Y + rect.Height/2
actions := driver.Action()
actions.MoveToElementWithOffset(slider, startX, startY).ClickAndHold()
steps := 30
moveX := distance / float64(steps)
for i := 0; i < steps; i++ {
currentX := startX + int(float64(i)*moveX)
actions.MoveByOffset(currentX-startX, 0)
time.Sleep(time.Millisecond * time.Duration(100+rand.Intn(50)))
}
actions.Release().Perform()
return nil
}
func main() {
// 初始化代码同上...
getImage(driver, ".yidun_bg-img", "bg.png")
getImage(driver, ".yidun_jigsaw", "puzzle.png")
distance, err := getSlideDistance()
if err != nil {
log.Println(err)
return
}
fmt.Printf("Slide distance: %f\n", distance)
if err := slidePuzzle(driver, distance); err != nil {
log.Println(err)
return
}
time.Sleep(5 * time.Second)
}
更多内容联系q1436423940