Jmeter验证码识别插件实战笔记

唉~,做个Web端的性能测试,第一步遇到的难题就是万恶的图形验证码,大家都知道验证码的处理有以下几点:
1、找个善良乐于助人的开发大大帮忙屏蔽一下验证码
2、如果你和开发大大关系够铁,开个后门,整个万能验证码
3、以上两种都不可以的话,掀桌(╯' - ')╯︵ ┻━┻走人~,

emmmm,开玩笑的,赶紧快马加鞭的gun回来。以上两种如果都不可以的话,咱们只能通过暴力手段,把开发打残了。还是开个玩笑了,毕竟是法制社会呢!言归正传,以上两种都不可以,咱们只能写一个识别验证码的插件了。
主要是参考大神的文章,我只是代码的搬运工https://blog.csdn.net/xreztento/article/details/48682923

一、准备工具

1、Tesseract,图形图像识别工具
2、ApacheJmeter_core.jar,
3、 jorphon.jar
4、logkit-2.0.jar
5、jai-imageio-1.1.jar
6、 swingx-1.6.1.jar
7、eclipse

二、安装Tesseract,将需要用的jar包导入到工程下

Jmeter验证码识别插件实战笔记_第1张图片

三、新建如下类

ImageIOHelper.java

import java.awt.Color;
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 ImageIOHelper{
public static File createImage(File imageFile, String imageFormat) {

    File tempFile = null;
    ImageInputStream iis = null;
    ImageOutputStream ios = null;
    ImageReader reader = null;
    ImageWriter writer = null;

    try {
        Iterator readers = ImageIO.getImageReadersByFormatName(imageFormat);
        reader = readers.next();

        iis = ImageIO.createImageInputStream(imageFile);
        reader.setInput(iis);

        IIOMetadata streamMetadata = reader.getStreamMetadata();
                    TIFFImageWriteParam tiffWriteParam = new TIFFImageWriteParam(Locale.CHINESE);
        tiffWriteParam.setCompressionMode(ImageWriteParam.MODE_DISABLED);
        Iterator writers = ImageIO.getImageWritersByFormatName("tiff");
        writer = writers.next();

        BufferedImage bi = removeBackgroud(reader.read(0));
        IIOImage image = new IIOImage(bi,null,reader.getImageMetadata(0));
        tempFile = tempImageFile(imageFile);

        ios = ImageIO.createImageOutputStream(tempFile);
        writer.setOutput(ios);
        writer.write(streamMetadata, image, tiffWriteParam);

    } catch (IOException e) {
        e.printStackTrace();
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } finally {
        if(iis != null){
            try {
                iis.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        if(ios != null){
            try {
                ios.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        if(writer != null){
            writer.dispose();
        }
        if(reader != null){
            reader.dispose();
        }

    }

    return tempFile;
}

private static File tempImageFile(File imageFile) {
    String path = imageFile.getPath();
    StringBuffer strB = new StringBuffer(path);
    return new File(strB.toString().replaceFirst("jpg", "tif"));
 
}
public static int isFilter(int colorInt) {  
    Color color = new Color(colorInt);
    if ((color.getRed() > 85 && color.getRed() < 255) 
            && (color.getGreen() > 85 && color.getGreen() < 255) 
            && (color.getBlue() > 85 && color.getBlue() < 255)) {  
        return 1;  
    }  
    return 0;
}  

public static BufferedImage removeBackgroud(BufferedImage img)  
        throws Exception {  
    int width = img.getWidth();  
    int height = img.getHeight();  
    for (int x = 0; x < width; ++x) {  
        for (int y = 0; y < height; ++y) {  
            if (isFilter(img.getRGB(x, y)) == 1) {  
                img.setRGB(x, y, Color.WHITE.getRGB());  
            }
        }  
    }  
    return img;
}
}

OCR.java

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;


public class OCR {
    private final String LANG_OPTION = "-l";
    private final String EOL = System.getProperty("line.separator");
    private String tessPath = "D://Tesseract-OCR";

    public String recognizeText(File imageFile,String imageFormat) {
        
        File tempImage = ImageIOHelper.createImage(imageFile,imageFormat);
        File outputFile = new File(imageFile.getParentFile(),"output" + imageFile.getName());
        StringBuffer sb = new StringBuffer();
        List cmd = new ArrayList();

        cmd.add(tessPath+"//tesseract");
        cmd.add("");
        cmd.add(outputFile.getName());
        cmd.add(LANG_OPTION);
        cmd.add("eng");     
        ProcessBuilder pb = new ProcessBuilder();
        pb.directory(imageFile.getParentFile());

        cmd.set(1, tempImage.getName());
        pb.command(cmd);
        pb.redirectErrorStream(true);

        Process process = null;
        BufferedReader in = null;
        int wait;
        try {
            process = pb.start();
            //tesseract.exe xxx.tif 1 -l eng
            wait = process.waitFor();
            if(wait == 0){
                in = new BufferedReader(new InputStreamReader(new FileInputStream(outputFile.getAbsolutePath()+".txt"),"UTF-8"));
                String str;
                while((str = in.readLine())!=null){
                    sb.append(str).append(EOL);
                }
                in.close();

            }else{

                tempImage.delete();
            }
            new File(outputFile.getAbsolutePath()+".txt").delete();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            if(in != null){
                try {
                    in.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }

        tempImage.delete();
        return sb.toString();
    }
}

VcodeExtractor.java

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Serializable;

import org.apache.jmeter.processor.PostProcessor;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.jmeter.testelement.AbstractScopedTestElement;
import org.apache.jmeter.threads.JMeterContext;
import org.apache.jmeter.threads.JMeterVariables;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.log.Logger;

public class VcodeExtractor extends AbstractScopedTestElement implements PostProcessor, Serializable{
    private static final Logger log = LoggingManager.getLoggerForClass();
    public void process() {
        // TODO Auto-generated method stub
        JMeterContext context = getThreadContext();
        SampleResult previousResult = context.getPreviousResult();
        if (previousResult == null) {
            return;
        }
        log.debug("VcodeExtractor processing result");

        String status = previousResult.getResponseCode();
        int id = context.getThreadNum();
        String imageName = id + ".jpg";

        if(status.equals("200")){
            byte[] buffer = previousResult.getResponseData();
            FileOutputStream out = null;
            File file = null;
            try {
                file = new File(imageName);
                out = new FileOutputStream(file);
                out.write(buffer);
                out.flush();

            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } finally {
                if(out != null){
                    try {
                        out.close();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }

              try {   
                String vcode = new OCR().recognizeText(file, "jpg"); 
                vcode = vcode.replace(" ", "").trim();

                JMeterVariables var = context.getVariables();
                var.put("vcode", vcode);
                var.put("vuser", String.valueOf(id));
                } catch (Exception e) {
                    e.printStackTrace();
                }    
        }

    }

}

VcodeExtractorGUI.java

import org.apache.jmeter.processor.gui.AbstractPostProcessorGui;
import org.apache.jmeter.testelement.TestElement;

public class VcodeExtractorGUI extends AbstractPostProcessorGui{

    public TestElement createTestElement() {
        // TODO Auto-generated method stub
        VcodeExtractor extractor = new VcodeExtractor();
        modifyTestElement(extractor);
        return extractor;
    }

    public String getLabelResource() {
        // TODO Auto-generated method stub
        return this.getClass().getName();
    }

    @Override
    public String getStaticLabel() {//设置显示名称
        // TODO Auto-generated method stub
        return "VcodeExtractor";
    }

    public void modifyTestElement(TestElement extractor) {
        // TODO Auto-generated method stub
        super.configureTestElement(extractor);

    }
}

以上前两个类是图像识别,后两个是Jmeter的UI部分。

四、咱们可以写一个测试类,看一下执行结果是否正确,测试类源码如下

ReadPicture.java

import java.io.File;
import java.io.IOException;

public abstract class ReadPicture {

     public static void main(String[] args) throws IOException {  
         File imageFile = new File("D://123.png");
         System.out.println(imageFile.getAbsolutePath());
         OCR ocr = new OCR();
         String recognizeText = ocr.recognizeText(imageFile, "png");
         System.out.println(recognizeText);
         
     }

}

执行测试类,结果如下图


Jmeter验证码识别插件实战笔记_第2张图片

五、生成插件

生成插件,直接在项目右键-> export->Runnable jar file,生成.jar文件。然后将生成的jar文件放在Jmeter的lib文件下的ext文件夹下。然后打开Jmeter,在后置处理器下会有验证码识别的插件。

你可能感兴趣的:(Jmeter验证码识别插件实战笔记)