举例网站:https://my.1hai.cn/Login/?url=http://www.1hai.cn/
一、场景:出于安全性考虑,越来越多的Web平台登录都会增加图形验证码(图片),或者短信验证码。由于是图片脚本selenium是无法识别的,这是时候我们解析图片验证码。
解决思路:1.通过selenium定位到图片,把图片保存到本地。
2 通过ORC技术将图片验证码转化为文字。
其他解决方法:A:去掉验证码
B:设置万能码
二、Web图片验证码的实现源码:
1 package util; 2 3 import java.awt.Color; 4 import java.awt.Font; 5 import java.awt.Graphics; 6 import java.awt.image.BufferedImage; 7 import java.io.IOException; 8 import java.io.OutputStream; 9 import java.util.Random; 10 import javax.imageio.ImageIO; 11 12 public class MakeCarke { 13 14 // 验证码图片中可以出现的字符集,可根据需要修改 15 private char mapTable[] = { \'a\', \'b\', \'c\', \'d\', \'e\', \'f\', \'g\', \'h\', \'i\', 16 \'j\', \'k\', \'l\', \'m\', \'n\', \'o\', \'p\', \'q\', \'r\', \'s\', \'t\', \'u\', \'v\', 17 \'w\', \'x\', \'y\', \'z\', \'0\', \'1\', \'2\', \'3\', \'4\', \'5\', \'6\', \'7\', \'8\', 18 \'9\' }; 19 20 /** * 功能:生成彩色验证码图片 * 参数width为生成图片的宽度,参数height为生成图片的高度,参数os为页面的输出流 */ 21 public String getCertPic(int width, int height, OutputStream os) { 22 23 if (width <= 0) { 24 width = 60; 25 } 26 if (height <= 0) { 27 height = 20; 28 } 29 BufferedImage image = new BufferedImage(width, height, 30 BufferedImage.TYPE_INT_RGB); 31 // 获取图形上下文 32 Graphics g = image.getGraphics(); 33 // 设定背景色 34 g.setColor(new Color(0xDCDCDC)); 35 g.fillRect(0, 0, width, height); 36 // 画边框 37 g.setColor(Color.black); 38 g.drawRect(0, 0, width - 1, height - 1); 39 // 取随机产生的认证码 40 String strEnsure = ""; 41 // 4代表4位验证码,如果要生成更多位的认证码,则加大数值 42 for (int i = 0; i < 4; ++i) { 43 strEnsure += mapTable[(int) (mapTable.length * Math.random())]; 44 } 45 // 将认证码显示到图像中,如果要生成更多位的认证码,增加drawString语句 46 g.setColor(Color.black); 47 g.setFont(new Font("Atlantic Inline", Font.PLAIN, 18)); 48 String str = strEnsure.substring(0, 1); 49 g.drawString(str, 8, 17); 50 str = strEnsure.substring(1, 2); 51 g.drawString(str, 20, 15); 52 str = strEnsure.substring(2, 3); 53 g.drawString(str, 35, 18); 54 str = strEnsure.substring(3, 4); 55 g.drawString(str, 45, 15); 56 57 // 随机产生10个干扰点 58 Random rand = new Random(); 59 for (int i = 0; i < 10; i++) { 60 int x = rand.nextInt(width); 61 int y = rand.nextInt(height); 62 g.drawOval(x, y, 1, 1); 63 } 64 // 释放图形上下文 65 g.dispose(); 66 try { 67 // 输出图像到页面 68 ImageIO.write(image, "JPEG", os); 69 } catch (IOException e) { 70 return ""; 71 } 72 return strEnsure; 73 74 } 75 76 }
三、selenium+java 实现验证码图片保存
1 package com.app.launch; 2 import java.io.File; 3 import java.awt.image.BufferedImage; 4 import java.io.IOException; 5 6 import javax.imageio.ImageIO; 7 8 import org.apache.commons.io.FileUtils; 9 import org.openqa.selenium.By; 10 import org.openqa.selenium.OutputType; 11 import org.openqa.selenium.TakesScreenshot; 12 import org.openqa.selenium.WebDriver; 13 import org.openqa.selenium.WebElement; 14 import org.openqa.selenium.chrome.ChromeDriver; 15 16 import com.app.utils.Utils; 17 18 public class OcrDownloadPicture { 19 20 public static void main(String[] args) throws IOException { 21 22 public void dowanLoadPictureVerificationCode() throws IOException{ 23 driver.get("https://my.1hai.cn/Login/?url=http://www.1hai.cn/"); 24 WebElement ele = driver.findElement(By.xpath(".//img[@id=\'quick_imgCaptcha\']")); 25 ele.click();
26 Utils.waitABit(2000); 27 File screenshot = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE); 28 BufferedImage fullImg = ImageIO.read(screenshot); // 读取截图 29 // 得到页面元素 30 org.openqa.selenium.Point point= ele.getLocation(); 31 // 得到长、宽 32 int eleWidth= ele.getSize().getWidth(); 33 int eleHeight= ele.getSize().getHeight(); 34 35 BufferedImage eleScreenshot= fullImg.getSubimage(point.getX(), point.getY(), eleWidth, eleHeight); 36 ImageIO.write(eleScreenshot, "png", screenshot); 37 // copy 把图片放对应的生成目录下 38 File screenshotLocation = new File("E:/Vame/img/test.jpg"); 39 FileUtils.copyFile(screenshot, screenshotLocation); 40 } 41 42 }
四、效果图