OpenCV自动滑块验证(Java版)

前提

爬与防爬就是一场"道高一尺,魔高一丈"的拉力赛,双方都在见招拆招。时至今日,较为常见的防爬手段有手机短信验证、滑块验证、按顺序点击图片验证等。

本文主要介绍滑块验证的应对之法。

验证实现

关键点在于获取滑块到滑动背景缺口图的横向距离,这里通过OpenCV的模板匹配技术matchTemplate,然后再通过selenium的Actions类完成滑动(拖动轨迹算法本文不予过多介绍,请自行查找相关资料)。

java 复制代码
//获取滑块到滑动背景缺口图的横向距离
double slideDistance = getSlideDistance(System.getProperty("user.dir")+"\\slideBlock.png", System.getProperty("user.dir")+"\\slideBg.png");
Actions actions = new Actions(driver);
WebElement dragElement = driver.findElement(By.id("tcaptcha_drag_button"));
//获取style属性值,其中设置了滑块初始偏离值  style=left: 23px;
//需要注意的是网页前端图片和本地图片比例是不同的,需要进行换算
slideDistance = slideDistance * 280 / 680 - 23;
actions.clickAndHold(dragElement).perform();
//根据滑动距离生成滑动轨迹,约定规则:开始慢->中间快->最后慢
List<Integer> moveTrack = getMoveTrack(slideDistance);
for (Integer index : moveTrack) {
    //Thread.sleep(20);
    actions.moveByOffset(index, 0).perform();
}
actions.release().perform();

getSlideDistance方法实现

对滑块进行处理

  1. 灰度化
  2. 去除图片黑边
  3. inRange二值化转黑白图

代码实现:

java 复制代码
// 加载OpenCV本地库
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
//对滑块进行处理
Mat slideBlockMat = Imgcodecs.imread(slideBlockPicPath);
//1、灰度化图片
Imgproc.cvtColor(slideBlockMat, slideBlockMat, Imgproc.COLOR_BGR2GRAY);
//2、去除周围黑边
for (int row = 0; row < slideBlockMat.height(); row++) {
    for (int col = 0; col < slideBlockMat.width(); col++) {
        if (slideBlockMat.get(row, col)[0] == 0) {
            slideBlockMat.put(row, col, 96);
        }
    }
}
//3、inRange二值化转黑白图
Core.inRange(slideBlockMat, Scalar.all(96), Scalar.all(96), slideBlockMat);

对滑动背景图进行处理

  1. 灰度化
  2. 二值化转黑白图

代码如下:

java 复制代码
//对滑动背景图进行处理
Mat slideBgMat = Imgcodecs.imread(slideBgPicPath);
//1、灰度化图片
Imgproc.cvtColor(slideBgMat, slideBgMat, Imgproc.COLOR_BGR2GRAY);
//2、二值化
Imgproc.threshold(slideBgMat, slideBgMat, 127, 255, Imgproc.THRESH_BINARY);
Mat g_result = new Mat();
/*
 * matchTemplate:在模板和输入图像之间寻找匹配,获得匹配结果图像
 * result:保存匹配的结果矩阵
 * TM_CCOEFF_NORMED标准相关匹配算法
 */
Imgproc.matchTemplate(slideBgMat, slideBlockMat, g_result, Imgproc.TM_CCOEFF_NORMED); 
/* minMaxLoc:在给定的结果矩阵中寻找最大和最小值,并给出它们的位置
 * maxLoc最大值
 */
Point matchLocation = Core.minMaxLoc(g_result).maxLoc;
//返回匹配点的横向距离
return matchLocation.x;
相关推荐
爱喝热水的呀哈喽1 分钟前
expand,None索引,permute【pytorch】
人工智能·深度学习
web3探路者5 分钟前
加密货币行业与2024年美国大选
java·大数据·web3·区块链·团队开发·开源软件
为啥不能修改昵称啊9 分钟前
静态数据区,堆,栈
java·jvm·算法
爱吃土豆的程序员14 分钟前
HTTP慢速攻击原理及解决办法
java·http慢速攻击
编程修仙22 分钟前
Java继承练习
java·开发语言·python
bytebeats28 分钟前
Kotlin 注解全面指北
android·java·kotlin
流浪大人32 分钟前
Java实现pdf转图片
java·pdf
宋一诺3338 分钟前
机器学习—推理:做出预测(前向传播)
人工智能·机器学习
AI人H哥会Java40 分钟前
【JAVA】Java基础—基础语法:数据类型(基本数据类型与引用数据类型)
java
路在脚下@1 小时前
IntelliJ IDEA的快捷键
java·ide·intellij-idea