Selenium 实现图片验证码识别

前言

在测试过程中,有的时候登录需要输入图片验证码。这时候使用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

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要使用 Python Selenium 调用阿里 API 实现图片验证码识别,您需要先注册阿里云账户并开通 OCR 服务。然后,您可以按照以下步骤进行操作: 1. 安装阿里云 Python SDK 您可以使用以下命令进行安装: ``` pip install aliyun-python-sdk-core-v3 pip install aliyun-python-sdk-ocr ``` 2. 在 Python 中调用 OCR API 以下是一个示例代码,它可以将本地图片文件上传到阿里云 OCR 服务,并返回识别结果: ```python from aliyunsdkcore.client import AcsClient from aliyunsdkocr.request.v20191230 import RecognizeCharacterRequest # 阿里云 OCR API 配置 access_key_id = 'your_access_key_id' access_key_secret = 'your_access_key_secret' region_id = 'cn-shanghai' product_name = 'ocr' domain = 'ocr.cn-shanghai.aliyuncs.com' # 初始化阿里云 client client = AcsClient(access_key_id, access_key_secret, region_id) # 读取本地图片文件 with open('captcha.png', 'rb') as f: image_data = f.read() # 构造 OCR API 请求 request = RecognizeCharacterRequest.RecognizeCharacterRequest() request.set_ImageURL(image_data) request.set_accept_format('json') # 调用 OCR API 进行识别 response = client.do_action(request) # 解析识别结果 result = response.decode('utf-8') print(result) ``` 在上面的示例代码中,`access_key_id` 和 `access_key_secret` 是您的阿里云账户的 Access Key ID 和 Access Key Secret,`region_id` 是 OCR 服务所在的地域,`product_name` 是 OCR 服务的产品名称,`domain` 是 OCR 服务的 API 域名。 需要注意的是,OCR 服务支持的图片格式有限,只支持 JPEG、JPG、PNG、BMP 等常见格式。另外,OCR 服务的免费配额较低,需要购买更多的调用次数才能满足大规模的识别需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值