深度解析:使用JavaScript识别滑动验证码缺口
滑动验证码是一种常见的网站防护机制。极验和网易易盾是两大知名服务商。用户需要将滑块拖动到验证码右侧的缺口位置,当滑块匹配缺口时,验证通过。自动破解滑动验证码的步骤我们将主要关注如何通过编程自动化识别滑动验证码的缺口位置。基本原理可以使用Op
滑动验证码是一种常见的网站防护机制。极验和网易易盾是两大知名服务商。用户需要将滑块拖动到验证码右侧的缺口位置,当滑块匹配缺口时,验证通过。
自动破解滑动验证码的步骤
我们将主要关注如何通过编程自动化识别滑动验证码的缺口位置。
基本原理
可以使用 OpenCV 实现滑动验证码缺口的识别。输入一张带有缺口的验证码图片,输出缺口的位置(通常为缺口左侧的横坐标)。
示例图片
输入的验证码图片如下:
输出的识别结果如下:
实现步骤
我们通过以下几个步骤,用 OpenCV 进行图像处理来实现缺口识别:
高斯模糊滤波,消除部分噪声
边缘检测,识别滑块的边缘
轮廓筛选,确定缺口位置
准备工作
首先,需要安装 Node.js 和 OpenCV 库。这里我们以 JavaScript 为例,通过 opencv4nodejs 实现缺口识别。
安装 opencv4nodejs
确保已经安装了 Node.js,然后使用以下命令安装 opencv4nodejs:
sh
复制代码
npm install opencv4nodejs
示例代码
javascript
复制代码
const cv = require('opencv4nodejs');
// 读取验证码图片
const imageRaw = cv.imread('captcha.png');
const imageHeight = imageRaw.rows;
const imageWidth = imageRaw.cols;
// 高斯模糊处理
const imageGaussianBlur = imageRaw.gaussianBlur(new cv.Size(5, 5), 0);
// 边缘检测
const imageCanny = imageGaussianBlur.canny(200, 450);
// 轮廓提取
const contours = imageCanny.findContours(cv.RETR_CCOMP, cv.CHAIN_APPROX_SIMPLE);
// 获取阈值方法
const getContourAreaThreshold = (imageWidth, imageHeight) => {
const contourAreaMin = (imageWidth * 0.15) * (imageHeight * 0.25) * 0.8;
const contourAreaMax = (imageWidth * 0.15) * (imageHeight * 0.25) * 1.2;
return [contourAreaMin, contourAreaMax];
};
const getArcLengthThreshold = (imageWidth, imageHeight) => {
const arcLengthMin = ((imageWidth * 0.15) + (imageHeight * 0.25)) * 2 * 0.8;
const arcLengthMax = ((imageWidth * 0.15) + (imageHeight * 0.25)) * 2 * 1.2;
return [arcLengthMin, arcLengthMax];
};
const getOffsetThreshold = (imageWidth) => {
const offsetMin = 0.2 * imageWidth;
const offsetMax = 0.85 * imageWidth;
return [offsetMin, offsetMax];
};
// 轮廓筛选
const [contourAreaMin, contourAreaMax] = getContourAreaThreshold(imageWidth, imageHeight);
const [arcLengthMin, arcLengthMax] = getArcLengthThreshold(imageWidth, imageHeight);
const [offsetMin, offsetMax] = getOffsetThreshold(imageWidth);
let offset = null;
for (let i = 0; i < contours.length; i++) {
const contour = contours[i];
const boundingRect = contour.boundingRect();
const contourArea = contour.area;
const arcLength = contour.arcLength(true);
if (contourArea > contourAreaMin && contourArea < contourAreaMax &&
arcLength > arcLengthMin && arcLength < arcLengthMax &&
boundingRect.x > offsetMin && boundingRect.x < offsetMax) {
imageRaw.drawRectangle(
new cv.Point(boundingRect.x, boundingRect.y),
new cv.Point(boundingRect.x + boundingRect.width, boundingRect.y + boundingRect.height),
new cv.Vec(0, 0, 255),
2
);
offset = boundingRect.x;
}
}
// 保存结果图片
cv.imwrite('image_label.png', imageRaw);
console.log('offset', offset);
代码说明
读取验证码图片:使用 cv.imread 读取图片。
高斯模糊处理:使用 gaussianBlur 进行高斯模糊处理。
边缘检测:使用 canny 进行边缘检测。
轮廓提取:使用 findContours 提取轮廓。
轮廓筛选:通过面积、周长、位置筛选目标轮廓,使用 boundingRect 获取外接矩形,使用 contourArea 计算轮廓面积,使用 arcLength 计算轮廓周长。
结果标注:使用 drawRectangle 标注目标轮廓,并保存结果图片。