本文适合新手小白,带你一步步实现自动化通过多缺口滑块验证,助你轻松应对反爬虫难题!
一、什么是滑块验证?
滑块验证是一种常见的反爬虫手段,用户需要按住滑块拖动到指定位置,才能通过验证。多缺口滑块验证则是在背景图上有多个缺口,滑块需要精确拖动到正确的缺口位置。
手动操作很简单,但自动化通过却难倒了不少爬虫新手。本文将带你用 Python + DrissionPage 实现自动化滑块验证。
二、核心思路
- 识别滑块和背景图:获取页面上的滑块和背景图片。
- 识别缺口位置:用 OCR 或图像处理算法识别缺口的准确位置。
- 模拟人类拖动滑块:用代码模拟鼠标按下、移动、释放,完成滑块验证。
三、代码实战
1. 环境准备
- Python 3.8+
- DrissionPage
- pillow(用于图片处理)
- ddddocr(滑块识别)
bash
pip install DrissionPage pillow ddddocr
2. 主要代码结构
2.1 滑块识别核心:recognize_slider_distance
滑块验证的关键是如何准确识别滑块需要移动的距离。下面详细讲解 recognize_slider_distance 的实现原理和代码:
python
import base64
import numpy as np
from PIL import Image
import io
import ddddocr
def base64_decode(str):
return base64.b64decode(str)
def slider_puzzle_qg(p_puzzle_path: str = ''):
"""
将小拼图去除透明边缘,返回处理后的base64图片和位置信息
"""
image = Image.open(p_puzzle_path)
width, height = image.size
pixels = image.load()
_a = 0 # 顶部透明行数
_b = 0 # 有效拼图高度
_c = 0 # 底部透明行数
k = [] # 有效像素
buffered = io.BytesIO()
for x in range(height):
data_pixel = []
for y in range(width):
r, g, b, a = pixels[y, x]
data_pixel += [(r, g, b, a)]
NumPy_data_pixel = np.array(data_pixel)
if np.all(NumPy_data_pixel == 0):
if _b == 0:
_a += 1
else:
if _c == 0:
new_image = Image.new('RGBA', (width, _b), color=(0, 0, 0, 0))
new_image.putdata(k)
new_image.save(buffered, format="PNG")
_c += 1
else:
_b += 1
k += data_pixel
return {
'最顶层-顶层距离': _a,
'中间层-拼图的高度': _b,
'最底层-底层距离': _c,
'base64': base64.b64encode(buffered.getvalue()).decode()
}
def background_cutting(b_puzzle_path: str = '', b_size_h: int = 0, p_size_h: int = 0):
"""
按小拼图的高度切割背景图,返回base64
"""
image = Image.open(b_puzzle_path)
width, height = image.size
left, right = 0, width
top, bottom = b_size_h, b_size_h + p_size_h
cropped_image = image.crop((left, top, right, bottom))
buffered = io.BytesIO()
cropped_image.save(buffered, format="PNG")
return {'base64': base64.b64encode(buffered.getvalue()).decode()}
def recognize_slider_distance(xiaopintu_path, beijingtu_path):
"""
识别滑块需要移动的距离
:param xiaopintu_path: 小拼图路径
:param beijingtu_path: 背景图路径
:return: 滑动距离
"""
det = ddddocr.DdddOcr(det=False, ocr=False, show_ad=False)
xiaopintu_data = slider_puzzle_qg(p_puzzle_path=xiaopintu_path)
beijingtu_data = background_cutting(b_puzzle_path=beijingtu_path, b_size_h=xiaopintu_data['最顶层-顶层距离'],
p_size_h=xiaopintu_data['中间层-拼图的高度'])
res1 = det.slide_match(base64_decode(beijingtu_data['base64']), base64_decode(xiaopintu_data['base64']),
simple_target=True)
res1 = res1['target'][0]
# 为了更像人类操作,可以加一点偏移
res = res1 * 1.1 - 4
return res
原理说明:
- 先用
slider_puzzle_qg
去除小拼图的透明边缘,获得有效区域和高度。 - 用
background_cutting
按小拼图的高度切割背景图,获得滑道。 - 用 ddddocr 的
slide_match
方法,计算小拼图在滑道中的最佳匹配位置(即缺口横坐标)。 - 最后加一点偏移,模拟人类误差,防止被反爬虫检测。
2.2 登录与滑块拖动
下面是完整的登录与滑块拖动自动化代码示例,适合新手理解:
python
import random
import time
import base64
from DrissionPage import Chromium, ChromiumOptions
from utils.ocr_util import recognize_slider_distance # 上文已详细讲解
from service.logger import logger
# 创建浏览器实例
co = ChromiumOptions().set_browser_path(r'C:\Path\To\chrome.exe')
tab = Chromium().latest_tab
def base64_decode(data):
return base64.b64decode(data + '==')
def login_with_slider(tab, username, password):
try:
# 1. 打开登录页面(URL已脱敏)
tab.get('https://your-domain.com/login')
# 2. 输入账号密码
username_ele = tab.ele('@@tag()=input@@placeholder=请输入账号')
password_ele = tab.ele('@@tag()=input@@placeholder=请输入密码')
username_ele.input(username)
password_ele.input(password)
# 3. 点击登录按钮
login_button = tab.ele('@@tag()=span@@text():登 录')
login_button.click(by_js=True)
# 4. 获取滑块和背景图片
background_image_ele = tab.ele('@@tag()=div@@class=verify-img-panel').ele('@@tag()=img')
gap_image_ele = tab.ele('@@tag()=div@@class=verify-sub-block').ele('@@tag()=img')
xiaopintu_data = gap_image_ele.attr('src').split("data:image/png;base64,")[-1]
background_img_data = background_image_ele.attr('src').split("data:image/png;base64,")[-1]
with open('beijingtu.png', 'wb') as f:
f.write(base64_decode(background_img_data))
with open('xiaopintu.png', 'wb') as f:
f.write(base64_decode(xiaopintu_data))
# 5. 识别滑块需要移动的距离
distance = recognize_slider_distance(xiaopintu_path="xiaopintu.png", beijingtu_path="beijingtu.png")
tab.wait.ele_displayed('@@tag()=div@@class=verify-move-block', timeout=10)
slider = tab.ele('@@tag()=div@@class=verify-move-block').wait.clickable(timeout=10)
if not slider:
logger.error('未找到滑块元素,请检查类名或页面结构')
return False
else:
tab.run_js('arguments[0].style.border="2px solid red"', slider)
logger.info(' 找到滑块元素,开始滑动')
# 6. 获取滑块中心点坐标
slider_rect = tab.run_js('''
const rect = arguments[0].getBoundingClientRect();
return {
x: rect.x + rect.width / 2,
y: rect.y + rect.height / 2
}
''', slider)
try:
# 7. 用 JS 模拟鼠标事件拖动滑块
tab.run_js('''
function simulateMouseEvent(element, eventType, x, y) {
const event = new MouseEvent(eventType, {
view: window,
bubbles: true,
cancelable: true,
clientX: x,
clientY: y
});
element.dispatchEvent(event);
}
const slider = arguments[0];
const startX = arguments[1];
const startY = arguments[2];
const distance = arguments[3];
simulateMouseEvent(slider, 'mousedown', startX, startY);
const segments = 5;
const segmentDistance = distance / segments;
let currentX = startX;
for (let i = 0; i < segments; i++) {
currentX += segmentDistance;
simulateMouseEvent(slider, 'mousemove', currentX, startY);
}
currentX -= 5;
simulateMouseEvent(slider, 'mousemove', currentX, startY);
simulateMouseEvent(slider, 'mouseup', currentX, startY);
''', slider, slider_rect['x'], slider_rect['y'], distance)
logger.info(' 滑动操作已发送')
time.sleep(1)
except Exception as e:
logger.error(f' 滑动出错: {e}')
return False
# 8. 后续验证、UKey等操作略
return True
except Exception as e:
logger.error(f"登录失败,错误信息:{e}")
return False
代码说明:
- 步骤1-3:自动化输入账号、密码并点击登录。
- 步骤4:获取滑块和背景图片,保存为本地文件。
- 步骤5:调用
recognize_slider_distance
识别滑块需要移动的距离。 - 步骤6:获取滑块元素的中心点坐标。
- 步骤7:用 JavaScript 分段模拟鼠标拖动滑块,模拟人类操作。此处也可以使用drisionpage操作元素例如:
bash
# 向右移动鼠标
# tab_.actions.right(distance - 10)
time.sleep(0.05)
# tab_.actions.right(10)
- 步骤8:后续如UKey验证等可根据实际需求补充。
3. 关键技术点说明
- 图片识别 :
recognize_slider_distance
利用 ddddocr 的滑块识别能力,极大简化了滑块距离的计算。 - 图片预处理:去除透明边缘、切割滑道,是提升识别准确率的关键。
- JS 模拟鼠标事件 :直接用 JS 触发
mousedown
、mousemove
、mouseup
,比传统动作链更容易绕过部分反爬虫。 - 分段移动:模拟人手抖动,分多段移动更像真人。
- 异常处理:每一步都要加 try/except,方便调试。
四、常见问题与排查
- 滑块没动?
- 检查元素选择器是否准确。
- 检查 JS 事件是否被页面拦截。
- 尝试加大分段数,或调整每段距离。
- 识别距离不准?
- 检查图片保存是否完整。
- 调整识别算法参数。
- 检查小拼图和背景图的预处理是否正确。
- 验证失败?
- 检查是否有额外的行为验证(如轨迹分析、行为分析)。
- 尝试加大拖动时间,模拟更慢的拖动。
五、总结
自动化通过多缺口滑块验证并不神秘,关键在于:
- 正确识别滑块和缺口位置(图片预处理+滑块识别)
- 用 JS 或动作链模拟真实拖动
- 多调试、多尝试,遇到问题多看日志
希望这篇教程能帮你迈出自动化滑块验证的第一步!
温馨提示:请勿将本教程用于非法用途,合理合规使用自动化技术。