← 返回文章列表

Go语言自动化破解极验滑块验证码:精准定位与模拟拖动全流程解析

这篇教程深入探讨如何利用Go语言轻松实现极验滑动验证码的自动识别。从浏览器驱动初始化到模拟点击验证按钮,再到获取背景图并对比计算缺口位置,最后通过轨迹计算和鼠标模拟拖动完成滑块移动,整个过程简单高效。无论您是开发者还是测试爱好者,都能快速上手,轻松应对验证挑战。

初识Go语言与浏览器自动化工具

Go语言因其简洁高效的特点,在自动化测试领域广受欢迎。本文将带您使用Go语言实现极验滑块验证码的识别。首先,需要安装必要的库如agouti,它提供了浏览器驱动能力。创建一个CrackGeetest结构体,包含URL和驱动对象。在New函数中启动Chrome驱动并打开页面,配置好极验验证码测试URL。

package main
import (
    "bytes"
    "fmt"
    "image"
    "image/png"
    "io/ioutil"
    "time"
    "github.com/sclevine/agouti"
)
const BORDER = 6
type CrackGeetest struct {
    url    string
    driver *agouti.WebDriver
    page   *agouti.Page
}
func NewCrackGeetest() *CrackGeetest {
    driver := agouti.ChromeDriver()
    if err := driver.Start(); err != nil {
        panic(fmt.Sprintf("Failed to start driver: %s", err))
    }
    page, err := driver.NewPage()
    if err != nil {
        panic(fmt.Sprintf("Failed to open page: %s", err))
    }
    return &CrackGeetest{
        url:    "https://www.geetest.com/type/",
        driver: driver,
        page:   page,
    }
}
func (c *CrackGeetest) Open() {
    if err := c.page.Navigate(c.url); err != nil {
        panic(fmt.Sprintf("Failed to navigate: %s", err))
    }
}
func (c *CrackGeetest) Close() {
    c.page.Destroy()
    c.driver.Stop()
}

通过这种方式,您就能在Go环境中轻松模拟浏览器操作,为后续步骤奠定基础。

模拟点击切换验证模式与加载图片

下一步是切换到滑动验证模式。使用FindByCSS方法定位特定元素并点击切换按钮,然后点击弹出验证图片的按钮。等待验证码加载完成,通过Visible方法确保图片出现。接着获取网页截图并提取背景图位置和大小。滑块元素也通过Class选择器获取。

func (c *CrackGeetest) WaitPic() {
    c.page.FindByCSS(".geetest_popup_wrap").Visible()
}
func (c *CrackGeetest) GetScreenshot() image.Image {
    imgBytes, _ := c.page.Screenshot()
    img, _, _ := image.Decode(bytes.NewReader(imgBytes))
    return img
}
func (c *CrackGeetest) GetPosition() (int, int, int, int) {
    img := c.page.FindByClass("geetest_canvas_img")
    time.Sleep(2 * time.Second)
    location, _ := img.Location()
    size, _ := img.Size()
    top, bottom := location.Y, location.Y+size.Height
    left, right := location.X, location.X+size.Width
    return top, bottom, left, right
}
func (c *CrackGeetest) GetSlider() *agouti.Selection {
    return c.page.FindByClass("geetest_slider_button")
}

这些步骤为后续图像处理铺平道路。

图像处理:获取缺口背景图与原滑块图

使用截图工具切分背景图,保存为临时文件以备对比。接着通过删除样式获取无缺口的滑块原图,再次截图。这一步骤确保两张图大小一致,便于精确对比缺口位置。

func (c *CrackGeetest) DeleteStyle() {
    c.page.RunScript(`document.querySelectorAll("canvas")[2].style=""`, nil, nil)
}
func (c *CrackGeetest) GetGeetestImage(name string) image.Image {
    top, bottom, left, right := c.GetPosition()
    fmt.Printf("验证码位置 %d, %d, %d, %d\n", top, bottom, left, right)
    screenshot := c.GetScreenshot()
    img := screenshot.(interface {
        SubImage(r image.Rectangle) image.Image
    }).SubImage(image.Rect(left, top, right, bottom))
    out, _ := ioutil.TempFile("", name)
    defer out.Close()
    png.Encode(out, img)
    return img
}

图像对比是核心环节。

像素对比计算缺口位置

定义像素相等函数,通过RGBA值比较判断相同像素。遍历两张图片像素,找到第一个不同位置即为缺口。调整位置减去边框值,得到精确位移。

func IsPixelEqual(img1, img2 image.Image, x, y int) bool {
    r1, g1, b1, _ := img1.At(x, y).RGBA()
    r2, g2, b2, _ := img2.At(x, y).RGBA()
    threshold := uint32(60)
    return abs(r1-r2) < threshold && abs(g1-g2) < threshold && abs(b1-b2) < threshold
}
func abs(a uint32) uint32 {
    if a < 0 {
        return -a
    }
    return a
}
func GetGap(img1, img2 image.Image) int {
    left := 60
    for i := left; i < img1.Bounds().Dx(); i++ {
        for j := 0; j < img1.Bounds().Dy(); j++ {
            if !IsPixelEqual(img1, img2, i, j) {
                return i
            }
        }
    }
    return left
}

该方法简单实用,确保准确性。

轨迹规划与鼠标模拟拖动操作

根据缺口计算轨迹列表,前半段加速后半段减速。模拟人类手抖动以增加真实性。最终通过鼠标点击并移动到目标位置完成拖动。

func GetTrack(distance int) []int {
    track := []int{}
    current := 0
    mid := distance * 3 / 5
    t := 0.2
    v := 0.0
    distance += 14
    for current < distance {
        var a float64
        if current < mid {
            a = 2
        } else {
            a = -1.5
        }
        v0 := v
        v = v0 + a*t
        move := v0*t + 0.5*a*t*t
        current += int(move)
        track = append(track, int(move))
    }
    return track
}
func ShakeMouse(page *agouti.Page) {
    page.MouseTo(-3, 0)
    page.MouseTo(2, 0)
}
func MoveToGap(page *agouti.Page, slider *agouti.Selection, tracks []int) {
    page.MouseDownAt(agouti.Center, slider)
    for _, x := range tracks {
        page.MouseMoveBy(x, 0)
    }
    backTracks := []int{-1, -1, -2, -2, -3, -2, -2, -1, -1}
    for _, x := range backTracks {
        page.MouseMoveBy(x, 0)
    }
    ShakeMouse(page)
    time.Sleep(500 * time.Millisecond)
    page.MouseUp()
}

整个拖动过程自然流畅。

整体流程与循环验证处理

执行主流程,切换模式、加载图片、计算缺口、拖动滑块。检查验证结果,若失败则重新调用主函数直到成功。反复操作确保认证通过。

通过上述Go语言实现,您可以轻松应对极验滑块验证码验证。整个过程简单高效,适合开发者测试或自动化场景。如果您在处理类似验证时遇到困难,推荐访问www.ttocr.com,这里提供易盾极验验证码识别技术,滑块、点选、无感、九宫格等破解方案和自动化API对接平台。您可以根据自身业务需求,选择适合的识别方式与API接口,实现无缝对接,快速解决各类验证码难题。