Selenium实战【滑动验证码破解】【JAVA爬虫】

news2025/4/7 3:29:52

简介

本文主要讲解,利用之前所学到的java selenium如何实战操作,浏览器控制鼠标,模拟人工操作滑动验证码。这里需要用javacv 的代码知识,用于计算图像中滑块需要移动的距离。

实战

目标网站:

https://dun.163.com/trial/jigsaw

操作流程:

    • 找到目标

  • 这里我们需要使用selenium库来模拟操作浏览器,可以通过pip install selenium安装它,同时需要下载对应浏览器版本的webdriver来辅助控制电脑,这里就不详细讲解了,直接看操作流程:


import cn.hutool.http.HttpUtil;
import lombok.extern.slf4j.Slf4j;
import org.bytedeco.javacpp.DoublePointer;
import org.bytedeco.opencv.global.opencv_core;
import org.bytedeco.opencv.global.opencv_imgcodecs;
import org.bytedeco.opencv.global.opencv_imgproc;
import org.bytedeco.opencv.opencv_core.Mat;
import org.bytedeco.opencv.opencv_core.Point;
import org.bytedeco.opencv.opencv_core.Scalar;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.interactions.Actions;

import java.io.*;
import java.util.concurrent.TimeUnit;

@Slf4j
public class SwipeCaptcha2 {

    private final static String webDriver = "webdriver.chrome.driver";
    private final static String webDriverPath ="E:\\chromedriver\\chromedriver.exe";

    public static void main(String[] args) throws IOException, InterruptedException {
        System.setProperty(webDriver, webDriverPath);
        WebDriver driver= new ChromeDriver();
        driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
        driver.get("https://dun.163.com/trial/jigsaw");
        //浏览器最大化
        driver.manage().window().maximize();
        //滑块按钮
        WebElement sliderBtn=driver.findElement(By.className("yidun_slider"));
        //点击触发滑块拼图
        sliderBtn.click();
        Thread.sleep(500);
     }
}
  • 通过上面的流程找到验证码的位置,开始获取验证码图片

    • 下载验证码图片

从网页中,我们可以看出这是两张图片:

  • 现在需要把这两张图片下载到本地文件

           
           //获取两张图片的下载链接
            WebElement bgImg=driver.findElement(By.className("yidun_bg-img"));
            WebElement sliderImg=driver.findElement(By.className("yidun_jigsaw"));
            String bgImgSrc=bgImg.getAttribute("src");
            String sliderImgSrc=sliderImg.getAttribute("src");
            Thread.sleep(500);

            //下载操作
            String bgImage="E:\\screenshot\\bj.jpg";
            String sliderImage="E:\\screenshot\\slider.png";
            HttpUtil.downloadFile(bgImgSrc,bgImage);
            HttpUtil.downloadFile(sliderImgSrc,sliderImage);
    • 验证码图像识别

3.1、图像转黑白图片

        //1.从本地读取背景原图,灰度处理
        Mat sliderMat = opencv_imgcodecs.imread(sliderImage, opencv_imgcodecs.IMREAD_GRAYSCALE);
        Mat bgMat = opencv_imgcodecs.imread(bgImage , opencv_imgcodecs.IMREAD_GRAYSCALE);
        //2.二值化转黑白图
        opencv_imgproc.threshold(sliderMat,sliderMat,127,255, opencv_imgproc.THRESH_BINARY);
        opencv_imgproc.threshold(bgMat,bgMat,127,255, opencv_imgproc.THRESH_BINARY);
        //保存为黑白图片
        opencv_imgcodecs.imwrite("E:\\screenshot\\slider_black.png",sliderMat);
        opencv_imgcodecs.imwrite("E:\\screenshot\\bg_black.jpg",bgMat);
  • 转成只有黑和白的像素图片,方便javacv识别匹配位置。

3.2 识别图像位置

     //匹配小图在大图中的位置  用标准模式去比较 然后把返回结果给result
        opencv_imgproc.matchTemplate(sliderMat, bgMat, result, opencv_imgproc.TM_CCORR_NORMED);
        opencv_core.normalize(result, result, 0, 1, opencv_core.NORM_MINMAX, -1, new Mat());
        DoublePointer pointer = new DoublePointer(new double[2]);
        org.bytedeco.opencv.opencv_core.Point maxLoc = new org.bytedeco.opencv.opencv_core.Point();
        //获取匹配结果坐标
        opencv_core.minMaxLoc(result, null, pointer, null, maxLoc, null);
        //在图上做标记
        opencv_imgproc.rectangle(sliderMat, maxLoc,
                new Point(maxLoc.x() + bgMat.cols(), maxLoc.y() + bgMat.rows()),
                new Scalar(0, 255, 0,1));
        System.out.println(maxLoc.x()+","+maxLoc.y()+"  x-y="+(maxLoc.x()-maxLoc.y()));

4.拖动滑块

4.1、控制滑块滑动

Actions actions = new Actions(driver);
actions.clickAndHold(sliderBtn).perform();
actions.moveByOffset(moveDist, 0).perform();
Thread.sleep(200);
actions.release().perform();

4.2、验证是否滑动成功

  • 当验证通过后,滑动底的部会出现“对勾”,如图:

  • 可以通过检查这个“对勾”判断是否验证成功,如果第一次验证失败,可以继续验证,直到成功为止!

isExistElement(driver,By.xpath("//div[contains(@class,'yidun--success')]"))
/**
     * 判断某个元素是否存在
     */
    public static boolean isExistElement(WebDriver webDriver, By by) {
        try {
            webDriver.findElement(by);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

代码汇总:


import cn.hutool.http.HttpUtil;
import lombok.extern.slf4j.Slf4j;
import org.bytedeco.javacpp.DoublePointer;
import org.bytedeco.opencv.global.opencv_core;
import org.bytedeco.opencv.global.opencv_imgcodecs;
import org.bytedeco.opencv.global.opencv_imgproc;
import org.bytedeco.opencv.opencv_core.Mat;
import org.bytedeco.opencv.opencv_core.Point;
import org.bytedeco.opencv.opencv_core.Scalar;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.interactions.Actions;

import java.io.*;
import java.util.concurrent.TimeUnit;

@Slf4j
public class SwipeCaptcha2 {

    private final static String webDriver = "webdriver.chrome.driver";
    private final static String webDriverPath ="E:\\chromedriver\\chromedriver.exe";

    public static void main(String[] args) throws IOException, InterruptedException {
        System.setProperty(webDriver, webDriverPath);
        WebDriver driver= new ChromeDriver();
        driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
        driver.get("https://dun.163.com/trial/jigsaw");
        //浏览器最大化
        driver.manage().window().maximize();
        //滑块按钮
        WebElement sliderBtn=driver.findElement(By.className("yidun_slider"));
        //点击触发滑块拼图
        sliderBtn.click();
        Thread.sleep(500);
        Actions actions = new Actions(driver);
        String bgImage="E:\\screenshot\\bj.jpg";
        String sliderImage="E:\\screenshot\\slider.png";
        for (int i = 0; i < 10; i++) {
            WebElement bgImg=driver.findElement(By.className("yidun_bg-img"));
            WebElement sliderImg=driver.findElement(By.className("yidun_jigsaw"));
            String bgImgSrc=bgImg.getAttribute("src");
            String sliderImgSrc=sliderImg.getAttribute("src");
            Thread.sleep(500);
            //下载操作
            HttpUtil.downloadFile(bgImgSrc,bgImage);
            HttpUtil.downloadFile(sliderImgSrc,sliderImage);
            double slideDistance=getMoveDist(bgImage,sliderImage);
            //修正误差
            slideDistance = slideDistance +10;
            actions.clickAndHold(sliderBtn).perform();
            //循环一点点的移动
            for(int j=moveDist;j>=1;) {
                int move=1;
                if(j>1){
                    move= RandomUtil.randomInt(1,j);
                    actions.moveByOffset(move, 0).perform();
                }else {
                    actions.moveByOffset(move, 0).perform();
                }
                j=j-move;
            }
            Thread.sleep(200);
            actions.release().perform();
            Thread.sleep(1000);
            if(isExistElement(driver,By.xpath("//div[contains(@class,'yidun--success')]"))){
                break;
            }
        }
    }

    /**
     * 计算滑块移动距离(经过反复测试只有在颜色比较深的时候,才能计算转圈)
     *
     */
    private static double getMoveDist(String bgImage,String sliderImage){
        //1.从本地读取背景原图,灰度处理
        Mat sliderMat = opencv_imgcodecs.imread(sliderImage, opencv_imgcodecs.IMREAD_GRAYSCALE);
        Mat bgMat = opencv_imgcodecs.imread(bgImage , opencv_imgcodecs.IMREAD_GRAYSCALE);
        //2.二值化转黑白图
        opencv_imgproc.threshold(sliderMat,sliderMat,127,255, opencv_imgproc.THRESH_BINARY);
        opencv_imgproc.threshold(bgMat,bgMat,127,255, opencv_imgproc.THRESH_BINARY);
        //保存为黑白图片
        //opencv_imgcodecs.imwrite("E:\\screenshot\\slider_black.png",sliderMat);
        //opencv_imgcodecs.imwrite("E:\\screenshot\\bg_black.jpg",bgMat);
        Mat result = new Mat();
        //3.匹配小图在大图中的位置  用标准模式去比较 然后把返回结果给result
        opencv_imgproc.matchTemplate(sliderMat, bgMat, result, opencv_imgproc.TM_CCORR_NORMED);
        opencv_core.normalize(result, result, 0, 1, opencv_core.NORM_MINMAX, -1, new Mat());
        DoublePointer pointer = new DoublePointer(new double[2]);
        org.bytedeco.opencv.opencv_core.Point maxLoc = new org.bytedeco.opencv.opencv_core.Point();
        //4.获取匹配结果坐标
        opencv_core.minMaxLoc(result, null, pointer, null, maxLoc, null);
        //5.在图上做标记
        opencv_imgproc.rectangle(sliderMat, maxLoc,
                new Point(maxLoc.x() + bgMat.cols(), maxLoc.y() + bgMat.rows()),
                new Scalar(0, 255, 0,1));
        System.out.println("二维中坐标的位置:"+maxLoc.x()+","+maxLoc.y());
        return maxLoc.x();
    }

    /**
     * 判断某个元素是否存在
     */
    public static boolean isExistElement(WebDriver webDriver, By by) {
        try {
            webDriver.findElement(by);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}

  • 未经本人同意,文章禁止转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/155865.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Java入门】Java注释和关键字

✅作者简介&#xff1a;CSDN内容合伙人、阿里云专家博主、51CTO专家博主、新星计划第三季python赛道Top1&#x1f3c6; &#x1f4c3;个人主页&#xff1a;hacker707的csdn博客 &#x1f525;系列专栏&#xff1a;Java入门 &#x1f4ac;个人格言&#xff1a;不断的翻越一座又一…

mycat个人详谈

项目背景 现在业务想实现不同的用户分别看到不同的数据库&#xff0c;领导说用mycat中间件试试。没有接触过这个东西&#xff0c;刚拿到手直接头皮发麻&#xff0c;现在搞定了&#xff0c;索性就记录一下 Mycat数据库分库分表中间件 简介 阿里大牛开发的开源免费产品&#x…

设计模式——抽象工厂模式

文章目录1. 抽象工厂模式的定义2. 抽象工厂模式的类图3. 抽象工厂模式的作用4. 抽象工厂模式的实现1. 抽象工厂模式的定义 提供一个接口&#xff0c;用于创建相关或依赖对象的家族&#xff0c;而不需要明确指定具体类。 抽象工厂允许客户使用抽象的接口来创建一组相关的产品&a…

OAuth 2.0简介

OAuth就是一种授权机制。数据的所有者告诉系统&#xff0c;同意授权第三方应用进入系统&#xff0c;获取这些数据。系统从而产生一个短期的、一定权限的令牌&#xff08;token&#xff09;&#xff0c;用来代替密码&#xff0c;供第三方应用使用。 流程 1.第三方客户端要求用…

【欧姆龙控制器NX1系列调研】

欧姆龙控制器NX1系列调研NX系列 NX1 CPU单元NX系列-EtherNet/IP耦合器单元NX系列-系统单元NX系列通信接口单元NX系列数字输入单元NX系列模拟量输入单元NX系列模拟量输出入单元NX系列 高速模拟量模块NX系列IO-Link 主站单元温度控制/温度输入单元位置接口单元NX系列 安全控制单元…

【algorithm】算法基础课---排序算法(附笔记 | 建议收藏)

&#x1f680;write in front&#x1f680; &#x1f4dd;个人主页&#xff1a;认真写博客的夏目浅石. &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd; &#x1f4e3;系列专栏&#xff1a;AcWing算法学习笔记 &#x1f4ac;总结&#xff1a;希望你看完…

CSS入门四、浮动

零、文章目录 文章地址 个人博客-CSDN地址&#xff1a;https://blog.csdn.net/liyou123456789个人博客-GiteePages&#xff1a;https://bluecusliyou.gitee.io/techlearn 代码仓库地址 Gitee&#xff1a;https://gitee.com/bluecusliyou/TechLearnGithub&#xff1a;https:…

mybatis参数配置和日志详解

生命周期和作用域是至关重要的&#xff0c;因为错误的使用会导致非常严重的并发问题 每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的&#xff0c;SqlSessionFactory的实例可以通过 SqlSessionFactoryBuilder 获得&#xff0c;而 SqlSessionFactoryBuild…

【stl容器--实践操作】

目录&#xff1a;前言一、string&#xff08;一&#xff09;初始化 、 赋值 、 拼接&#xff08;二&#xff09;单个字符的访问和修改[]、at()&#xff08;三&#xff09;插入和删除insert 、erase&#xff08;四&#xff09;查找和替换find、rfind、replace&#xff08;五&…

代码随想录-47-101. 对称二叉树

目录前言题目1.递归思路2. 本题思路分析&#xff1a;3. 算法实现4. pop函数的算法复杂度5. 算法坑点前言 在本科毕设结束后&#xff0c;我开始刷卡哥的“代码随想录”&#xff0c;每天一节。自己的总结笔记均会放在“算法刷题-代码随想录”该专栏下。 代码随想录此题链接 题目…

FileNotFoundError: [Errno 2] No such file or directory VSCode Python插件的工作路径

文章目录1 前言2 Python主进程工作路径3 解决参考1 前言 在VSCode中&#xff0c;你是否遇到这样的情况 Traceback (most recent call last):File "......*.py", line 1, in <module>with open(filepath, r) as f: FileNotFoundError: [Errno 2] No such file…

提面优秀成功上岸浙大MBA的一点经验——专业管理思维很重要

本人的学历背景比较一般&#xff0c;就是个普通一本&#xff0c;但大学时为了挣学分&#xff0c;参加了不少的活动&#xff0c;还考了教师资格证&#xff0c;并且还去山区支教过3个月&#xff0c;支教一开始也是为了学分&#xff0c;但是通过与孩子们的相处&#xff0c;其实自己…

http相关(更新中)

概念 HTTP&#xff08;hypertext transport protocol&#xff09;协议也叫超文本传输协议&#xff0c;这个协议详细规定了浏览器和万维网服务器之间互相通信的规则。HTTPS更安全&#xff1b;无状态&#xff0c;cookie解决了无状态的问题 请求过程 客户端发送给服务器的称为“…

深度聚类方法之跨实例引导的对比聚类(Cross-instance guided Contrastive Clustering,C3)

深度聚类方法之跨实例引导的对比聚类(Cross-instance guided Contrastive Clustering,C3) 1.参考文献 《C3: Cross-instance guided Contrastive Clustering》2.跨实例引导的对比聚类(Cross-instance guided Contrastive Clustering,C3) 该方法是在对比聚类(Contrastive Clus…

Linux系统编程——信号

1.信号 信号共性: 简单、不能携带大量信息、满足条件才发送。信号的特质: 信号是软件层面上的“中断”。一旦信号产生&#xff0c;无论程序执行到什么位置&#xff0c;必须立即停止运行&#xff0c;处理信号&#xff0c;处理结束&#xff0c;再继续执行后续指令。所有信号的产…

如何使用Element-UI?

文章目录Element-UI概述Element-UI快速入门Element 布局Layout 局部Container 布局容器Element-UI组件使用案例介绍准备基本页面完成表格展示拷贝修改完成搜索表单展示完成批量删除和新增按钮展示完成对话框展示完成分页条展示完整页面代码Element-UI概述 Element&#xff1a;…

day11|144.二叉树的前序遍历、145.二叉树的后序遍历、94.二叉树的中序遍历

144.二叉树的前序遍历 给你二叉树的根节点 root &#xff0c;返回它节点值的 前序 遍历。 示例 1&#xff1a; 输入&#xff1a;root [1,null,2,3] 输出&#xff1a;[1,2,3] 示例 2&#xff1a; 输入&#xff1a;root [] 输出&#xff1a;[] 示例 3&#xff1a; 输入&#xf…

隔离放大器工作原理及其应用

介绍 隔离放大器或单位增益放大器提供从电路的一部分到另一部分的隔离。因此&#xff0c;不能在电路中消耗、使用和浪费功率。该放大器的主要功能是增加信号。运算放大器的相同输入信号作为输出信号从运算放大器精确地传出。这些放大器用于提供电气安全屏障和隔离。这些放大器…

从制造到“智造”,中国电信5G创新赋能工厂进入全连接时代

日前&#xff0c;工业和信息化部印发《5G全连接工厂建设指南》&#xff0c;提出“十四五”时期&#xff0c;主要面向原材料、装备、消费品、电子等制造业各行业以及采矿、港口、电力等重点行业领域&#xff0c;推动万家企业开展5G全连接工厂建设&#xff0c;建成1000个分类分级…

十一.字符串函数与内存函数

目录 一.求字符串长度 二.长度不受限制的字符串函数 1.strcpy函数 2.strcat函数 3.strcmp函数 三.长度受限制的字符串函数 1.strncpy函数 2.strncat函数 3.strncmp函数 四.字符串查找 1.strstr函数 2.strtok函数 3.strerror函数 五.字符操作 1.字符分类 2.字符…