整套实现用到了selenium的jar包,chromedriver.exe驱动,opencv_java340-x64.dll图像处理文件。运行环境是windows,jdk1.8,项目是maven的~~因为属于半实验的项目,所以做的非常糙,后期大家自己继续改造吧~下面上代码一一说明吧~
1.入口程序加载需要的资源,定义必要的变量~
public static String basePath = "D:\\test\\";
public static String FULL_IMAGE_NAME = "full-image";
public static String BG_IMAGE_NAME = "bg-image";
public static int[][] moveArray = new int[52][2];
public static boolean moveArrayInit = false;
public static String INDEX_URL = "https://1111.com";
public static WebDriver driver;
public void run() throws InterruptedException {
System.setProperty("webdriver.chrome.driver", "F:\\spring\\ESController\\src\\main\\java\\chromedriver.exe");
if (!System.getProperty("os.name").toLowerCase().contains("windows")){
System.setProperty("webdriver.chrome.driver", "/Users/wangyang/workspace/selenium/chromedriver_V2.30/chromedriver");
}
driver = new ChromeDriver();
System.load("F:\\spring\\ESController\\opencv_java340-x64.dll");
String[] us = {"用户名集合"};
String[] ps = {"密码集合"};
for(int i = 0; i < us.length; i++) {
try {
invoke(us[i] , ps[i]);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
driver.quit();
}
2.循环开始,这里所有的css样式需要各位换成目标项目的样式,也可以用id或者其他属性进行web页面的元素定位(非通用!非通用!非通用!)
public void invoke(String us , String ps) throws IOException, InterruptedException {
//设置input参数
driver.get(INDEX_URL);
By moveBtn = By.cssSelector(".ui-slider-wrap .ui-slider-btn");
waitForLoad(driver, moveBtn);
WebElement moveElemet = driver.findElement(moveBtn);
moveElemet.click();
By successBtn = By.cssSelector(".ui-slider-wrap .ui-slider-no-select");
waitForLoad(driver, successBtn);
WebElement successElemet = driver.findElement(successBtn);
int i = 0;
while (i++ < 1000){
waitForLoad(driver, successBtn);
if(successElemet.isEnabled() && "验证成功".equals(successElemet.getText().split(",")[0])) {
By nameinput = By.cssSelector(".eleWrapperNew .userName");
waitForLoad(driver, nameinput);
WebElement nameinputElemet = driver.findElement(nameinput);
String nameId = nameinputElemet.getAttribute("id");
String js1 = "document.getElementById(\""+nameId+"\").value=\""+us+"\"";//将display属性修改为block的js代码
((JavascriptExecutor) driver).executeScript(js1);
By passwordinput = By.cssSelector(".eleWrapperNew .password");
waitForLoad(driver, passwordinput);
WebElement passwordinputElemet = driver.findElement(passwordinput);
passwordinputElemet.click();
String str = ps;
String[] singleCharacters = str.split("");
for (int ii = 0; ii < singleCharacters.length; ii++)
{
if (singleCharacters[ii]!="")
{
passwordinputElemet.sendKeys(singleCharacters[ii]);
Thread.sleep(500);
}
}
By loginButton = By.id("loginButton");
waitForLoad(driver, loginButton);
WebElement loginButtonElemet = driver.findElement(loginButton);
loginButtonElemet.click();
By kkkkk = By.cssSelector(".mr36");
waitForLoad(driver, kkkkk);
WebElement kkkkkElemet = driver.findElement(kkkkk);
kkkkkElemet.click();
System.out.println("验证成功!继续继续!");
i = 10001;
}else {
int distance = getMoveDistance(driver , i);
waitForLoad(driver, moveBtn);
try {
move(driver, moveElemet, distance);
}catch(Exception e) {
}
i++;
}
Thread.sleep(2000);
}
}
3.计算平移的距离,这里面用到了之前提到的图像处理,通过图像的灰度来计算底图与滑块之间的移动距离。其中保存图片的时候我修改了页面的属性,要不然底图和滑块我保存不下来~~同时保存了这些处理之后的图,想在未来做一个图库精简目前的计算步骤~
public static int getMoveDistance(WebDriver driver , int i) throws IOException, InterruptedException {
//String pageSource = driver.getPageSource();
String bignonejs = "document.getElementById(\"smallImage\").parentNode.style.backgroundColor=\"white\"";//将display属性修改为block的js代码
((JavascriptExecutor) driver).executeScript(bignonejs);
Thread.sleep(500);
By smallImage = By.id("smallImage");
waitForLoad(driver, smallImage);
WebElement smallImageElemet = driver.findElement(smallImage);
File smallFile = smallImageElemet.getScreenshotAs(OutputType.FILE);
try {
String savePath = basePath + FULL_IMAGE_NAME + i + ".png";
//复制内容到指定文件中
FileUtils.copyFile(smallFile, new File(savePath));
} catch (IOException e) {
e.printStackTrace();
}
String bigblockjs = "document.getElementById(\"smallImage\").parentNode.style.backgroundColor=\"\"";//将display属性修改为block的js代码
((JavascriptExecutor) driver).executeScript(bigblockjs);
//String fullImageUrl = getFullImageUrl(pageSource);
//FileUtils.copyURLToFile(new URL(fullImageUrl), new File(basePath + FULL_IMAGE_NAME + i + ".jpg"));
String nonejs = "document.getElementById(\"smallImage\").style.display=\"none\"";//将display属性修改为block的js代码
((JavascriptExecutor) driver).executeScript(nonejs);
Thread.sleep(500);
By bigImage = By.id("bigImage");
waitForLoad(driver, bigImage);
WebElement bigImageElemet = driver.findElement(bigImage);
File bigFile = bigImageElemet.getScreenshotAs(OutputType.FILE);
try {
String savePath = basePath + BG_IMAGE_NAME + i + ".png";
//复制内容到指定文件中
FileUtils.copyFile(bigFile, new File(savePath));
} catch (IOException e) {
e.printStackTrace();
}
String blockjs = "document.getElementById(\"smallImage\").style.display=\"block\"";//将display属性修改为block的js代码
((JavascriptExecutor) driver).executeScript(blockjs);
Thread.sleep(500);
//String getBgImageUrl = getBgImageUrl(pageSource);
//FileUtils.copyURLToFile(new URL(getBgImageUrl), new File(basePath + BG_IMAGE_NAME + i + ".jpg"));
//initMoveArray(driver);
//restoreImage(FULL_IMAGE_NAME + i);
//restoreImage(BG_IMAGE_NAME + i);
BufferedImage fullBI = ImageIO.read(new File(basePath + FULL_IMAGE_NAME + i + ".png"));
BufferedImage bgBI = ImageIO.read(new File(basePath + BG_IMAGE_NAME + i + ".png"));
setWhite(fullBI);
ImageIO.write(fullBI, "png", new File(basePath + FULL_IMAGE_NAME + i + ".png"));
Mat s_mat = Imgcodecs.imread(new File(basePath + FULL_IMAGE_NAME + i + ".png").getPath());
Mat b_mat = Imgcodecs.imread(new File(basePath + BG_IMAGE_NAME + i + ".png").getPath());
// 转灰度图像
Mat s_newMat = new Mat();
Mat b_newMat = new Mat();
Imgproc.cvtColor(s_mat, s_newMat, Imgproc.COLOR_BGR2GRAY);
Imgproc.cvtColor(b_mat, b_newMat, Imgproc.COLOR_BGR2GRAY);
Imgcodecs.imwrite(new File(basePath + FULL_IMAGE_NAME + i + ".png").getPath(), s_newMat);
Imgcodecs.imwrite(new File(basePath + BG_IMAGE_NAME + i + ".png").getPath(), b_newMat);
// 自适应阈值化
Mat s_nMat = new Mat();
Imgproc.adaptiveThreshold(s_newMat, s_nMat, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY, 7, -4);
Imgcodecs.imwrite(new File(basePath + FULL_IMAGE_NAME + i + ".png").getPath(), s_nMat);
Mat b_nMat = new Mat();
Imgproc.adaptiveThreshold(b_newMat, b_nMat, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY, 7, -4);
Imgcodecs.imwrite(new File(basePath + BG_IMAGE_NAME + i + ".png").getPath(), b_nMat);
b_mat = Imgcodecs.imread(new File(basePath + BG_IMAGE_NAME + i + ".png").getPath());
s_mat = Imgcodecs.imread(new File(basePath + FULL_IMAGE_NAME + i + ".png").getPath());
int result_rows = b_mat.rows() - s_mat.rows() + 1;
int result_cols = b_mat.cols() - s_mat.cols() + 1;
Mat g_result = new Mat(result_rows, result_cols, CvType.CV_32FC1);
Imgproc.matchTemplate(b_mat, s_mat, g_result, Imgproc.TM_CCOEFF); // 相关系数匹配法
Core.normalize(g_result, g_result, 0, 1, Core.NORM_MINMAX, -1, new Mat());
org.opencv.core.Point matchLocation = new org.opencv.core.Point();
MinMaxLocResult mmlr = Core.minMaxLoc(g_result);
matchLocation = mmlr.maxLoc; // 此处使用maxLoc还是minLoc取决于使用的匹配算法
Imgproc.rectangle(b_mat, matchLocation, new org.opencv.core.Point(matchLocation.x + s_mat.cols(), matchLocation.y + s_mat.rows()), new Scalar(0, 255, 0, 0));
Imgcodecs.imwrite(basePath + "dx"+i+".png", b_mat);
double a = matchLocation.x + 15;
return Double.valueOf(a).intValue();
//(matchLocation.x + s_mat.cols() - sBI.getWidth()) * 3 / 4 - 8);
//throw new RuntimeException("未找到需要平移的位置");
}
4.计算完移动距离,然后根据滑块位置进行移动操作。
public static void move(WebDriver driver, WebElement element, int distance) throws InterruptedException {
int xDis = distance + 11;
System.out.println("应平移距离:" + xDis);
int moveX = new Random().nextInt(8) - 5;
int moveY = 1;
Actions actions = new Actions(driver);
new Actions(driver).clickAndHold(element).perform();
Thread.sleep(200);
printLocation(element);
actions.moveToElement(element, moveX, moveY).perform();
//System.out.println(moveX + "--" + moveY);
printLocation(element);
for (int i = 0; i < 22; i++){
int s = 10;
if (i % 2 == 0){
s = -10;
}
actions.moveToElement(element, s, 1).perform();
// printLocation(element);
Thread.sleep(new Random().nextInt(100) + 150);
}
//System.out.println(xDis + "--" + 1);
actions.moveByOffset(xDis, 1).perform();
printLocation(element);
Thread.sleep(200);
actions.release(element).perform();
}
5.还有一些公共方法~
public static void waitForLoad(final WebDriver driver, final By by){
new WebDriverWait(driver, 10).until(new ExpectedCondition() {
public Boolean apply(WebDriver d) {
WebElement element = driver.findElement(by);
if (element != null){
return true;
}
return false;
}
});
}
private static void printLocation(WebElement element){
Point point = element.getLocation();
System.out.println(point.toString());
}
整体上就利用selenium完成了滑块验证码的操作~
希望给大家有所帮助~欢迎讨论~~