自动化识别验证码 UI方式+接口方式

欢迎大家加群,共同讨论测试自动化,qq群:436370465
登录时经常要识别验证码
下面提供2种方式
1.UI方式
通过截图方式会去到验证码图片,借助打码平台识别验证码

首先截取验证码图片
import lombok.extern.slf4j.Slf4j;
import org.openqa.selenium.*;
import org.apache.commons.io.FileUtils;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
@Slf4j
public class Base {
/**
* UI方式获取验证码截图
* 验证码截图
*
* @param driver
* @param by
* @return
* @throws IOException
*/
public String verificationCodeScreenshot(WebDriver driver, By by) throws IOException {
String screenShotDirPath = System.getProperty("user.dir") + File.separator + "target" + File.separator + "test-output" + File.separator + "png" + File.separator;
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HHmmssSSS");
String time = simpleDateFormat.format(new Date());
try {
log.info("准备截取图片验证码图片到本地");
WebElement element = driver.findElement(by);
// 获取验证码x,y轴坐标
Point location = element.getLocation();
// 获取验证码的长宽
int x = location.getX();
int y = location.getY();
int width = element.getSize().getWidth();
int height = element.getSize().getHeight();
//截屏
File screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
BufferedImage fullImg = ImageIO.read(screenshot);
//裁剪出验证码的截图
BufferedImage eleScreenshot = fullImg.getSubimage(location.getX(), location.getY(), width, height);
ImageIO.write(eleScreenshot, "png", screenshot);
//储存到指定位置
File screenshotLocation = new File(screenShotDirPath + time + "verify.png");
FileUtils.copyFile(screenshot, screenshotLocation);
log.info("成功保存验证码图片");
} catch (WebDriverException | IOException e) {
e.printStackTrace();
}
return screenShotDirPath + time + "verify.png";

}

}

然后将图片传给打码平台(我这边用的图鉴 ttshitu),获取验证码结果
/**
* 通过打码平台(图鉴)查找验证码
*
* @param filePath
* @return
* @throws IOException
*/
public String getVerificationCodeByttshitu(String filePath) throws IOException {
String ttshituHost = PropertyReader.getValue("ttshitu.host");
//用户名与密码我是写在了配置文件,从配置文件读取
String ttshituUsername = PropertyReader.getValue("ttshitu.username");
String ttshituPassword = PropertyReader.getValue("ttshitu.password");
String typeid = "3";
String remark = "输出计算结果";
InputStream inputStream = null;
File needRecoImage = new File(filePath);
inputStream = new FileInputStream(needRecoImage);
Map<String, String> data = new HashMap<>(20);
data.put("username", ttshituUsername);
data.put("password", ttshituPassword);
data.put("typeid", typeid);
data.put("remark", remark);

    String resultString = "";
    for (int i = 0; i < 5; i++) {
        try {
            log.info("图鉴地址是:" + ttshituHost);
            resultString = Jsoup.connect(ttshituHost)
                    .data(data).data("image", "test.jpg", inputStream)
                    .ignoreContentType(true)
                    .post().text();
            break;
        } catch (Exception e) {
            log.info("链接图鉴失败,准备尝试");
            try {
                Thread.sleep(3000);
            } catch (InterruptedException interruptedException) {
                interruptedException.printStackTrace();
            }
        }
    }

    JSONObject jsonObject = JSONObject.parseObject(resultString);
    String result = "";
    if (jsonObject.getBoolean("success")) {
        result = jsonObject.getJSONObject("data").getString("result");
        log.info("识别成功结果为:" + result);
    } else {
        log.info("识别失败原因为:" + jsonObject.getString("message"));
    }

    return result;


}

2.通过接口方式获取到验证码的密文报文,借助打码平台识别验证码
首先观察接口 拿到密文的图片压缩信息(与加密方式有关,我这边试base64)

/**
     * 接口方式取验证码信息(base64加密的一串密文),传给打码平台返回验证码
     * @return
     */
    @SneakyThrows
    public String getVerificationCodeByAPi(){
      //能返回验证码信息的接口
      JsonObject imageObj=userActive(manager);
      //取出返回的验证码密文信息(我这边是base64加密的一串密文)
      String image=imageObj.get("image").getAsString();
      //调用打码平台识别验证码(图鉴)
      String verifyCode = getVerificationCodeBybase64(image);
      log.info("图片验证码是:"+verifyCode);
      return verifyCode;
    }
    /**
     * 通过imagebase64的方式获得图片验证码
     *
     * @param imagebase64
     * @return
     * @throws IOException
     */
    public String getVerificationCodeBybase64(String imagebase64) throws IOException {
        String ttshituHost = PropertyReader.getValue(ttHost);
        String ttshituUsername = PropertyReader.getValue(ttUsername);
        String ttshituPassword = PropertyReader.getValue(ttPassword);
        String typeid = "3";
        String remark = "输出计算结果";
        InputStream inputStream = null;


        Map<String, String> data = new HashMap<>(20);
        data.put("username", ttshituUsername);
        data.put("password", ttshituPassword);
        data.put("typeid", "3");
        data.put("remark", remark);
        data.put("image", imagebase64);
        String result = "";
        String resultString = "";
        for (int i = 0; i < 3; i++) {
            try {
                log.info("图鉴地址是:" + ttshituHost);
                resultString = Jsoup.connect(ttshituHost)
                        .requestBody(JSON.toJSONString(data))
                        .header("Content-Type", "application/json")
                        .ignoreContentType(true).timeout(120000).post().text();
                JSONObject jsonObject = JSONObject.parseObject(resultString);
                if (jsonObject.getBoolean("success")) {
                    result = jsonObject.getJSONObject("data").getString("result");
                    System.out.println("识别成功结果为:" + result);
                    break;
                } else {
                    System.out.println("识别失败原因为:" + jsonObject.getString("message"));
                }

            } catch (Exception e) {
                log.info("链接图鉴失败,准备尝试");
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException interruptedException) {
                    interruptedException.printStackTrace();
                }
            }
        }
        return result;


    }
posted @ 2022-04-14 16:22  小黑ようちょう  阅读(548)  评论(0)    收藏  举报