selenium-web滑块验证码-java

    整套实现用到了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完成了滑块验证码的操作~

希望给大家有所帮助~欢迎讨论~~

你可能感兴趣的:(笔记,web滑块验证码,selenium,前端,java)