Web自动化大神操作:如何用OpenCV 破解滑块验证码?

验证码作为一种安全机制,可以有效防止暴力破解密码、发帖、灌水、刷票等,大家在做 Web 自动化的时候应该有碰到验证码这个难题,一般我们可以和开发沟通请求他们的帮助:去掉验证码或者设置一个万能验证码,而如果开发不帮忙我们该如何去解决呢?

本篇文章以 Java 语言为例教你怎么破解验证码。

现在大多数网址会采用滑块验证码的方式,下面以腾讯的滑块验证码为例,先来看看破解的效果:

Web自动化大神操作:如何用OpenCV 破解滑块验证码?

要破解滑块验证码,我们一般采取的思路如下:

  • 获取滑块到背景缺口图的距离
  • 通过 selenium 的 Actions 类完成滑动

关键点就在于如何获取滑块到背景缺口图的距离,现在主流的方案是通过 OpenCV(Open Source Computer Vision Library)开源计算机视觉库来处理,openCV 有非常多图像处理方法,其是通过 C/C++ 开发的,但是对外有提供 Java,Python 的接口,所以不管是 Python 还是 Java 我们都可以使用 openCV 进行图像处理。

环境准备

Step1:下载 OpenCV

进入到官网
https://opencv.org/releases/ 下载对应系统的 openCV 软件包,之后解压

Step2:配置环境变量

进入到 opencv -> build ->x64 ->vc15 ->bin 目录,将路径复制追加到 Path 环境变量中

Web自动化大神操作:如何用OpenCV 破解滑块验证码?

Step3:Intellij 工程中添加 jar 包

Intellij 中选择 File -> Project Structure -> Modules -> Dependencies

点击 add -> JARS or directories... 选择

D:\software\opencv\build\java\opencv-450.jar 文件

Web自动化大神操作:如何用OpenCV 破解滑块验证码?

验证码破解实现

首先我们通过 selenium 进入到验证码页面(以 QQ 空间为例)

//设置chromeDriver识别路径

System.setProperty("webdriver.chrome.driver","src/test/resources/chromedriver.exe");

driver = new ChromeDriver();

driver.get("https://qzone.qq.com/");

driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

//切换登录页面所在iframe

WebElement loginFrame =driver.findElement(By.id("login_frame"));

driver.switchTo().frame(loginFrame);

driver.findElement(By.id("switcher_plogin")).click();

driver.findElement(By.id("u")).sendKeys("362715381");

driver.findElement(By.id("p")).sendKeys("1234r2we");

driver.findElement(By.id("login_button")).click();

进入到验证码界面后,我们仔细观察会发现:滑块和背景是两张分开的图片,src 属性中保存的即为图片 URL 地址,所以我们可以通过 URL 将两者下载到本地

Web自动化大神操作:如何用OpenCV 破解滑块验证码?

//切换到验证码所在的iframe

WebElementtcaptchaFrame=driver.findElement(By.id("tcaptcha_iframe"));

driver.switchTo().frame(tcaptchaFrame);

//定位滑块图片

WebElementslideBlock= driver.findElement(By.id("slideBlock"));

//定位验证码背景图

WebElementslideBg=driver.findElement(By.id("slideBg"));

//获取图片Url链接

StringslideBlockUrl=slideBlock.getAttribute("src");

String slideBgUrl = slideBg.getAttribute("src");

//下载对应图片

System.out.println("图片下载开始...");

downloadImg(slideBlockUrl, "slideBlock.png");

downloadImg(slideBgUrl, "slideBg.png");

关键点在于获取滑块到滑动背景缺口图的横向距离,这里通过 OpenCV 的模板匹配技术 matchTemplate

然后再通过 selenium 的 Actions 类完成滑动,在滑动的时候需要注意不能直接从开始点滑到终止点(有些网站会判定脚本操作),其中 getMoveTrack 用于获取滑动轨迹,控制每阶段的滑动速度

//获取滑块到滑动背景缺口图的横向距离

double slideDistance=getSlideDistance(System.getProperty("user.dir")+"\\slideBlock.png",System.getProperty("user.dir")+"\\slideBg.png");

Actions actions = new Actions(driver);

WebElementdragElement=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 二值化转黑白图

效果如下:

Web自动化大神操作:如何用OpenCV 破解滑块验证码?

代码实现:

// 加载OpenCV本地库

System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

//对滑块进行处理

MatslideBlockMat=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. 二值化转黑白图

Web自动化大神操作:如何用OpenCV 破解滑块验证码?

代码如下:

//对滑动背景图进行处理

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;

需要注意的是运行时需要指定 library 路径,不然会报如下错误:

java.lang.UnsatisfiedLinkError: no opencv_java450 in java.library.path

选择 Edit Configuration -> VM options 中添加:

-Djava.library.path=D:\software\opencv\build\java\x64

Web自动化大神操作:如何用OpenCV 破解滑块验证码?

推荐一个软件测试学习交流群:785128166,群里有分享的视频,面试指导,测试资料,还有思维导图、群里有视频,都是干货的,你可以下载来看。主要分享测试基础、接口测试、性能测试、自动化测试、TestOps架构、Jmeter、LoadRunner、Fiddler、MySql、Linux、简历优化、面试技巧以及大型测试项目实战视频资料。合理利用自己每一分每一秒的时间来学习提升自己,不要再用"没有时间“来掩饰自己思想上的懒惰!趁年轻,使劲拼,给未来的自己一个交代!

公众号:程序员二黑, 关注后免费领取海量学习资料。

好东西要和朋友一起分享哦
 

猜你喜欢

转载自blog.csdn.net/m0_52668874/article/details/114412929