Java + Selenium + OpenCV解决自动化测试中的滑块验证问题

目录
  • 1、滑块验证思路
  • 2、使用OpenCV进行图片解析
    • 2.1 OpenCV引入项目
    • 2.2 实现图片解析,计算所需距离
    • 2.3 算法解析说明
  • 3、Selenium处理滑块滑动
  • 4、最终效果

最近工作过程中,一个常用的被测网站突然增加了滑块验证环节,导致整个自动化项目失效了。

为了解决这个滑块验证问题,在网上查阅了一些资料后,总结并实现了解决方案,现记录如下。

1、滑块验证思路

被测对象的滑块对象长这个样子。相对而言是比较简单的一种形式,需要将左侧的拼图通过下方的滑块进行拖动,嵌入到右侧空槽中,即完成验证。

要自动化完成这个验证过程,关键点就在于确定滑块滑动的距离。

根据上面的分析,验证的关键点在于确定滑块滑动的距离。但是看似简单的一个需求,完成起来却并不简单。

如果使用自然逻辑来分析这个过程,可以拆解如下:

1. 定位到左侧拼图所在的位置,由于拼图的形状和大小固定,那么其实只需要定位其左边边界离背景图片的左侧距离。(实际在本例中,拼图的起始位置也是固定的,节省了不少工夫)

2. 定位到右侧凹槽所在位置,同样其形状和大小是固定的,那么只需要定位其左边边界离背景图片的左侧距离。

3. 用2中探测到的距离减去1中的距离,既是滑块需要被拖动的距离。

要完成上述的探测计算,首先我们想到的是使用元素定位的方法定位到拼图和凹槽的位置。

然而这一想法是不可行的,原因在于这个验证模块是使用两个canvas即画布元素实现的:

拼图和凹槽都是“画”在画布上的,其本身并不是一个页面元素,不能使用元素定位的方法。

因此我们考虑使用图片解析的方法,分析画布图像本身,来确定相应图形的位置。

2、使用OpenCV进行图片解析

这里我们将引入OpenCV库,来帮我完成图片解析过程:

OpenCV是一个基于Apache2.0许可(开源)发行的跨平台计算机视觉和机器学习软件库,可以运行在Linux、Windows、Android和Mac OS操作系统上。

它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。
OpenCV用C++语言编写,它具有C ++,Python,Java和MATLAB接口,并支持Windows,Linux,Android和Mac OS,OpenCV主要倾向于实时视觉应用,并在可用时利用MMX和SSE指令, 如今也提供对于C#、Ch、Ruby,GO的支持。

2.1 OpenCV引入项目

1:下载 OpenCV

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

使用Maven依赖并不能引入正确的OpenCV外部依赖,这里需使用外部

2:工程中添加 jar 包

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

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

3. 新建滑块验证工具类,引入OpenCV动态链接库文件:opencv_java450.dll

public class slideUtil {

    public static String dllPath = "D:\\AutoTest\\src\\main\\resources\\lib\\opencv\\opencv_java450.dll";

    public static void main(String[] args) {

        //getDistance();//调试用的main方法,调用一个getDistance方法,获取拼图和凹槽之间的距离,返回double类型数值。
    }

2.2 实现图片解析,计算所需距离

由于本项目的特点,拼图的形状和位置是固定的,首先我们将拼图和凹槽图片下载到本地,方便后续处理。(其它项目可能出现图片形状不固定的情况,可以直接用selenium实时下载图片,这过程比较简单,因此不赘述)。

下载完的图片如下:

凹槽图片:

拼图图片:

下面直接上代码再做说明:

 public static double getDistance(){

        // 加载OpenCV本地库
        System.load(dllPath);
        //System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
//对拼图图形进行处理,存储为Mat类型①
        Mat slideBlockMat=Imgcodecs.imread("slide_blk.png");//由于本项目的特点,拼图的形状和位置是固定的,因此直接将拼图图片保存到本地进行使用了
//Step1、灰度化图片②
        Imgproc.cvtColor(slideBlockMat,slideBlockMat,Imgproc.COLOR_BGR2GRAY);
        imwrite("cvt_blk.png",slideBlockMat);
//Step2、去除周围黑边
        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);
                }
            }
        }
        imwrite("nsr_blk.png",slideBlockMat);
//Step3、转黑白图
        Core.inRange(slideBlockMat, Scalar.all(96), Scalar.all(96), slideBlockMat);
        imwrite("ezh_blk.png",slideBlockMat);<br>
//对滑动背景图进行处理③
        Mat slideBgMat = Imgcodecs.imread("slide_bg.png");//背景凹槽图片需要动态获取,见下面的解析
//Step1、灰度化图片④
        Imgproc.cvtColor(slideBgMat,slideBgMat,Imgproc.COLOR_BGR2GRAY);
        imwrite("hdh_bg.png",slideBgMat);
//Step2、二值化
        //Core.inRange(slideBgMat, Scalar.all(96), Scalar.all(96), slideBgMat);
        Imgproc.threshold(slideBgMat,slideBgMat,127,255, Imgproc.THRESH_BINARY);
        imwrite("ezh_bg.png",slideBgMat);
        Mat g_result = new Mat();
        /*
         * 将凹槽背景和拼图图形进行匹配⑤
         */
        Imgproc.matchTemplate(slideBgMat,slideBlockMat,g_result, Imgproc.TM_CCOEFF_NORMED);
        Point matchLocation= Core.minMaxLoc(g_result).maxLoc;
//返回匹配点的横向距离
        System.out.println(matchLocation.x);
        return matchLocation.x;
    }

2.3 算法解析说明

①什么是Mat类型:

Mat 是 OpenCV 中用来存储图像信息的内存对象。Mat 对象中除了存储图像的像素数据外,还包括图像的其它属性:宽、高、类型、维度、大小、深度等。可以认为在OpenCV中,一个Mat对象就定义了一个图像。②对于slide_blk.png的处理经过了以下过程:灰度化:

去黑边:

二值化:

最终的目的在于将图形转化为黑白分明的图形,便于后续匹配。

③本项目中,由于背景凹槽图片,凹槽的位置是动态的,所以需要实时动态获取:(如果遇到拼图也需要动态获取,可以同样处理)

WebElement bg_canvas = driver.findElement(slide_ver_bg_by);//元素定位,定位到背景图片

        Object base64 = ((JavascriptExecutor) driver)
                .executeScript("return arguments[0].toDataURL('image/png').substring(21);", bg_canvas);//页面元素转Base64
        String base64Str = base64.toString();
        generateImage(base64Str , "slide_bg.png");// 将base64把字符串装换成图片

④对于slide_bg.png的处理经过了以下过程:

灰度化:

二值化:

这里省略了去黑边这一过程,因为实践发现,经过上述两部后,我们已经能够进行较为准确的图片匹配了。

⑤matchTemplate:在模板和输入图像之间寻找匹配,获得匹配结果图像

esult:保存匹配的结果矩阵

TM_CCOEFF_NORMED标准相关匹配算法

minMaxLoc:在给定的结果矩阵中寻找最大和最小值,并给出它们的位置

3、Selenium处理滑块滑动

Selenium的滑块处理是库里的标准玩法,使用actions类或者javaScript的方式都可以实现,本例采用的是actions类方法:

public void slide_verify(WebDriver driver) throws InterruptedException {

        double  slideDistance = getDistance();//此处就是调用2中的OpenCV计算拼图和凹槽距离
        System.out.println("滑动距离是" + slideDistance);
        WebElement dragElement = driver.findElement(slide_obj_by);//定位到滑块
        Actions actions = new Actions(driver);
        actions.clickAndHold(dragElement);//模拟鼠标动作,按住滑块
        Thread.sleep(300);
<br>//滑动,分两次进行①
        actions.moveByOffset(((int)slideDistance - 11)/2,0);
        Thread.sleep(1000);
        Thread.sleep(500);
        actions.release();
        actions.perform();
    }

①这里进行滑动时,首先滑动距离之所以要减去11,是因为本例中拼图的初始位置固定离整体图形的左边距是11.

分两次滑行并且中间sleep了一个时间,是为了防止全匀速拖动而被识别为机器人。

其它文章中有提到使用比较复杂的拖动轨迹算法,本项目中实践得知,滑动轨迹并没有太重要,分两次拖动就可以了,没必要复杂化。

4、最终效果

最终的滑动效果,因为被测网站的敏感性就不放上来了,最终实现成果是较为理想的。

到此这篇关于Java + Selenium + OpenCV解决自动化测试中的滑块验证的文章就介绍到这了,更多相关Java滑块验证内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 利用Java+Selenium+OpenCV模拟实现网页滑动验证

    目录 一.需求分析 二.模拟步骤 1.使用selenium打开某音网页 2.找到小滑块以及小滑块所在的背景图 3.计算小滑块需要滑动的距离 4.按住小滑块并滑动 三.学习过程中比较棘手的问题 1.截图问题 2.返回结果与实际滑动距离相差太多,甚至无规律可循 3.openCV的下载安装 四.总结 目前很多网页都有滑动验证,目的就是防止不良爬虫扒他们网站的数据,我这次本着学习的目的使用Java和selenium学习解决滑动验证的问题,前前后后花了一周时间(抄代码),终于成功了某音的滑动验证! 效果展

  • 使用java + selenium + OpenCV破解腾讯防水墙滑动验证码功能

    * 验证码地址:https://007.qq.com/online.html * 使用OpenCv模板匹配 * 成功率90%左右 * Java + Selenium + OpenCV 产品样例 来吧!展示! 注意!!! · 在模拟滑动时不能按照相同速度或者过快的速度滑动,需要向人滑动时一样先快后慢,这样才不容易被识别. 模拟滑动代码↓↓↓ /** * 模拟人工移动 * @param driver * @param element页面滑块 * @param distance需要移动距离 */ pu

  • 使用java + selenium + OpenCV破解网易易盾滑动验证码的示例

    网易易盾:dun.163.com * 验证码地址:https://dun.163.com/trial/jigsaw * 使用OpenCv模板匹配 * Java + Selenium + OpenCV 产品样例 接下来就是见证奇迹的时刻! 注意!!! · 在模拟滑动时不能按照相同速度或者过快的速度滑动,需要向人滑动时一样先快后慢,这样才不容易被识别. 模拟滑动代码↓↓↓ /** * 模拟人工移动 * @param driver * @param element页面滑块 * @param dista

  • Java + Selenium + OpenCV解决自动化测试中的滑块验证问题

    目录 1.滑块验证思路 2.使用OpenCV进行图片解析 2.1 OpenCV引入项目 2.2 实现图片解析,计算所需距离 2.3 算法解析说明 3.Selenium处理滑块滑动 4.最终效果 最近工作过程中,一个常用的被测网站突然增加了滑块验证环节,导致整个自动化项目失效了. 为了解决这个滑块验证问题,在网上查阅了一些资料后,总结并实现了解决方案,现记录如下. 1.滑块验证思路 被测对象的滑块对象长这个样子.相对而言是比较简单的一种形式,需要将左侧的拼图通过下方的滑块进行拖动,嵌入到右侧空槽中

  • 使用Vuex解决Vue中的身份验证问题

    传统方式中,许多人使用本地存储,来管理通过客户端验证生成的tokens.一个大问题是如何有更好的方式,来管理验证tokens,从而允许我们来存储更大的用户信息. 这就是Vuex的作用. Vuex为Vue.js应用管理状态..对于应用中所有的组件来说,它被当做中央存储,并用规则确保状态只能以可预见的方式改变. 对于经常检查本地存储来说,听起来是个更好的选择?让我们一起来探索下吧. 建立应用模块 对于这个项目,我们想创建一个使用vuex和vue-router的vue应用.我们会使用vue cli 3

  • Python 网易易盾滑块验证功能的实现

    目录 操作环境 分析 解决方案 使用selenium请求url,并触发滑块验证 获取验证图片并计算滑块距离 生成滑动轨迹 滑动模块 效果 资源下载 记一次 网易易盾滑块验证分析并通过 操作环境 win10 . mac Python3.9 selenium.PIL.numpy.scipy.matplotlib 分析 网易易盾滑块验证,就长下面这个样子 具体验证原理有兴趣的可自行查询官方文档:网易易盾开发文档 话不多少,借助之前写阿里云盾滑块和极验滑块的经验,直接上代码,详细可参考:[python3

  • java使用OpenCV从视频文件中获取帧

    本文实例为大家分享了java使用OpenCV从视频文件中获取帧的具体代码,供大家参考,具体内容如下 实现功能:使用Java获取mp4.mov.avi等视频文件中的图像帧,每秒获取一帧图像,并保存 环境要求:需要安装Opencv,安装FFmpeg,下载javacv包 操作系统:本次实验使用的Ubuntu系统 实验代码 import com.googlecode.javacv.cpp.opencv_highgui; import org.opencv.core.Core; import org.op

  • 分享我的第一次java Selenium自动化测试框架开发过程

    由于公司的开发团队偏向于使用Java技术,而且公司倡导学习开源技术,所以我选择用Java语言来进行Selenium WebDriver的自动化框架开发.由于本人没有Java开发经验,以前虽然学过QTP但从没有接触过Selenium,正好通过这个机会能学习一下自动化测试,同时也学习一下基本的Java开发过程. 一.首先是搭建框架开发环境 按照网上的方法部署eclipse,建立TestAction工程,并Import引用JDK和Selenium-2.44完整包 二.继续引用和安装相关jar包 1.首

  • java selenium处理Iframe中的元素示例

    java selenium  处理Iframe 中的元素 有时候我们定位元素的时候,发现怎么都定位不了. 这时候你需要查一查你要定位的元素是否在iframe里面 阅读目录 什么是iframe iframe 就是HTML 中,用于网页嵌套网页的. 一个网页可以嵌套到另一个网页中,可以嵌套很多层. selenium 中提供了进入iframe 的方法 // 进入 id 叫frameA 的 iframe dr.switchTo().frame("frameA"); // 回到主窗口 dr.sw

  • Java自动化测试中多数据源的切换(实例讲解)

    在做自动化测试时,数据驱动是一个很重要的概念,当数据与脚本分离后,面对茫茫多的数据,管理数据又成了一个大问题,而数据源又可能面对多个,就跟在开发过程中,有时候要连接MYSQL,有时候又要连接SQL SERVER一样,如何做到快速切换?下面的示例中,我们将从一个数据源开始,一步步的演示下去: 一. 用外部文件做数据驱动的基本写法 1.1 我们在做数据驱动时,把数据存储在JAVA的属性文件中:data.properties username=test password=123456 1.2 解析pr

随机推荐