1. 程式人生 > >JAVA + Selenium + 易源識別圖片驗證碼模擬註冊

JAVA + Selenium + 易源識別圖片驗證碼模擬註冊

“易源資料”圖片識別API說明文件地址:https://www.showapi.com/api/lookPoint/184

程式碼模擬的也是“易源資料”的賬號註冊,主要程式碼如下:

模擬註冊入口-YiYuanUtil.java

package com.vps.api.util;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Date;

import javax.imageio.ImageIO;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
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.chrome.ChromeDriver;

import com.vps.Constants;
import com.vps.api.vo.YiYuanCodeVo;
import com.vps.common.Config;

import flexjson.JSONDeserializer;

/**
 * 易源模擬註冊工具類
 * 
 * @author nangongyanya
 * 
 */
public class YiYuanUtil {

	/**
	 * 模擬註冊
	 * 
	 * @param webAddress
	 * @param usernameId
	 * @param username
	 * @param emailId
	 * @param email
	 * @param pwdId
	 * @param pwd
	 * @param comfirmId
	 * @param codeImgId
	 * @param codeValueId
	 * @param agreeId
	 * @param buttonId
	 * @param codeType
	 * @throws InterruptedException 
	 */
	public static void reg(String webAddress, String usernameId, String username, String emailId, String email,
			String pwdId, String pwd, String comfirmName, String codeImgId, String codeValueId, String agreeId,
			String buttonId, Integer codeType) throws InterruptedException {
		/** 獲取谷歌外掛地址 */
		String chromdriverPath = "C:\\program_agent\\Google\\Chrome\\Application\\chromedriver.exe";
		if (StringUtils.isNotBlank(Config.getString("chromedriver_path"))) {
			chromdriverPath = Config.getString("chromedriver_path");
		}

		/** 使用谷歌瀏覽器開啟易源註冊頁面 */
		System.setProperty("webdriver.chrome.driver", chromdriverPath);// chromedriver服務地址
		WebDriver driver = new ChromeDriver();
		driver.get(webAddress);

		/** 填寫註冊資料 */
		driver.findElement(By.id(usernameId)).sendKeys(username);// 填寫使用者名稱
		driver.findElement(By.id(emailId)).sendKeys(email);// 填寫郵箱
		driver.findElement(By.id(pwdId)).sendKeys(pwd);// 填寫密碼
		driver.findElement(By.name(comfirmName)).sendKeys(pwd);// 確認密碼
		driver.findElement(By.id(codeValueId)).sendKeys(getCodeValue(driver, codeImgId, codeType)
				.toLowerCase());// 填寫驗證碼
		driver.findElement(By.id(agreeId)).click(); // 同意服務條款
		Thread.sleep(3000);// 等待3秒,檢視資料填充情況
		driver.findElement(By.id(buttonId)).click(); // 點選註冊按鈕
		
		Thread.sleep(5000);// 等待5秒,檢視註冊結果
		driver.quit();// 關閉瀏覽器
	}
	
	/**
	 * 獲取驗證碼
	 * 
	 * @param driver
	 * @param codeImgId
	 * @param codeType
	 * @return
	 */
	public static String getCodeValue(WebDriver driver, String codeImgId, Integer codeType) {
		/** 下載驗證碼 */
		String imgFile = downloadVerificationCode(driver, codeImgId);
		/** 使用易源介面獲取驗證碼內容 */
		String imgBase64 = ImageBase64Util.getLocalImgBase64(imgFile);
		String result = chatAndNumByBase64(imgBase64, codeType);
		YiYuanCodeVo vo = new JSONDeserializer<YiYuanCodeVo>().deserialize(result, YiYuanCodeVo.class);
		String codeValue = vo.getShowapi_res_body().getResult();
		
		return codeValue;
	}
	
	/**
	 * 下載驗證碼
	 * 
	 * @param driver
	 * @param codeImgId
	 * @return
	 */
	public static String downloadVerificationCode(WebDriver driver, String codeImgId) {
		try {
			/** 設定圖片名稱 */
			Date now = new Date();
			String imageName = getAppPath() + "uploads/verification_code/" + now.getTime() + ".jpg";
			
			WebElement ele = driver.findElement(By.id(codeImgId));// 獲取驗證碼元素
			((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView();", ele);// 滾動條滾動至驗證碼位置
			Thread.sleep(3000);// 等待3秒,等待js執行完成

			/** 計算網頁被捲去的高,即滾動條滾動距離 */
			String jsStr = "var yScroll; if (self.pageYOffset) { yScroll = self.pageYOffset; } else if (document.documentElement && document.documentElement.scrollTop) { yScroll = document.documentElement.scrollTop; } else if (document.body) { yScroll = document.body.scrollTop; } return yScroll;";
			Long rollHeight = (Long) ((JavascriptExecutor) driver).executeScript(jsStr);
			// System.out.println("網頁被捲去的高: " + rollHeight);

			/** 儲存驗證碼 */
			File screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
			BufferedImage fullImg;
			fullImg = ImageIO.read(screenshot);
			Point point = ele.getLocation();
			int eleWidth = ele.getSize().getWidth();
			int eleHeight = ele.getSize().getHeight();
			BufferedImage eleScreenshot = fullImg.getSubimage(point.getX(), point.getY() - rollHeight.intValue(),
					eleWidth, eleHeight);
			ImageIO.write(eleScreenshot, "jpg", screenshot);
			File screenshotLocation = new File(imageName);
			FileUtils.copyFile(screenshot, screenshotLocation);
			
			return imageName;
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return null;
	}
	
	/**
	 * 獲取專案根路徑
	 * 
	 * @return
	 * @throws InterruptedException 
	 * @throws IOException 
	 */
	public static final String getAppPath() {
		String path = Thread.currentThread().getContextClassLoader().getResource("").getPath();
		path = path.substring(0, path.indexOf("WEB-INF"));
		if (System.getProperties().get("os.name").toString().toLowerCase().contains("windows")) {
			path = path.substring(1, path.length());
		} else {
			path = File.separator.concat(path);
		}
		return path;
	}
	
	/**
	 * 驗證碼識別英數_base64
	 * 
	 * @param imgBase64
	 * @param typeId
	 * @return
	 */
	public static String chatAndNumByBase64(String imgBase64, Integer typeId) {
		try {
			String urlStr = "http://route.showapi.com/184-5?showapi_appid="
					+ Constants.YIYUAN_APPID_TEST + "&showapi_sign="
					+ Constants.YIYUAN_APPID_SECRET + "&img_base64="
					+ URLEncoder.encode(imgBase64, "utf-8")
					+ "&convert_to_jpg=1" + "&typeId=" + typeId;
			URL u = new URL(urlStr);
			InputStream in = u.openStream();
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			try {
				byte buf[] = new byte[1024];
				int read = 0;
				while ((read = in.read(buf)) > 0) {
					out.write(buf, 0, read);
				}
			} finally {
				if (in != null) {
					in.close();
				}
			}
			byte b[] = out.toByteArray();
			System.out.println(new String(b, "utf-8"));
			return new String(b, "utf-8");
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return null;
	}

	public static void main(String[] args) throws InterruptedException, IOException {
		// TODO 以下引數需要後臺定製
		String webAddress = "https://www.showapi.com/auth/reg";// 網頁地址
		String usernameId = "name";// 使用者名稱ID
		String username = "situxuanbin";// 使用者名稱
		String emailId = "email";// 郵箱ID
		String email = username + "@163.com";// 郵箱
		String pwdId = "pwd";// 密碼ID
		String pwd = "92863945";// 密碼
		String comfirmName = "repwd";// 確認密碼ID
		String codeImgId = "checkImg";// 驗證碼圖片ID
		String codeValueId = "checkCode";// 驗證碼輸入框ID
		String agreeId = "fwtk";// 服務條款ID
		String buttonId = "regBtn";// 註冊按鈕ID
		/**
		 * 注意:最大支援10位的驗證碼。 1.純數字
		 * typeId=10 任意長度數字,識別率會降低
		 * typeId=11 1位數字
		 * typeId=12 2位數字
		 * ...
		 * typeId=19 9位數字
		 * 
		 * 2.純英文
		 * typeId=20 任意長度英文,識別率會降低
		 * typeId=21 1位英文
		 * typeId=22 2位英文
		 * ...
		 * typeId=29 9位英文
		 * 
		 * 3.英文數字混合
		 * typeId=30 任意長度英數混合,識別率會降低
		 * typeId=31 1位英數
		 * typeId=32 2位英數混合
		 * ...
		 * typeId=39 9位英數混合
		 */
		Integer codeType = 35; // 驗證碼型別
		reg(webAddress, usernameId, username, emailId, email, pwdId, pwd, comfirmName, codeImgId, codeValueId, agreeId,
				buttonId, codeType);
	}
}

圖片轉Base64字串工具類-ImageBase64Util.java

package com.vps.api.util;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import com.thoughtworks.xstream.core.util.Base64Encoder;

/**
 * 圖片轉Base64字串工具類
 * 
 * @author nangongyanya
 * 
 */
public class ImageBase64Util {

	/**
	 * 獲取線上圖片base64字串
	 * 
	 * @param imgUrlStr
	 * @return
	 */
	public static String getOnlineImgBase64(String imgUrlStr) {
		byte[] data = null;  
        try {  
            URL url = new URL(imgUrlStr);// 建立URL    
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();// 建立連結    
            conn.setRequestMethod("GET");  
            conn.setConnectTimeout(5 * 1000);  
            InputStream inStream = conn.getInputStream();  
            data = new byte[inStream.available()];  
            inStream.read(data);  
            inStream.close();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
        Base64Encoder encoder = new Base64Encoder();// 對位元組陣列Base64編碼    
        return encoder.encode(data);// 返回Base64編碼過的位元組陣列字串  
	}
	
	/**
	 * 獲取本地圖片base64字串
	 * 
	 * @param imgUrlStr
	 * @return
	 */
	public static String getLocalImgBase64(String imgFile) {
		InputStream in = null;  
        byte[] data = null;  
  
        /** 讀取圖片位元組陣列 */ 
        try {  
            in = new FileInputStream(imgFile);  
              
            data = new byte[in.available()];  
            in.read(data);  
            in.close();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
        Base64Encoder encoder = new Base64Encoder();// 對位元組陣列Base64編碼    
        return encoder.encode(data);// 返回Base64編碼過的位元組陣列字串 
	}

}

易源驗證碼vo類-YiYuanCodeBodyVo.java

package com.vps.api.vo;

import com.common.util.json.BaseFlexjson;

/**
 * 易源驗證碼vo
 * 
 * @author nangongyanya
 * 
 */
public class YiYuanCodeBodyVo extends BaseFlexjson {

	private String Result;
	private Integer ret_code;
	private String Id;

	public String getResult() {
		return Result;
	}

	public void setResult(String result) {
		Result = result;
	}

	public Integer getRet_code() {
		return ret_code;
	}

	public void setRet_code(Integer ret_code) {
		this.ret_code = ret_code;
	}

	public String getId() {
		return Id;
	}

	public void setId(String id) {
		Id = id;
	}

}

易源解析驗證碼返回結果vo類-YiYuanCodeVo.java

package com.vps.api.vo;

import com.common.util.json.BaseFlexjson;

/**
 * 易源解析驗證碼返回結果vo
 * 
 * @author nangongyanya
 * 
 */
public class YiYuanCodeVo extends BaseFlexjson {

	private String showapi_res_error;
	private Integer showapi_res_code;
	private YiYuanCodeBodyVo showapi_res_body;

	public String getShowapi_res_error() {
		return showapi_res_error;
	}

	public void setShowapi_res_error(String showapi_res_error) {
		this.showapi_res_error = showapi_res_error;
	}

	public Integer getShowapi_res_code() {
		return showapi_res_code;
	}

	public void setShowapi_res_code(Integer showapi_res_code) {
		this.showapi_res_code = showapi_res_code;
	}

	public YiYuanCodeBodyVo getShowapi_res_body() {
		return showapi_res_body;
	}

	public void setShowapi_res_body(YiYuanCodeBodyVo showapi_res_body) {
		this.showapi_res_body = showapi_res_body;
	}

}

如有疑問歡迎在評論區留言交流!