java Selenium 滑块验证破解

目标

前两天发现个好玩的工具Selenium,可以模拟人进行游览器操作,赶紧趁热打铁玩个小demo,滑块验证现在使用普遍,就是为了验证是否是机器人,但是这个是可以破解的,且听我娓娓道来

思路

  1. 计算滑块距离
  2. 模拟人进行滑块拖动

解决

前提

Selenium 官网下载jar包,先搭建环境

第一个问题我在另一篇博客已经详细描述
现在是第二个问题如何拟人化的拖动滑块,滑的太快不行,太慢也不行,这里我提供别人用python的一种方案,可以用

public static void move(WebDriver driver, WebElement element, Integer[] track) 
throws InterruptedException {
     
        Actions actions = new Actions(driver);
        // 按下滑块
        new Actions(driver).clickAndHold(element).perform();

        for (int i : track) {
     
            actions.moveByOffset(i, 0).perform();
        }
        Thread.sleep(500);
        //释放
        actions.release(element).perform();

    }



// 获取运动轨迹
public static Integer[] getTrack(int distance){
     
        List<Integer> integers = new ArrayList<>();
//        distance += 20;
        int current = 0;
        double mid = (distance * 3) / 4;
        double t = 0.2;
        double v = 0.0;
        double v0 = 0;
        double move = 0.0;
        while (current < distance){
     
            int a = 0;
            if (current < mid){
     
                a = 2;
            }else {
     
                a = -3;
            }
            v0 = v;
            v = v0 + a * t;
            move = v0 * t + (0.5) * a * t * t;
            current += move;
            integers.add((int) CommandUtil.round(move));
        }
//        integers.addAll(Stream.of(-3, -3, -2, -2, -2, -2, -2, -1, -3, -4).collect(Collectors.toList()));
        return integers.toArray(new Integer[0]);
    }
    

由于我们计算的距离不一定十分准确,我们可以重试

   // 单个验证 重试次数
   int retryCount = 0;
   int i = 0;
   WebElement tcaptchaButtonEle = null;
   while (true){
     
       // 3次 是滑块验证单个图验证次数最多出现3次,否则会换图的
       if (retryCount % 3 == 0){
     
           retryCount = 0;
      	   // 滑块按钮元素
           tcaptchaButtonEle = webDriver.findElementById("tcaptcha_drag_thumb");
           System.out.println(tcaptchaButtonEle.getAttribute("class"));

           // 滑块背景图
           WebElement slideBgEle = webDriver.findElementById("slideBg");
           String slideBgPicUrl = slideBgEle.getAttribute("src");

           // 滑块元素
           WebElement slideBlockEle = webDriver.findElementById("slideBlock");
           String slideBlockPicUrl = slideBlockEle.getAttribute("src");
           String style = slideBlockEle.getAttribute("style");
           String[] split = style.split(";");
           // html中滑块的宽度
           double htmlBlockWidth = 0.0;
           // html中滑块x坐标
           double marginLeft = 0.0;

           for (String s : split) {
     
               if (s.contains("width")){
     
                   String px = s.replace("width: ", "").replace("px", "");
                   htmlBlockWidth = Double.parseDouble(px);
               }else if (s.contains("left")){
     
                   String px = s.replace("left: ", "").replace("px", "");
                   marginLeft = Double.parseDouble(px);
               }
           }
           System.out.println(htmlBlockWidth + "," + marginLeft);
           try {
     
				// 计算移动距离(基于上篇博客的代码)
               i = SlideUtils.calculateOffset(slideBgPicUrl, slideBlockPicUrl, htmlBlockWidth, marginLeft);
               // 误差
               i -= 20;
           } catch (Exception e) {
     
               e.printStackTrace();
           }
       }else {
     
           // 没有换图,那就不需要重新下载,直接修改距离
           // 如果距离不对,减少挪动距离,这个参数视情况而定
           i -= 15;
       }
       Thread.sleep(1000);

       System.out.println("移动距离 ==> "+ i);
       Integer[] track = getTrack(i);
       System.out.println("移动轨迹 ==> " + JSON.toJSONString(track));
       move(webDriver, tcaptchaButtonEle, track);

       Thread.sleep(1000);
       WebElement guideText = null;
       try {
     
           // 验证是否成功,因为滑块的图片基本会有这个字提示
           // 拖动下方滑块完成拼图   去找这个字元素id
           // 如果没有的话会报异常的,那就是通过了
           guideText = webDriver.findElementById("guideText");
       } catch (Exception e) {
     
           System.out.println("验证通过");
           break;
       }

//            Thread.sleep(3000);
		
       System.out.println("验证失败等待进行下一次重试");
       retryCount++;

   }
   // 回到父级的页面
   webDriver.switchTo().parentFrame();

   buttons = webDriver.findElementsByTagName("button");
   for (WebElement button : buttons) {
     
       String span = button.findElement(By.tagName("span")).getText();
       // 点击登录
       if (span.equals("登录")){
     
           button.click();
           Thread.sleep(2000);
           break;
       }
   }

总结

好玩!!!

你可能感兴趣的:(java,selenium,selenium,java)