← 返回文章列表

深度解析:使用Go语言破解网易易盾滑动验证码

准备工作安装Go语言和相关库首先,你需要安装Go语言。如果你还没有安装,可以访问Go语言官网进行安装。接下来,我们需要安装Go语言的Selenium客户端库selenium和OpenCV的Go绑定库gocv。在终端中运行以下命令安装依赖:s

准备工作

安装Go语言和相关库

首先,你需要安装Go语言。如果你还没有安装,可以访问Go语言官网进行安装。

接下来,我们需要安装Go语言的Selenium客户端库selenium和OpenCV的Go绑定库gocv。

在终端中运行以下命令安装依赖:

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{}

service, err := selenium.NewSeleniumService(seleniumPath, port, opts...)

if err != nil {

log.Fatalf("Error starting the Selenium server: %v", err)

}

defer service.Stop()

caps := selenium.Capabilities{"browserName": "chrome"}

wd, err := selenium.NewRemote(caps, fmt.Sprintf("http://localhost:%d/wd/hub", port))

if err != nil {

log.Fatalf("Error connecting to the WebDriver: %v", err)

}

defer wd.Quit()

err = wd.Get("https://dun.163.com/trial/jigsaw")

if err != nil {

log.Fatalf("Error loading page: %v", err)

}

time.Sleep(3 * time.Second)

// 后续的验证码处理代码将放在这里

}

2. 获取验证码图片

获取验证码图片并保存到本地,以便使用OpenCV进行图像处理。

go

package main

import (

"fmt"

"io/ioutil"

"log"

"net/http"

"os"

"time"

"github.com/tebeka/selenium"

)

func getImage(wd selenium.WebDriver, selector string, filePath string) error {

elem, err := wd.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()

imgData, err := ioutil.ReadAll(resp.Body)

if err != nil {

return err

}

err = ioutil.WriteFile(filePath, imgData, 0644)

if err != nil {

return err

}

return nil

}

func main() {

opts := []selenium.ServiceOption{}

service, err := selenium.NewSeleniumService(seleniumPath, port, opts...)

if err != nil {

log.Fatalf("Error starting the Selenium server: %v", err)

}

defer service.Stop()

caps := selenium.Capabilities{"browserName": "chrome"}

wd, err := selenium.NewRemote(caps, fmt.Sprintf("http://localhost:%d/wd/hub", port))

if err != nil {

log.Fatalf("Error connecting to the WebDriver: %v", err)

}

defer wd.Quit()

err = wd.Get("https://dun.163.com/trial/jigsaw")

if err != nil {

log.Fatalf("Error loading page: %v", err)

}

time.Sleep(3 * time.Second)

err = getImage(wd, ".yidun_bg-img", "bg.png")

if err != nil {

log.Fatalf("Error getting background image: %v", err)

}

err = getImage(wd, ".yidun_jigsaw", "puzzle.png")

if err != nil {

log.Fatalf("Error getting puzzle image: %v", err)

}

// 后续的验证码处理代码将放在这里

}

3. 使用OpenCV匹配图像

使用OpenCV找到拼图缺口的位置。

go

package main

import (

"fmt"

"image"

"log"

"gocv.io/x/gocv"

)

func getSlideDistance(bgPath, puzzlePath string) (float64, error) {

bgImg := gocv.IMRead(bgPath, gocv.IMReadColor)

if bgImg.Empty() {

return 0, fmt.Errorf("error reading background image")

}

defer bgImg.Close()

puzzleImg := gocv.IMRead(puzzlePath, gocv.IMReadColor)

if puzzleImg.Empty() {

return 0, fmt.Errorf("error reading puzzle image")

}

defer puzzleImg.Close()

result := gocv.NewMat()

defer result.Close()

gocv.MatchTemplate(bgImg, puzzleImg, &result, gocv.TmCcoeffNormed, gocv.NewMat())

_, maxVal, _, maxLoc := gocv.MinMaxLoc(result)

fmt.Printf("Max value: %f, Max location: %v\n", maxVal, maxLoc)

return float64(maxLoc.X), nil

}

func main() {

opts := []selenium.ServiceOption{}

service, err := selenium.NewSeleniumService(seleniumPath, port, opts...)

if err != nil {

log.Fatalf("Error starting the Selenium server: %v", err)

}

defer service.Stop()

caps := selenium.Capabilities{"browserName": "chrome"}

wd, err := selenium.NewRemote(caps, fmt.Sprintf("http://localhost:%d/wd/hub", port))

if err != nil {

log.Fatalf("Error connecting to the WebDriver: %v", err)

}

defer wd.Quit()

err = wd.Get("https://dun.163.com/trial/jigsaw")

if err != nil {

log.Fatalf("Error loading page: %v", err)

}

time.Sleep(3 * time.Second)

err = getImage(wd, ".yidun_bg-img", "bg.png")

if err != nil {

log.Fatalf("Error getting background image: %v", err)

}

err = getImage(wd, ".yidun_jigsaw", "puzzle.png")

if err != nil {

log.Fatalf("Error getting puzzle image: %v", err)

}

distance, err := getSlideDistance("bg.png", "puzzle.png")

if err != nil {

log.Fatalf("Error calculating slide distance: %v", err)

}

fmt.Printf("Slide distance: %f\n", distance)

// 后续的验证码处理代码将放在这里

}

4. 模拟滑动行为

模拟人类滑动行为,以避免被检测为机器人。

go

package main

import (

"fmt"

"log"

"math/rand"

"time"

"github.com/tebeka/selenium"

)

func slidePuzzle(wd selenium.WebDriver, distance float64) error {

slider, err := wd.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

err = wd.MoveToObject(slider, 1, 1)

if err != nil {

return err

}

err = wd.ButtonDown()

if err != nil {

return err

}

steps := 30

moveX := distance / float64(steps)

for i := 0; i < steps; i++ {

currentX := startX + int(moveX*float64(i))

err = wd.MoveTo(currentX, startY)

if err != nil {

return err

}

time.Sleep(time.Millisecond * time.Duration(100+rand.Intn(50)))

}

err = wd.ButtonUp()

if err != nil {

return err

}

return nil

}

func main() {

opts := []selenium.ServiceOption{}

service, err := selenium.NewSeleniumService(seleniumPath, port, opts...)

if err != nil {

log.Fatalf("Error starting the Selenium server: %v", err)

}

defer service.Stop()

caps := selenium.Capabilities{"browserName": "chrome"}

wd, err := selenium.NewRemote(caps, fmt.Sprintf("http://localhost:%d/wd/hub", port))

if err != nil {

log.Fatalf("Error connecting to the WebDriver: %v", err)

}

defer wd.Quit()

err = wd.Get("https://dun.163.com/trial/jigsaw")

if err != nil {

log.Fatalf("Error loading page: %v", err)

}

time.Sleep(3 * time.Second)

err = getImage(wd, ".yidun_bg-img", "bg.png")

if err != nil {

log.Fatalf("Error getting background image: %v", err)

}

err = getImage(wd, ".yidun_jigsaw", "puzzle.png")

if err != nil {

log.Fatalf("Error getting puzzle image: %v", err)

}

distance, err := getSlideDistance("bg.png", "puzzle.png")

if err != nil {

log.Fatalf("Error calculating slide distance: %v", err)

}

fmt.Printf("Slide distance: %f\n", distance)

err = slidePuzzle(wd, distance)

if err != nil {

log.Fatalf("Error sliding puzzle: %v", err)

}

time.Sleep(5 * time.Second)

}