滑动验证码是一种常见的验证码形式,通过拖动滑块将缺失的拼图块对准原图中的空缺位置来验证用户操作。本文将介绍如何使用Go语言中的OpenCV进行模板匹配,并结合Rod实现自动化破解滑动验证码的过程。
所需技术
OpenCV模板匹配:用于识别滑块在背景图中的正确位置。
Go:主要编程语言。
Rod:用于浏览器自动化,模拟用户操作。
破解过程概述
获取验证码图像:
下载背景图和滑块图。
进行必要的图像预处理。
模板匹配:
使用OpenCV的模板匹配算法,计算滑块在背景图中的最佳匹配位置。
模拟滑动:
生成模拟人类滑动的轨迹,避免被识别为机器人。
使用Rod模拟滑动操作。
实现步骤
1. 设置环境
首先,我们需要设置Go语言环境并安装相关的依赖包。
sh
go get -u github.com/go-rod/rod
go get -u gocv.io/x/gocv
2. 获取并预处理验证码图像
编写Go代码,下载验证码的背景图和滑块图,并对图像进行预处理。
go
package main
import (
"gocv.io/x/gocv"
"image"
"io"
"net/http"
"os"
)
func downloadImage(url, filename string) error {
resp, err := http.Get(url)
if err != nil {
return err
}
defer resp.Body.Close()
file, err := os.Create(filename)
if err != nil {
return err
}
defer file.Close()
_, err = io.Copy(file, resp.Body)
return err
}
func preprocessImages(bgPath, sliderPath string) (gocv.Mat, gocv.Mat) {
bgImg := gocv.IMRead(bgPath, gocv.IMReadColor)
sliderImg := gocv.IMRead(sliderPath, gocv.IMReadGrayScale)
return bgImg, sliderImg
}
func main() {
bgURL := "background_image_url"
sliderURL := "slider_image_url"
downloadImage(bgURL, "background.png")
downloadImage(sliderURL, "slider.png")
bgImg, sliderImg := preprocessImages("background.png", "slider.png")
defer bgImg.Close()
defer sliderImg.Close()
// Next steps will be here
}
在上述代码中,我们下载并保存验证码图像,然后将滑块图转换为灰度图进行处理。
3. 模板匹配
使用OpenCV的模板匹配算法来确定滑块在背景图中的正确位置。
func findSliderPosition(bgImg, sliderImg gocv.Mat) int {
result := gocv.NewMat()
defer result.Close()
gocv.MatchTemplate(bgImg, sliderImg, &result, gocv.TmCcoeffNormed, gocv.NewMat())
_, _, _, maxLoc := gocv.MinMaxLoc(result)
return maxLoc.X
}
func main() {
bgURL := "background_image_url"
sliderURL := "slider_image_url"
downloadImage(bgURL, "background.png")
downloadImage(sliderURL, "slider.png")
bgImg, sliderImg := preprocessImages("background.png", "slider.png")
defer bgImg.Close()
defer sliderImg.Close()
sliderPosition := findSliderPosition(bgImg, sliderImg)
println("Slider Position:", sliderPosition)
// Next steps will be here
}
这里我们使用TmCcoeffNormed算法进行匹配,并找到最佳匹配位置的坐标。
4. 模拟滑动操作
通过生成一条模拟人类滑动的轨迹,并使用Rod模拟滑动操作。
package main
import (
"context"
"github.com/go-rod/rod"
"github.com/go-rod/rod/lib/input"
"math"
"math/rand"
"time"
)
func generateTrack(distance int) []int {
var track []int
current := 0
mid := distance * 4 / 5
t := 0.2
v := 0.0
for current < distance {
var a int
if current < mid {
a = 2
} else {
a = -3
}
v0 := v
v = v0 + float64(a)*t
move := v0*t + 0.5*float64(a)*t*t
current += int(math.Round(move))
track = append(track, int(math.Round(move)))
}
return track
}
func main() {
bgURL := "background_image_url"
sliderURL := "slider_image_url"
downloadImage(bgURL, "background.png")
downloadImage(sliderURL, "slider.png")
bgImg, sliderImg := preprocessImages("background.png", "slider.png")
defer bgImg.Close()
defer sliderImg.Close()
sliderPosition := findSliderPosition(bgImg, sliderImg)
println("Slider Position:", sliderPosition)
page := rod.New().MustConnect().MustPage("your_target_website_with_captcha")
page.MustWaitLoad()
slider := page.MustElement("your_slider_css_selector")
box := slider.MustShape().Box()
track := generateTrack(sliderPosition)
ctx := context.Background()
page.Mouse.MustMove(box.X+box.Width/2, box.Y+box.Height/2, 1)
page.Mouse.MustDown(input.Left)
for _, move := range track {
page.Mouse.MustMove(box.X+box.Width/2+float64(move), box.Y+box.Height/2, 1)
time.Sleep(time.Duration(rand.Intn(20)+10) * time.Millisecond)
}
page.Mouse.MustUp(input.Left)
page.MustScreenshot("result.png")
}