本教程将展示如何使用V语言模拟人类行为,破解极验滑动验证码。我们将通过网页截图、图像处理和模拟鼠标操作来实现这个过程。
准备工作
首先,确保你的系统上安装了V编译器和相应的依赖库,如Selenium和Pillow。
初始化
我们需要定义一个类来初始化Selenium对象并配置相关参数。
v
module main
import time
import selenium { WebDriver, WebElement, by, keys, ActionChains }
import os
const (
border = 6
)
struct CrackGeetest {
url string
browser &WebDriver
}
fn new_crack_geetest() CrackGeetest {
browser := selenium.chrome_driver()
return CrackGeetest{
url: 'https://www.geetest.com/type/',
browser: browser
}
}
fn (cg &CrackGeetest) open() {
cg.browser.get(cg.url)
}
fn (cg &CrackGeetest) close() {
cg.browser.close()
cg.browser.quit()
}
模拟点击
接下来,我们需要模拟点击切换到滑动验证并显示验证界面。
v
fn (cg &CrackGeetest) change_to_slide() &WebElement {
huadong := cg.browser.find_element(by.css_selector('.products-content ul > li:nth-child(2)'))
return huadong
}
fn (cg &CrackGeetest) get_geetest_button() &WebElement {
button := cg.browser.find_element(by.css_selector('.geetest_radar_tip'))
return button
}
获取背景图
我们需要等待验证码加载完成,然后获取网页截图,并获取验证背景图的位置及大小参数。
v
fn (cg &CrackGeetest) wait_pic() {
cg.browser.wait(10).until(fn (browser &WebDriver) bool {
return browser.find_element(by.css_selector('.geetest_popup_wrap')).is_displayed()
})
}
fn (cg &CrackGeetest) get_screenshot() os.File {
screenshot := cg.browser.screenshot_as_png()
return screenshot
}
fn (cg &CrackGeetest) get_position() (int, int, int, int) {
img := cg.browser.find_element(by.class_name('geetest_canvas_img'))
time.sleep(2)
location := img.location()
size := img.size()
top := location.y
bottom := location.y + size.height
left := location.x
right := location.x + size.width
return top, bottom, left, right
}
删除样式以获取无缺口图像
我们可以通过执行JavaScript脚本删除样式以获取无缺口的原图。
v
fn (cg &CrackGeetest) delete_style() {
js := 'document.querySelectorAll("canvas")[2].style=""'
cg.browser.execute_script(js)
}
识别缺口
对比带缺口和无缺口的两张图,找到缺口位置。
v
fn is_pixel_equal(img1 os.File, img2 os.File, x int, y int) bool {
pix1 := img1.pixel_at(x, y)
pix2 := img2.pixel_at(x, y)
threshold := 60
return abs(pix1.r - pix2.r) < threshold && abs(pix1.g - pix2.g) < threshold && abs(pix1.b - pix2.b) < threshold
}
fn get_gap(img1 os.File, img2 os.File) int {
left := 60
for i := left; i < img1.width(); i++ {
for j := 0; j < img1.height(); j++ {
if !is_pixel_equal(img1, img2, i, j) {
return i
}
}
}
return left
}
模拟拖动
根据计算出的距离,模拟拖动滑块。
v
fn get_track(distance int) []int {
mut track := []int{}
mut current := 0
mid := distance * 3 / 5
t := 0.2
mut v := 0
distance += 14
for current < distance {
a := if current < mid { 2 } else { -1.5 }
v0 := v
v = v0 + int(a * t)
move := v0 * int(t) + int(1 / 2 * a * t * t)
current += move
track << move
}
return track
}
fn (cg &CrackGeetest) move_to_gap(slider &WebElement, tracks []int) {
back_tracks := [-1, -1, -2, -2, -3, -2, -2, -1, -1]
actions := ActionChains(cg.browser)
actions.click_and_hold(slider).perform()
for x in tracks {
actions.move_by_offset(x, 0).perform()
}
for x in back_tracks {
actions.move_by_offset(x, 0).perform()
}
actions.release().perform()
}
主程序
整合以上步骤,编写主程序实现验证码破解。
v
fn (cg &CrackGeetest) crack() {
cg.open()
s_button := cg.change_to_slide()
s_button.click()
g_button := cg.get_geetest_button()
g_button.click()
cg.wait_pic()
slider := cg.browser.find_element(by.class_name('geetest_slider_button'))
image1 := cg.get_screenshot()
cg.delete_style()
image2 := cg.get_screenshot()
gap := get_gap(image1, image2)
gap -= border
track := get_track(gap)
cg.move_to_gap(slider, track)
success := cg.browser.wait(10).until(fn (browser &WebDriver) bool {
return browser.find_element(by.class_name('geetest_success_radar_tip_content')).text() == '验证成功'
})
if success {
println('验证成功')
} else {
println('验证失败,重试中...')
cg.crack()
}
time.sleep(5)
cg.close()
}
fn main() {
mut crack := new_crack_geetest()
crack.crack()
}