滑块验证码是一种常见的验证方式,用于防止自动化脚本的操作。本文使用Eiffel语言来实现一个滑块验证码破解程序,通过模拟用户行为,获取图片、去除黑边、计算缺口位置,并最终模拟滑动行为完成验证。
获取验证码图片
首先,我们需要获取滑块验证码中的背景图片和带缺口的滑块图片。以下代码展示了如何从网页中提取这些图片并保存到本地。
eiffel
class
CAPTCHA_SLIDER
create
make
feature
driver: WEBDRIVER
wait: WAIT
make
-- 创建浏览器并打开测试网站
do
create driver
driver.launch("chrome")
driver.get("http://dun.163.com/trial/jigsaw")
wait := driver.create_wait(20)
end
get_images (target_img, template_img: STRING)
-- 获取滑块和背景图片并保存
local
target_link, template_link: STRING
target_image, template_image: IMAGE
do
target_link := wait.until_element((By.CLASS_NAME, "yidun_bg-img")).attribute("src")
template_link := wait.until_element((By.CLASS_NAME, "yidun_jigsaw")).attribute("src")
target_image := Image.from_url(target_link)
template_image := Image.from_url(template_link)
target_image.save(target_img)
template_image.save(template_img)
end
end
去除黑边
滑块验证码中的滑块图片可能有一些黑边,这会影响后续的图像匹配。我们使用以下代码进行图像的边缘裁剪,去除黑色区域。
eiffel
feature
remove_black_edges (image_path: STRING): IMAGE
-- 去除图片中的黑边
local
image, binary_image: IMAGE
x, y, left, right, top, bottom: INTEGER
do
image := Image.read(image_path)
binary_image := image.convert_to_gray().threshold(15, 255)
left := binary_image.left_bound()
right := binary_image.right_bound()
top := binary_image.top_bound()
bottom := binary_image.bottom_bound()
Result := image.crop(left, right, top, bottom)
end
end
计算缺口位置
为了找到滑块缺口的位置,我们使用模板匹配算法进行图像对比。
eiffel
feature
find_gap_position (target_img, template_img: STRING): INTEGER
-- 通过模板匹配算法查找缺口位置
local
target, template: IMAGE
result: MATRIX
do
target := Image.read(target_img).convert_to_gray()
template := remove_black_edges(template_img)
result := target.match_template(template)
Result := result.best_match_position()
end
end
模拟滑动
滑块验证码的最后一步是模拟用户的滑动行为。我们通过编写一个函数,生成带有加速和减速效果的滑动轨迹,然后在网页中模拟滑动动作。
eiffel
feature
simulate_slide (distance: INTEGER)
-- 模拟滑块的滑动动作
local
slider: ELEMENT
tracks: LIST [INTEGER]
do
slider := wait.until_element_clickable((By.CLASS_NAME, "yidun_slider"))
tracks := calculate_tracks(distance)
driver.click_and_hold(slider)
across
tracks as t更多内容联系1436423940
loop
driver.move_by_offset(t.item, 0)
driver.pause(50)
end
driver.release()
end
calculate_tracks (distance: INTEGER): LIST [INTEGER]
-- 生成滑动轨迹
local
t, offset: REAL
track: LIST [INTEGER]
do
from
t := 0.0
create track.make
until
t > 1.0
loop
offset := ease_out_quart(t) * distance
track.extend(offset)
t := t + 0.1
end
track.extend([-3, -2, -1])
Result := track
end
ease_out_quart (x: REAL): REAL
-- 四次方缓动函数
do
Result := 1.0 - (1.0 - x) ^ 4
end
end