Tesseract-OCR识别验证码

时间:2022-03-01 23:28:27

1. 安装Tesseract-OCR,安装后测试下是否安装成功

 Tesseract-OCR识别验证码

2. eclipse创建Java项目,再创建包

3. 新建类BaseClass.java, 里面包括通用的一些方法

 

Tesseract-OCR识别验证码Tesseract-OCR识别验证码
package testNG;

import java.awt.Desktop;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.FileNotFoundException; 
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;
import javax.xml.crypto.Data;

import org.apache.commons.io.FileUtils;
import org.apache.poi.ss.usermodel.Cell; 
import org.apache.poi.xssf.usermodel.XSSFName;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.openqa.selenium.By;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.openqa.selenium.remote.DesiredCapabilities;

import com.sun.media.imageio.plugins.tiff.TIFFImageWriteParam;

 
@SuppressWarnings("unused")

public class BaseClass {
    /***
     * 基础类,包括方法:启动webdriver、获取基础数据、获取测试数据、返回当前时间、写入结果文件、
     * 截图、打开结果文件、去除空格换行及制表符的字符串
     * 
     * @param args
     * @throws IOException
     * @throws InterruptedException
     */
    public static WebDriver startBrowser(String browserType){
        /**
          * FunName:        startBrowser
          * Description :   启动浏览器,支持ie/fireFox/chrome
          * @param:                 String browserType
          * @return WebDriver:  driver
          * @Author:        Bingo
          * @Create Date:   2015-07-21
          **/        
        WebDriver wd = null;
        if (browserType == "ie"){
             System.setProperty("webdriver.ie.driver", "drivers\\IEDriverServer.exe");//ie驱动路径
             DesiredCapabilities dc = DesiredCapabilities.internetExplorer();
             dc.setCapability(InternetExplorerDriver.INTRODUCE_FLAKINESS_BY_IGNORING_SECURITY_DOMAINS, true);
             //关闭IE浏览器保护模式
             dc.setCapability("ignoreProtectedModeSettings", true);
             wd = new InternetExplorerDriver();
        }else if(browserType == "fireFox"){
            System.setProperty("webdriver.firefox.bin", //firefox的安装路径
                     "D:/Program Files/Mozilla Firefox/firefox.exe");
            wd = new FirefoxDriver();
        }else if(browserType == "chrome"){
            System.setProperty("webdriver.chrome.driver", "drivers\\chromedriver.exe");//驱动路径
            wd = new ChromeDriver();
        }        
        return wd;
        
    }
    
        
    //读取测试URL、测试数据文件路径和结果文件路径
    public String getBaseData(String testInfo, String baseDataPath) throws IOException{
        /**
          * FunName:        getBaseData
          * Description :   获取测试URL、测试数据文件路径和结果文件路径
          * @param:                 String testInfo
          * @return String:  返回基础数据字符串;
          * @Author:        Bingo
          * @Create Date:   2015-06-29
          **/
        String testString =  null;
        FileInputStream file = new FileInputStream(baseDataPath);
        @SuppressWarnings("resource")
        XSSFWorkbook wb = new XSSFWorkbook(file);
        XSSFSheet sheet = wb.getSheetAt(0);
        XSSFRow rowinf = sheet.getRow(1);
        Cell cell = null;
        switch(testInfo){
            case "inPath"                  : cell = rowinf.getCell(0);break;
            case "outPath"              : cell = rowinf.getCell(1);break;
            case "baseURL"              : cell = rowinf.getCell(2);break;
            case "firefoxPath"          : cell = rowinf.getCell(3);break;
            case "screenShotDir"          : cell = rowinf.getCell(4);break;
            case "snapshotDir"          : cell = rowinf.getCell(5);break;
            case "xiaoWeiIssuerURL"      : cell = rowinf.getCell(6);break;
            case "Tesseract-OCRPath"      : cell = rowinf.getCell(7);break;
            default: System.out.println("no testInfo found!");
        }
        cell.setCellType(Cell.CELL_TYPE_STRING);  
        testString= cell.getStringCellValue(); 
         
        return testString;
    }

    
    //读取信息,被测试方法调用,参数为方法名、列名colNm、文件路径inPath
    public String getData_xlsx(String funNm, String colNm, String inPath) throws FileNotFoundException, IOException{
        /**
          * FunName:        getData_xlsx
          * Description :   读取信息,供被测试方法调用
          * @param:                 String funNm, String colNm, String inPath
          * @return String:  返回测试数据;
          * @Author:        Bingo
          * @Create Date:   2015-06-29
          **/
        String str1 = null;
        FileInputStream file = new FileInputStream(inPath);
        @SuppressWarnings("resource")
        XSSFWorkbook wb = new XSSFWorkbook(file);
        XSSFSheet sheet = null;
        Cell cell = null;
        //根据方法名,读取对应的sheet
        if (funNm == "Login"){
            sheet = wb.getSheetAt(1);
        } else if (funNm == "QueryApp"){
            sheet = wb.getSheetAt(2);
        }
        XSSFRow row1 = sheet.getRow(1);
        //根据不同的列名,读取对应的列
        if(colNm == "orgz"||colNm == "appNo")
            cell = row1.getCell(0); 
            
        else if(colNm == "userId"||colNm == "holName")
            cell = row1.getCell(1);
        else if(colNm == "pwd"||colNm == "cerType")
            cell = row1.getCell(2);
        else if(colNm == "cerNo"||colNm == "xiaoWeiUserId")
            cell = row1.getCell(3);
        else if(colNm == "xiaoWeiUserPwd")
            cell = row1.getCell(4);    
        else System.out.println(nowDate()+" err funcName or colNume");
        cell.setCellType(Cell.CELL_TYPE_STRING);  
        str1= cell.getStringCellValue();
        return str1;
    }
    //写入测试结果文件,参数为方法名、是否通过、文件路径和执行时间
    public void outCome_xlsx(String funNm, String outCome, String outPath,String date) throws IOException
    {
        /**
          * FunName:        outCome_xlsx
          * Description :   写入测试结果
          * @param:                 String funNm, String outCome, String outPath,String date
          * @return void:        无返回数据;
          * @Author:        Bingo
          * @Create Date:   2015-06-29
          **/
        FileInputStream file = new FileInputStream(outPath);
        @SuppressWarnings("resource")
        XSSFWorkbook wb = new XSSFWorkbook(file);
        String stname = wb.getSheetName(0);
        XSSFSheet sheet = wb.getSheetAt(0);
        int trLength = sheet.getLastRowNum();  
        XSSFRow newrow = sheet.createRow((short)(trLength+1));
        newrow.createCell(0).setCellValue(funNm);  
        newrow.createCell(1).setCellValue(outCome);
        newrow.createCell(2).setCellValue(date);
        FileOutputStream fout = new FileOutputStream(outPath); 
        wb.write(fout);
        file.close();
        fout.close();
 
    }    
        
//        public File createLogFile(String fileName, String logDir){
//            File file = null;
//            
//            return file;
//        }
//        
        
        //写入日志文件信息,文件名为yyyy-mm-dd.log
        public static File writeLog(String logMsg) throws IOException
        {
            /**
              * FunName:        writeLog
              * Description :   记录日志
              * @param:                 File file, String msg
              * @return file:        返回文件;
              * @Author:        Bingo
              * @Create Date:   2015-07-21
              **/
            //FileInputStream file = new FileInputStream(outPath);
            String logDir = System.getProperty("user.dir")+"\\log\\";
            String time = null;
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");//设置日期格式
            time = sdf.format(new Date()).toString();
            File file = new File(logDir+time+".log");
            if(!file.exists()) {  
                file.createNewFile();
            }  
            @SuppressWarnings("resource")
            Writer txtWriter = new FileWriter(file,true);  
            txtWriter.write(nowDate() +"\t"+logMsg+"\n");  
            txtWriter.flush();
            return file;         
        }
            
        public void openOutCome(String outPath){
        /**
          * FunName:        openOutCome
          * Description :   打开测试结果文件
          * @param:                 文件URL
          * @return void:        无返回数据;
          * @Author:        Bingo
          * @Create Date:   2015-06-30
          **/
        Desktop desk=Desktop.getDesktop();  
        try  
        {  
            File file1=new File(outPath);//创建一个java文件系统  
            if (!file1.canWrite())//判断文件是否被占用
            {
                desk.open(file1); //调用open(File f)方法打开文件  
            }else {
                FileInputStream in=new FileInputStream(file1);
                in.close();
                desk.open(file1);
            }
        }catch(Exception e)  
        {  
            System.out.println(e.toString());  
        }
        
    }
    
    public void screenShot(String screenOutDir,WebDriver driver,String funNm) throws InterruptedException{
        /**
          * FunName:        openOutCome
          * Description :   截图
          * @param:                 文件URL
          * @return void:        无返回数据;
          * @Author:        Bingo
          * @Create Date:   2015-06-30
          **/
        //Thread.sleep(3000);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd HHmmss-SSS");
        String time = sdf.format(new Date());
        
        String fileName = funNm+time +".png";
        try {
             File source_file = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);  // 执行屏幕截图,默认会把截图保存到temp目录
             
             FileUtils.copyFile(source_file, new File(screenOutDir + "/" + fileName));  // 这里将截图另存到我们需要保存的目录,例如screenshot\20120406 165210-333.png
        } catch (IOException e) {
             e.printStackTrace();
          }        
    }
    
    public  static String replaceBlank(String str) {
        /**
         * 返回STR中去除空格、换行制表符的内容
         * 
         */
        
        String dest = "";
        if (str!=null) {
            Pattern p = Pattern.compile("\\s*|\t|\r|\n");
            Matcher m = p.matcher(str);
            dest = m.replaceAll("");
        }
        return dest;
    }
    //获取当前系统时间
    public static String nowDate(){
        String nowDate = null;
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
        nowDate =df.format(new Date()).toString();
        return nowDate;
    }
    
    //判断字符串是否纯数字
    public boolean isDigitStr(String s){
        for(int i =0; i<s.length()-1;i++){
            if(!Character.isDigit(s.charAt(i))){
                return false;
            }
        }
        return true;
    }
    
    //根据byType及值,返回by,访问方式:driver.findElement(getBy("id","kw"))
    public static WebElement getElement(WebDriver driver,String byType, String byValue){
        WebElement we = null;
        switch(byType){
            case "id": we = driver.findElement(By.id(byValue));break;
            case "xpath": we = driver.findElement(By.xpath(byValue));break;
            case "name": we = driver.findElement(By.name(byValue));break;
            case "className": we = driver.findElement(By.className(byValue));break;
            case "linkText": we = driver.findElement(By.linkText(byValue));break;
            case "cssSelector": we = driver.findElement(By.cssSelector(byValue));break;
            case "tagName": we = driver.findElement(By.tagName(byValue));break;
            case "partialLinkText": we = driver.findElement(By.partialLinkText(byValue));break;
            default:break;
            
        }
        return we;
    }
    public static void println(Object obj){
        /**
          * FunName:        println
          * Description :   简版打印,代替System.out.print(object)
          * @param:                 object
          * @return String:  none
          * @Author:        Bingoreo
          * @Create Date:   2015-07-15
          **/
        System.out.println(obj);
    }

    public static void print(Object obj){
        /**
          * FunName:        println
          * Description :   简版打印,代替System.out.print(object)
          * @param:                 object
          * @return String:  none
          * @Author:        Bingoreo
          * @Create Date:   2015-07-15
          **/
        System.out.print(obj);
        
    }

    public static void println(){
        /**
          * FunName:        println
          * Description :   简版打印,代替System.out.println()
          * @param:                 none
          * @return String:  none
          * @Author:        Bingoreo
          * @Create Date:   2015-07-15
          **/
        System.out.println();
    }
    
    
    public static void main(String[] args)  {
        // TODO 自动生成的方法存根
    }
    
}
View Code

4. 创建类GetNetImgAndSave.java,获取网页图片并保存本地

Tesseract-OCR识别验证码Tesseract-OCR识别验证码
package testNG;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

import org.apache.commons.io.FileUtils;
import org.openqa.selenium.Dimension;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.Point;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.remote.Augmenter;
/**
 * 类说明:获取网页图片并保存本地
 * 
 * @author Bingo
 *
 */
public class GetNetImgAndSave {
    static BaseClass baseclass = new BaseClass();
    
    public static void main(String[] args) throws IOException {
        // TODO 自动生成的方法存根
        GetNetImgAndSave in = new GetNetImgAndSave();
        
        try {
            in.inputText();
            
            baseclass.openOutCome("e://testasdasd.png");
        } catch (InterruptedException e) {
            // TODO 自动生成的 catch 块
            e.printStackTrace();
        }
    }
    

public static void snapshot2(WebDriver drivername, String filename, String baseDataPath)
{
    //截图
    try {
            WebDriver augmentedDriver = new Augmenter().augment(drivername);
            File screenshot = ((TakesScreenshot) augmentedDriver).getScreenshotAs(OutputType.FILE);
            String snapshotDir = baseclass.getBaseData("snapshotDir", baseDataPath);
            File file = new File(snapshotDir+filename);
            FileUtils.copyFile(screenshot, file);
      } catch (IOException e) {
          // TODO Auto-generated catch block
          BaseClass.println(BaseClass.nowDate()+" Can't save screenshot");
          e.printStackTrace();
      } 
      finally
      {
          BaseClass.println(BaseClass.nowDate()+" screen shot finished");
      }
    }

    public static byte[] takeScreenshot(WebDriver driver) throws IOException {
        WebDriver augmentedDriver = new Augmenter().augment(driver);
    return ((TakesScreenshot) augmentedDriver).getScreenshotAs(OutputType.BYTES);
        //TakesScreenshot takesScreenshot = (TakesScreenshot) driver;
        //return takesScreenshot.getScreenshotAs(OutputType.BYTES);
        }

     public static BufferedImage createElementImage(WebDriver driver,WebElement webElement)
                throws IOException, InterruptedException {
                // 获得webElement的位置和大小。
                Point location = webElement.getLocation();
                Dimension size = webElement.getSize();
                // 创建全屏截图。
                BufferedImage originalImage =
                ImageIO.read(new ByteArrayInputStream(takeScreenshot(driver)));
                // 截取webElement所在位置的子图。
                BufferedImage croppedImage = originalImage.getSubimage(
                location.getX(),
                location.getY(),
                size.getWidth(),
                size.getHeight());
                Thread.sleep(3000);
                return croppedImage;
                }
    public void inputText() throws InterruptedException, IOException{
        /***
         * 
         * 
         */
        String baseDataPath = "E:/workspace/1506/testNG/testdata/testData.xlsx";
        String firefoxPath;
        String testURL =  baseclass.getBaseData("testURL", baseDataPath);
        String OCRPath = baseclass.getBaseData("Tesseract-OCRPath", baseDataPath);
        try {
            firefoxPath = baseclass.getBaseData("firefoxPath",baseDataPath);
        
            System.setProperty("webdriver.firefox.bin",firefoxPath);
            WebDriver driver = new FirefoxDriver();
            driver.get(testURL);
            //driver.findElement(By.id("codeImg")).click();
            //driver.findElement(By.id("randCode")).clear();
            WebElement keyWord;
            try{  
               keyWord = BaseClass.getElement(driver,"id","codeImg");  
               if(keyWord!=null){  
                   String src =  keyWord.getAttribute("src");  
                   BaseClass.println(BaseClass.nowDate()+"  验证码地址 ====="+src);  
                   if(src!=null && !"".equals(src)){ 
                       snapshot2(driver,"1111111111.png",baseDataPath);  
                       BufferedImage inputbig = createElementImage(driver,keyWord);  
                       ImageIO.write(inputbig, "png", new File("c://testasdasd.png"));   
                       OCRTif ocr = new OCRTif();
                       
                       String key= ocr.recognizeText(new File("c://testasdasd.png"), "png", OCRPath);  
                       //验证码输入框  
                       BaseClass.println(BaseClass.nowDate()+" +++++\nkey:\n"+key+"\n+++++");
                       //keyWord = driver.findElement(By.id("randCode"));     
                       //keyWord.clear();  
                       BaseClass.getElement(driver,"id","randCode").sendKeys(key);  
                       //keyWord.sendKeys(key);
                       Thread.sleep(3000);
                         
                   }  
                     
               }  
           }catch(Exception e){  
               e.printStackTrace();  
           }
        } catch (IOException e1) {
            // TODO 自动生成的 catch 块
            e1.printStackTrace();
        }
       } 
    }
View Code

5. 创建类ImageConvertGif.java, 用于转换图片类型,并返回文件实例

Tesseract-OCR识别验证码Tesseract-OCR识别验证码
package testNG;
/***
 * 将指定类型的图像文件转换为tif
 * 
 */
import java.awt.image.BufferedImage;  
import java.io.File;  
import java.io.IOException;  
import java.util.Iterator;  
import java.util.Locale;  

import javax.imageio.IIOImage;  
import javax.imageio.ImageIO;  
import javax.imageio.ImageReader;  
import javax.imageio.ImageWriteParam;  
import javax.imageio.ImageWriter;  
import javax.imageio.metadata.IIOMetadata;  
import javax.imageio.stream.ImageInputStream;  
import javax.imageio.stream.ImageOutputStream;  
  
import com.sun.media.imageio.plugins.tiff.TIFFImageWriteParam;

public class ImageConverGif{ 
public static File createImage(File imageFile, String imageFormat) {  
    File tempFile = null;  
    try {  
        Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName(imageFormat);  
        ImageReader reader = readers.next();  
      
        ImageInputStream iis = ImageIO.createImageInputStream(imageFile);  
        reader.setInput(iis);  
        //Read the stream metadata  
        IIOMetadata streamMetadata = reader.getStreamMetadata();  
          
        //Set up the writeParam  
        TIFFImageWriteParam tiffWriteParam = new TIFFImageWriteParam(Locale.CHINESE);  
        tiffWriteParam.setCompressionMode(ImageWriteParam.MODE_DISABLED);  
          
        //Get tif 
        Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("tiff");  
        ImageWriter writer = writers.next();  
          
        BufferedImage bi = reader.read(0);  
        IIOImage image = new IIOImage(bi,null,reader.getImageMetadata(0));  
        tempFile = tempImageFile(imageFile);  
        ImageOutputStream ios = ImageIO.createImageOutputStream(tempFile);  
        writer.setOutput(ios);  
        writer.write(streamMetadata, image, tiffWriteParam);  
        ios.close();  
          
        writer.dispose();  
        reader.dispose();  
          
    } catch (IOException e) {  
        e.printStackTrace();  
    }  
    return tempFile;  
}  

private static File tempImageFile(File imageFile) {  
    String path = imageFile.getPath();  
    StringBuffer strB = new StringBuffer(path);  
    strB.insert(path.lastIndexOf('.'),0);  
    return new File(strB.toString().replaceFirst("(?<=//.)(//w+)$", "tif"));  
}  

} 
View Code

6. 创建类OCRTif.java,用于识别本地验证码,并返回验证码字符串

Tesseract-OCR识别验证码Tesseract-OCR识别验证码
package testNG;

//import java.awt.image.BufferedImage;
import java.io.BufferedReader;  
import java.io.File;  
import java.io.FileInputStream;  
import java.io.IOException;
import java.io.InputStreamReader;  
import java.util.ArrayList;  
import java.util.List;  

//import javax.imageio.ImageIO;

//import org.apache.james.mime4j.util.ContentUtil;
/***
 * 
 *   
 * @author tuanFu
 *
 */

//OCR识别图片验证码,
public class OCRTif {  
    //private final String LANG_OPTION = "-l";  //小写英文字母l(L),并非数字1  
    private final String LS = System.getProperty("line.separator");  
    //private String tessPath = "E:/Program Files/Tesseract-OCR";  //Tesseract-OCR 安装路径
    //private String tessPath = new File("tesseract").getAbsolutePath();  
    //tessPath为Tesseract-OCR安装地址
    public String recognizeText(File imageFile,String imageFormat, String tessPath)throws Exception{  
        
        File tempImage = ImageConverGif.createImage(imageFile,imageFormat);  
        File outputFile = new File(imageFile.getParentFile(),"output");  
        StringBuffer strB = new StringBuffer();  
        List<String> cmd = new ArrayList<String>();  
        cmd.add(tessPath+"//tesseract");   
        cmd.add("");  
        cmd.add(outputFile.getName());  
        //cmd.add(LANG_OPTION);  
        //cmd.add("chi_sim");  
        //cmd.add("eng");  
          
        ProcessBuilder pb = new ProcessBuilder();  
        pb.directory(imageFile.getParentFile());  
          
        cmd.set(1, tempImage.getName());  
        pb.command(cmd);  
        pb.redirectErrorStream(true);  
          
        Process process = pb.start();  
        //tesseract.exe 1.jpg 1 -l chi_sim  
        int w = process.waitFor();    
    
  
        //删除临时正在工作文件  
        tempImage.delete();  
  
        if(w==0){  
            BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(outputFile.getAbsolutePath()+".txt"),"UTF-8"));  
  
            String str;  
            while((str = in.readLine())!=null){  
                strB.append(str).append(LS);  
            }  
            in.close();  
        }else{  
            String msg;  
            switch(w){  
                case 1:  
                    msg = "Errors accessing files.There may be spaces in your image's filename.";  
                    break;  
                case 29:  
                    msg = "Cannot recongnize the image or its selected region.";  
                    break;  
                case 31:  
                    msg = "Unsupported image format.";  
                    break;  
                default:  
                    msg = "Errors occurred.";  
            }  
            tempImage.delete();  
            throw new RuntimeException(msg);  
        }  
        new File(outputFile.getAbsolutePath()+".txt").delete();
        Thread.sleep(3000);
        return strB.toString();  
    }  
    
    /**文件转换
    public static void converter(File imgFile,String format,File formatFile)
            throws IOException{
        BufferedImage bIMG =ImageIO.read(imgFile);
        ImageIO.write(bIMG, format, formatFile);
    }
    **/
    public static void main(String[] args) throws IOException {  
        
        String path = "http:...//captcha.png"; 
        //converter(new File(path),"jpeg", new File("d:\\psb2.jpg"));
        String tessPath = "E:/Program Files/Tesseract-OCR";//Tesseract-OCR install path
        try {  
            String valCode = new OCRTif().recognizeText(new File(path), "png",tessPath);  //png为当前文件类型
            System.out.println(valCode);  
        } catch (IOException e) {  
            e.printStackTrace();  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
    }
} 
View Code

7. 创建类XiaoWeiLogin.java,验证效果。

Tesseract-OCR识别验证码Tesseract-OCR识别验证码
package testNG;

import java.awt.image.BufferedImage;

import javax.imageio.ImageIO;

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

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.annotations.Test;

public class XiaoWeiLogin 
{    

    @Test
    public static WebDriver xiaoWeiLogin() throws Exception
    {
        String failMSG = "登录失败";
        String tag = null;//用于控制登录失败后,重新登录
        String baseDataPath = "E:\\workspace\\1506\\testNG\\testdata\\testData.xlsx";
        BaseClass data = new BaseClass();
        String xiaoWeiIssuerURL = data.getBaseData("xiaoWeiIssuerURL", baseDataPath);
        String inPath = data.getBaseData("inPath", baseDataPath);
        String outPath = data.getBaseData("outPath", baseDataPath);
        String TesseractOCRPath = data.getBaseData("Tesseract-OCRPath", baseDataPath);
        String userId = data.getData_xlsx("Login", "xiaoWeiUserId", inPath);
        String pwd = data.getData_xlsx("Login", "xiaoWeiUserPwd", inPath);
        String firefoxPath= data.getBaseData("firefoxPath",baseDataPath);
        String userIdXPath = "//*[@id='j_username']";
        String pwdXPath = "//*[@id='j_password']";
        String codeXpath = "//*[@id='codeImg']";
        String checkCode ="//*[@id='checkCode']";

        System.setProperty("webdriver.firefox.bin",firefoxPath);
        WebDriver driver = new FirefoxDriver();
        driver.get(xiaoWeiIssuerURL);
        driver.manage().window().maximize();
        while (tag == null)
        {    //刷新
            driver.navigate().refresh();
            BaseClass.getElement(driver, "xpath", userIdXPath).clear();
            BaseClass.getElement(driver, "xpath", userIdXPath).sendKeys(userId);
            driver.findElement(By.xpath(pwdXPath)).clear();
            driver.findElement(By.xpath(pwdXPath)).sendKeys(pwd);    
            WebElement keyWord = driver.findElement(By.xpath(codeXpath));
            if(keyWord!=null)
               {  
                   String src =  keyWord.getAttribute("src");  
                   BaseClass.println(BaseClass.nowDate()+"  验证码地址 ="+src);  
                   if(src!=null && !"".equals(src))
                   { 
                       //截屏并保存本地
                       GetNetImgAndSave.snapshot2(driver,"1111111111.png",baseDataPath);  
                       BufferedImage bi = GetNetImgAndSave.createElementImage(driver,keyWord);  
                       ImageIO.write(bi, "png", new File("e://testasdasd.png"));   
                       //Tesseract-OCR识别本地验证码,并获取结果
                       OCRTif ocr = new OCRTif();
                       String key= ocr.recognizeText(new File("e://testasdasd.png"), 
                               "png", TesseractOCRPath);  
                       //去除空格、换行、制表符等
                       String noBlankStr = BaseClass.replaceBlank(key);
                       //验证码输入框  
                       BaseClass.println(BaseClass.nowDate()+"  ==========key:"+noBlankStr+"==========");
                       BaseClass.println(BaseClass.nowDate()+"  ==========获取到的验证码长度:"+noBlankStr.length()+
                               "==========");
                       
                       if (data.isDigitStr(noBlankStr)){
                           if (noBlankStr.length()==4) 
                           {    
                               BaseClass.println(BaseClass.nowDate()+"  验证码长度正确,尝试登录");
                               driver.findElement(By.xpath(checkCode)).clear();
                               driver.findElement(By.xpath(checkCode)).sendKeys(noBlankStr);
                               driver.findElement(By.xpath("//*[@id='loginForm']/"
                                          + "table/tbody/tr/td[2]/table[3]/tbody/tr/td[2]/img")).click();
                               driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
                               try {
                                       driver.findElement(By.xpath("//*[contains(.,'"
                                           + failMSG + "')]"));
                                       System.out.println(BaseClass.nowDate()+"  验证码错误,重新登录");
                                       BaseClass.writeLog("验证码错误,重新登录");
                                       continue;
                                       //driver.close();
                               } catch (Exception e) {    
                                   System.out.println(BaseClass.nowDate()+"  登录成功");
                                   BaseClass.writeLog("login success!");
                                   data.screenShot(data.getBaseData("screenShotDir", baseDataPath), 
                                                  driver, "xiaoWeiLogin");
                                   driver.close();
                                   tag = "success";
                                   String nowDate = BaseClass.nowDate();
                                   data.outCome_xlsx("xiaoWeiLogin", "pass", outPath, nowDate);
                                   data.openOutCome(outPath);
                                   break;
                               }
                           
                           }else{
                               BaseClass.println(BaseClass.nowDate()+"  验证码长度错误,重新登录");
                               BaseClass.writeLog("验证码长度错误,重新登录");
                               //driver.close();
                           } 
                       }else{ 
                               BaseClass.println(BaseClass.nowDate()+"  验证码非纯数字,重新登录");
                            BaseClass.writeLog("验证码非纯数字,重新登录");
                               //driver.close();
                    }
                         
                 }
            }  
        }
        return driver;
    }

    public static void main(String[] args) throws Exception 
    {
        // TODO 自动生成的方法存根

        XiaoWeiLogin.xiaoWeiLogin();
        
    }    
}
View Code

日志打印如下:

Tesseract-OCR识别验证码

8. 说明。

  本次只是识别纯数字验证码,识别成功率在50%左右,如果需要识别特定语言的验证码,需要加入语言包,并在代码中加上语言参数

9. 参考资料:

  http://songpo-ath-taobao-com.iteye.com/blog/1664226