Selenium 实现图片验证码识别

news2025/1/4 15:31:53

前言

在测试过程中,有的时候登录需要输入图片验证码。这时候使用Selenium进行自动化测试,怎么做图片验证码识别?本篇内容主要介绍使用Selenium、BufferedImage、Tesseract进行图片 验证码识别。

环境准备

jdk:1.8
tessdata:文章末尾附下载地址

安装Tesseract

我本地是ubuntu系统

sudo apt install tesseract-ocr
sudo apt install libtesseract-dev 

在项目中引用

<dependency>
    <groupId>net.sourceforge.tess4j</groupId>
    <artifactId>tess4j</artifactId>
    <version>4.5.4</version>
</dependency>

实现

在下图中,登录需要使用图片验证码进行验证。我们的图片验证码识别流程是使用Selenium定位到图片验证码元素,将元素截图保。然后将保存的图片验证码使用BufferedImage进行灰度化、二值化处理,处理完成后去除图片上的干扰点。最后使用Tesseract进行图片验证码上的字符识别。
在这里插入图片描述

处理图片

首先使用BufferedImage读取图片验证码图片,然后调整亮度后进行灰度化、二值化处理。处理后的图片去除干扰点。

public static void cleanLinesInImage(File sfile, String destDir)  throws IOException{
	File destF =new File(destDir);
	if (!destF.exists())
	{
	    destF.mkdirs();
	}
	
	BufferedImage bufferedImage = ImageIO.read(sfile);
	int h = bufferedImage.getHeight();
	int w = bufferedImage.getWidth();
	
	// 灰度化
	int[][] gray = new int[w][h];
	for (int x = 0; x < w; x++)
	{
	    for (int y = 0; y < h; y++)
	    {
	        int argb = bufferedImage.getRGB(x, y);
	        // 图像加亮(调整亮度识别率非常高)
	        int r = (int) (((argb >> 16) & 0xFF) * 1.1 + 30);
	        int g = (int) (((argb >> 8) & 0xFF) * 1.1 + 30);
	        int b = (int) (((argb >> 0) & 0xFF) * 1.1 + 30);
	//                int r = (int) (((argb >> 16) & 0xFF) * 0.1 + 30);
	//                int g = (int) (((argb >> 8) & 0xFF) * 0.1 + 30);
	//                int b = (int) (((argb >> 0) & 0xFF) * 0.1 + 30);
	        if (r >= 255)
	        {
	            r = 255;
	        }
	        if (g >= 255)
	        {
	            g = 255;
	        }
	        if (b >= 255)
	        {
	            b = 255;
	        }
	        gray[x][y] = (int) Math
	                .pow((Math.pow(r, 2.2) * 0.2973 + Math.pow(g, 2.2)
	                        * 0.6274 + Math.pow(b, 2.2) * 0.0753), 1 / 2.2);
	
	    }
	}
	
	ImageIO.write(bufferedImage, "jpg", new File(destDir, sfile.getName()));
	
	// 二值化
	int threshold = ostu(gray, w, h);
	BufferedImage binaryBufferedImage = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_BINARY);
	for (int x = 0; x < w; x++)
	{
	    for (int y = 0; y < h; y++)
	    {
	        if (gray[x][y] > threshold)
	        {
	            gray[x][y] |= 0x00FFFF;
	        } else
	        {
	            gray[x][y] &= 0xFF0000;
	        }
	        binaryBufferedImage.setRGB(x, y, gray[x][y]);
	    }
	}
	
	ImageIO.write(binaryBufferedImage, "jpg", new File(destDir, sfile.getName()));
	
	//        去除干扰线条
	for(int y = 1; y < h-1; y++){
	    for(int x = 1; x < w-1; x++){
	        boolean flag = false ;
	        if(isBlack(binaryBufferedImage.getRGB(x, y))){
	            //左右均为空时,去掉此点
	            if(isWhite(binaryBufferedImage.getRGB(x-1, y)) && isWhite(binaryBufferedImage.getRGB(x+1, y))){
	                flag = true;
	            }
	            //上下均为空时,去掉此点
	            if(isWhite(binaryBufferedImage.getRGB(x, y+1)) && isWhite(binaryBufferedImage.getRGB(x, y-1))){
	                flag = true;
	            }
	            //斜上下为空时,去掉此点
	            if(isWhite(binaryBufferedImage.getRGB(x-1, y+1)) && isWhite(binaryBufferedImage.getRGB(x+1, y-1))){
	                flag = true;
	            }
	            if(isWhite(binaryBufferedImage.getRGB(x+1, y+1)) && isWhite(binaryBufferedImage.getRGB(x-1, y-1))){
	                flag = true;
	            }
	            if(flag){
	                binaryBufferedImage.setRGB(x,y,-1);
	            }
	        }
	    }
	}
	
	// 矩阵打印
	//        for (int y = 0; y < h; y++)
	//        {
	//            for (int x = 0; x < w; x++)
	//            {
	//                if (isBlack(binaryBufferedImage.getRGB(x, y)))
	//                {
	//                    System.out.print("*");
	//                } else
	//                {
	//                    System.out.print(" ");
	//                }
	//            }
	//            System.out.println();
	//        }
	
	ImageIO.write(binaryBufferedImage, "jpg", new File(destDir, sfile.getName()));
	}

OCR识别

setDataPath方法,传入你下载的

public static String executeTess4J(String imgUrl){
	String ocrResult = "";
	try{
	    ITesseract instance = new Tesseract();
	    instance.setDatapath("your tessdata path");
	    instance.setLanguage("eng");
	    instance.setOcrEngineMode(0);
	    instance.setTessVariable("tessedit_char_whitelist", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890");
	    File imgDir = new File(imgUrl);
	    //long startTime = System.currentTimeMillis();
	    ocrResult = instance.doOCR(imgDir);
	}catch (TesseractException e){
	    e.printStackTrace();
	}
	return ocrResult;
}

验证

编写Selenium脚本

public static void main(String[] args) throws IOException {
    System.setProperty("webdriver.chrome.driver", "/home/zhangkexin/chromedriver");
    WebDriver driver = new ChromeDriver();
    driver.manage().window().maximize();
    driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
    driver.get("https://xkczb.jtw.beijing.gov.cn/#");
    WebElement element = driver.findElement(By.xpath("//*[@id=\"getValidCode\"]/img"));
    File img = element.getScreenshotAs(OutputType.FILE);
    String path = System.getProperty("user.dir");
    cleanLinesInImage(img, path);
    String imgFile = path  + "/" + img.getName();
    Path source = Paths.get(imgFile);
    Path dest =  Paths.get("/home/zhangkexin/ui-test/autoTest/img.jpg");
    Files.copy(source, dest, StandardCopyOption.REPLACE_EXISTING);
    String code = executeTess4J("/home/zhangkexin/ui-test/autoTest/img.jpg");
    System.out.println(code);
    driver.quit();
}

看一下经过处理后的图片验证码
在这里插入图片描述
最后实际识别出来的结果。
在这里插入图片描述
testdata:
链接:https://pan.baidu.com/s/1uJE9wl1oa2WAsBTsydUlmg?pwd=m576 
提取码:m576

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

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

相关文章

关于CPP——std::future异步操作

目录 一、std::future 简介 1.1 概念 1.2 应用场景 1.3 关联的方法 1.3.1 std::async 1.3.2 std::package 1.3.3 std::promise 二、future 用法 2.1 使用std::async关联异步任务 2.2 使用std::packaged_task 1. 获取任务结果的机制&#xff1a; 2. 异步任务的管理&a…

jmeter之仅一次控制器

仅一次控制器作用&#xff1a; 不管线程组设置多少次循环&#xff0c;它下面的组件都只会执行一次 Tips&#xff1a;很多情况下需要登录才能访问其他接口&#xff0c;比如&#xff1a;商品列表、添加商品到购物车、购物车列表等&#xff0c;在多场景下&#xff0c;登录只需要…

【STM32 Blue Pill编程】-ADC数据采样(轮询、中断和DMA模式)

ADC数据采样(轮询、中断和DMA模式) 文章目录 ADC数据采样(轮询、中断和DMA模式)1、硬件准备及接线2、ADC轮询模式2.1 轮询模式配置2.2 代码实现3、ADC中断模式3.1 中断模式配置3.2 代码实现4、ADC的DMA模式4.1 DMA模式配置4.2 代码实现在本文中,我们将介绍如何使用 ADC 并…

[JAVA基础知识汇总-1] 创建线程的几种方式

文章目录 1. 继承Thread类2. 实现Runnable接口3. 实现Callable接口4. 线程池 可以认为有四种方式&#xff0c;也可以认为有一种&#xff0c;因为都跟Runnable接口有关 1. 继承Thread类 代码 public class Thread1ExtendsThread extends Thread { // public Thread1(String …

思维导图与头脑风暴:你值得拥有的四大工作与学习利器

在工作与学习中&#xff0c;我们都遇到过这样的情况&#xff1a;我们需要就某一问题或项目&#xff0c;汇集多人的智慧与创意&#xff0c;这时&#xff0c;头脑风暴便成为了我们不可或缺的利器&#xff1b;而为了更好地进行头脑风暴&#xff0c;选择一款合适的在线思维导图工具…

【Qt开发】QT6.5.3安装方法(使用国内源)亲测可行!!!

目录 &#x1f315;下载在线安装包&#x1f315; 把安装包放到系统盘&#x1f315;开始安装&#x1f315;参考文章 &#x1f315;下载在线安装包 https://mirrors.nju.edu.cn/qt/official_releases/online_installers/ &#x1f315; 把安装包放到系统盘 我的系统盘是G盘&…

uniapp 全屏日历,动态无限加载

不好用请移至评论区揍我 原创代码,请勿转载,谢谢! 注:本人仅在微信小程序测试过,未在其他app/h5尝试过,按理说应该是可以的,代码没有引用任何第三方组件 日历中每个日期下方的空白部分均可自定义,写在代码中的<view class="item">我是内容</view>…

Go入门指南(The Way to Go) 完整版PDF

The Way To Go可以说是入门 Go 的经典书籍&#xff0c;这本书有内容丰富各种资料链接&#xff0c;这是截止到目前&#xff0c;大叔看到的写得最好的go 语言教材&#xff0c;非常详细.一口气读下来&#xff0c;舍不得放手&#xff0c;大叔强烈推荐你去学习 百度网盘分享

docker基于minio部署outline团队知识库

outline 介绍 Outline 是一个开源的Wiki 知识库和团队协作文档管理工具&#xff0c;美观、实时协作、功能丰富且兼容 Markdown&#xff0c;设计用于帮助团队和组织有效地创建、共享和管理文档。 Outline 具有简单易用的界面和强大的功能&#xff0c;可以替代传统的文档管理系…

winndows系统修改cmd用户中文名、系统中文用户名修改为英文用户名的方法

文章目录 一、问题描述二、修改步骤1. 准备&#xff1a;2. 注销&#xff1a;3. 修改&#xff1a;4. 继续修改&#xff1a; 一、问题描述 电脑用户显示中文名&#xff08;我这里已经修改了&#xff09; 二、修改步骤 1. 准备&#xff1a; 我们需要使用 Administrator 登录&am…

OpenGL——画一个填充的三角形

1. vertShader.glsl&#xff08;顶点着色器代码&#xff09;&#xff1a; #version 460void main (void) {if (gl_VertexID 0)gl_Position vec4 (0.25, -0.25, 0.0, 1.0);else if (gl_VertexID 1)gl_Position vec4 (-0.25, -0.25, 0.0, 1.0);elsegl_Position vec4 (0.25,…

[C/C++入门][进制原理]31、求分数序列和

题目来自于信息学奥赛 1078 分析&#xff1a; 这道题看起来比较复杂&#xff0c;实际上只需要通过两个公式&#xff0c;一次性求出分母和分子&#xff0c;然后把这个求出来的数加入到变量和中。甚至都不需要知道总共游哪些数。数组都用不上。循环就能解决。 #include <ios…

快速排序(QuickSort)-归并排序(MergeSort)[java编写]

1. 快速排序 1.1 基本概述 快速排序采用分治思想&#xff0c;即在一个无序的序列中选取一个任意的基准元素pivot&#xff0c;利用pivot 将待排序的序列分成两部分&#xff0c;前面部分元素均小于或等于基准元素&#xff0c;后面部分均大于或等于基准元素&#xff0c;然后采用…

Chapter 10 Stability and Frequency Compensation

Chapter 10 Stability and Frequency Compensation Chapter 8介绍了负反馈, 这一章介绍稳定性, 如果设计不好, 负反馈系统是要发生震荡的. 首先我们学习理解稳定判断标准和条件, 然后学习频率补偿, 介绍适用于不同运放的补偿方式, 同时介绍不同补偿对两级运放slew rate的影响…

2024全新苹果cms影视源码/仿韩剧TV主题模板源码/电影视频在线观看网站源码-自适应 (PC+WAP)

源码简介 2024年最新版的苹果CMS影视源码&#xff0c;仿制了韩剧TV的主题模板&#xff0c;让网站看起来跟韩剧TV一模一样&#xff0c;而且这个源码支持在线观看电影和视频&#xff0c;无论是在电脑&#xff08;PC&#xff09;还是手机&#xff08;WAP&#xff09;上都能完美自…

网络编程之-UDP详解

&#x1f308;个人主页&#xff1a;努力学编程’ ⛅个人推荐&#xff1a; c语言从初阶到进阶 JavaEE详解 数据结构 ⚡学好数据结构&#xff0c;刷题刻不容缓&#xff1a;点击一起刷题 &#x1f319;心灵鸡汤&#xff1a;总有人要赢&#xff0c;为什么不能是我呢 &#x1f3c0…

2024年 Biomedical Signal Processing and Control 期刊投稿经验最新分享

期刊介绍 《Biomedical Signal Processing and Control 》期刊旨在为临床医学和生物科学中信号和图像的测量和分析研究提供一个跨学科的国际论坛。重点放在处理在临床诊断&#xff0c;患者监测和管理中使用的方法和设备的实际&#xff0c;应用为主导的研究的贡献。 生物医学信…

【大模型基础】P1 N-Gram 模型

目录 N-Gram 概述N-Gram 构建过程TokenN-Gram 实例第1步 构建实验语料库第2步 把句子分成 N 个 “Gram”第3步 计算每个 Bigram 在语料库中的词频第4步 计算出现的概率第5步 生成下一个词第6步&#xff1a;输入前缀&#xff0c;生成连续文本 上述实例完整代码N-Gram 的局限性 N…

一文理解粒子滤波

0. 粒子滤波流程 之前学习记录的文档&#xff0c;这里也拿出来分享一下~ 基本原理&#xff1a;随机选取预测域的 N NN 个点&#xff0c;称为粒子。以此计算出预测值&#xff0c;并算出在测量域的概率&#xff0c;即权重&#xff0c;加权平均就是最优估计。之后按权重比例&…

揭秘帕金森症幕后元凶:是哪些因素悄悄“震颤”了生活?

在这个快节奏的时代&#xff0c;健康成为了我们最宝贵的财富之一。然而&#xff0c;有一种名为“帕金森病”的神秘疾病&#xff0c;正悄悄影响着无数人的生活&#xff0c;让他们的日常充满了“不由自主”的颤抖。今天&#xff0c;就让我们一起揭开帕金森症的神秘面纱&#xff0…