selenium 过网页版抖音滑块

selenium 过网页版抖音滑块,滑块未测试, java 测试ok。失业好久了,java 爬虫没前途

 

打开小姐姐个人主页  https://www.douyin.com/user/MS4wLjABAAAAcHcG7GZFPOBmv0E4OGWn-KR4d-xxJ6VtsNLBRcNcb7Xtg5h3Vv_otohQsjBsxfpb 就会出现验证码

 

 

将 大的 div 保存为图片,即 class 为 captcha_verify_container 的 div 保存为图片, java 代码 

 // 查找目标 <div> 元素 --wrapper
        WebElement divElement = driver.findElement(By.className("captcha_verify_container"));
        WebElement imageElement = driver.findElement(By.id("captcha-verify-image"));
        if(divElement == null || imageElement == null) {
            return false;
        }

        // 创建 Actions 对象
        Actions actions = new Actions(driver);

        // 获取元素的位置和大小
        Rectangle rect = divElement.getRect();

        String res = devTools.send(Page.captureScreenshot(
                Optional.of(Page.CaptureScreenshotFormat.PNG),
                Optional.empty(),
                Optional.of(new Viewport((double)rect.getX(), (double)rect.getY(), (double)rect.getWidth(), (double)rect.getHeight(), 1.0)),
                Optional.empty(),
                Optional.empty(),
                Optional.empty()
        ));




        // 保存截图为文件
        byte[] screenshotData = Base64.getDecoder().decode(res);
        

            Path screenshotPath = Paths.get(imagePath);
            Files.write(screenshotPath, screenshotData, StandardOpenOption.CREATE);
            System.out.println("Screenshot saved: " + screenshotPath.toAbsolutePath());

 

原因,图片中的  "依次点击 喳 双 团" 是一张图片 , 不是 文字,是文字会方便很多,如果是文字,图片就直接从 class 为 ”captcha_verify_img--wrapper“ 的 div 会方便很多。

现在不是文字,另外的方案,从 class 为 ”captcha_verify_bar“ 获取图片,再对接第三方OCR识别出 ”喳 双 团“, 再从 class 为 ”captcha_verify_img--wrapper“ 获取图片

现在方案,直接将 class 为 captcha_verify_container 的 div 保存为图片,假设为 图片 1

 仅仅将 class 为 "captcha_verify_img--wrapper" 保存为图片,假设为 图片2

图片1是 475 * 435, 图片2 是 425 * 265

经过分析,画出如下草图(逆时针旋转90°)

 

 

将 图片1 接入打码平台,假设获取到3个坐标点  (x1,y1) (x2,y2) (x3,y3)

actions.moveToElement(divElement, x1,y1).click().perform(); 这样肯定是不能通过的 (这里的 divElement 本来我是打算用 imageElement ,没想到测试通过了 )

 

 

 

如图(上面说的图2一样),debug 的时候,发现 红色1的坐标的 (0,0),   红色2的坐标是 (-169,-105), 其实应该是 (-170, -106), 整个长宽就是 170*2=340,106*2=212,

上面说到,图片2的长宽是 425*265,缩放比例是  425 / 340=1.25  265/212=1.25

所以,打码获取到的 x 和 y 的坐标,需要重新计算

    public static int rex(int x) {
        double d = x;
        d = d - 25 - 212.5;
        d = d / 1.25;
        return new BigDecimal(String.valueOf(d)).intValue();
    }

    public static int rey(int y) {
        double d = y;
        d = d - 85 - 132.5;
        d = d / 1.25;
        return new BigDecimal(String.valueOf(d)).intValue();
    }

首先 x 要减去 25,y 要减去 85,看那个草图

x 再要减去 212.5,整个 长度是 425 , 中间的坐标点是 (0,0), 425 / 2 = 212.5, y 再减去  132.5

再等比缩放 1.25 即可。

整个代码 随便看看

 

import com.alibaba.fastjson.JSONObject;
import com.common.util.CommonUtils;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.openqa.selenium.By;
import org.openqa.selenium.Dimension;
import org.openqa.selenium.Rectangle;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.devtools.DevTools;
import org.openqa.selenium.devtools.v113.page.Page;
import org.openqa.selenium.devtools.v113.page.model.Viewport;
import org.openqa.selenium.interactions.Actions;

import java.io.File;
import java.io.FileInputStream;
import java.math.BigDecimal;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Base64;
import java.util.Optional;

public class TestDevTools2 {



    static String imagePath = "C:\\particularElementScreenshot.PNG";
    static String chromePath = "D:\\java_project\\chromedriver.exe";


    public static void main(String[] args) {


        System.setProperty("webdriver.chrome.driver", chromePath);
        ChromeOptions options = new ChromeOptions();
        options.addArguments("--disable-blink-features=AutomationControlled");
        options.addArguments("disable-infobars");
        options.addArguments("start-maximized");
        options.addArguments("ignore-certificate-errors");
        options.addArguments("--remote-allow-origins=*");
        options.setExperimentalOption("excludeSwitches", new String[]{"enable-automation"});
        options.setExperimentalOption("useAutomationExtension", false);

        // Initialize browser
        ChromeDriver driver = null;
        DevTools devTools = null;
        try {
            driver = new ChromeDriver(options);

            // 使用 DevTools API 进行截图
            devTools = driver.getDevTools();
            devTools.createSession();
            // 增加等待时间
            //driver.manage().timeouts().setScriptTimeout(Duration.ofSeconds(30));

            driver.manage().window().setSize(new Dimension(627, 537));
          //  driver.manage().timeouts().pageLoadTimeout(30, TimeUnit.SECONDS);

            // 导航到包含目标 <div> 元素的页面
            driver.get("https://www.douyin.com/user/MS4wLjABAAAAcHcG7GZFPOBmv0E4OGWn-KR4d-xxJ6VtsNLBRcNcb7Xtg5h3Vv_otohQsjBsxfpb");



            needCheck(driver, devTools);

            //
            System.out.println("获取数据");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if(driver != null) {
                driver.quit();
            }
        }
    }


    public static boolean needCheck(ChromeDriver driver, DevTools devTools) {

        CommonUtils.sleepMillisecond(10000);

        // 查找目标 <div> 元素 --wrapper
        WebElement divElement = driver.findElement(By.className("captcha_verify_container"));
        WebElement imageElement = driver.findElement(By.id("captcha-verify-image"));
        if(divElement == null || imageElement == null) {
            return false;
        }

        // 创建 Actions 对象
        Actions actions = new Actions(driver);

        //actions.moveToElement(imageElement, 0, 0).click().perform();;

        // 获取元素的位置和大小
        Rectangle rect = divElement.getRect();

        String res = devTools.send(Page.captureScreenshot(
                Optional.of(Page.CaptureScreenshotFormat.PNG),
                Optional.empty(),
                Optional.of(new Viewport((double)rect.getX(), (double)rect.getY(), (double)rect.getWidth(), (double)rect.getHeight(), 1.0)),
                Optional.empty(),
                Optional.empty(),
                Optional.empty()
        ));




        // 保存截图为文件
        byte[] screenshotData = Base64.getDecoder().decode(res);
        try {
            Path screenshotPath = Paths.get(imagePath);
            Files.write(screenshotPath, screenshotData, StandardOpenOption.CREATE);
            System.out.println("Screenshot saved: " + screenshotPath.toAbsolutePath());

            File file = new File(imagePath);
            String resultString= Jsoup.connect("http://api.ttshitu.com/predict")
                    .data("username", "---------------------------------")
                    .data("password", "---------------------------------")
                    .data("typeid", "27")
                    .data("remark", "")
                    .data("image", file.getName(), new FileInputStream(file)).ignoreContentType(true).timeout(120000).post().text();


            // {"code":"0","data":{"result":"173,190|362,177|133,295","id":"UsWi7VEyRZy7SvvLnJ6HjQ"},"success":true,"message":"success"}
            JSONObject jsonObject = JSONObject.parseObject(resultString);
            System.out.println(jsonObject);

            String result = Optional.ofNullable(jsonObject).map(t -> t.getJSONObject("data")).map(t -> t.getString("result")).orElse(null);
            System.out.println(result);

            if(StringUtils.isBlank(result)) {
                return false;
            }

            String[] strs = result.split("\\|");
            if(strs == null || strs.length < 1) {
                return false;
            }

           

             for(String s : strs) {
                String[] ss = s.trim().split(",");
                if(ss != null && ss.length == 2){
                    int x = Integer.parseInt(ss[0].trim());
                    int y = Integer.parseInt(ss[1].trim());
                    System.out.println(s + " , " + x  + ", " + y + " -> " + rex(x) + ", " + rey(y));
                    // 这里打算使用 imageElement ,测试的时候居然用 divElement 通过了,
                    actions.moveToElement(divElement, rex(x), rey(y)).click().perform();
                  
                     CommonUtils.sleepMillisecond(2000);
                }
            }

            //


            // actions.moveByOffset(410, 395).click().perform();
            divElement = driver.findElement(By.className("verify-captcha-submit-button"));
            if(divElement != null) {
                divElement.click();
            }
            CommonUtils.sleepMillisecond(5000);

            divElement = driver.findElement(By.className("captcha_verify_container"));
            if(driver != null) {
                return needCheck(driver, devTools);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return false;
    }

    public static int rex(int x) {
        double d = x;
        d = d - 25 - 212.5;
        d = d / 1.25;
        return new BigDecimal(String.valueOf(d)).intValue();
    }

    public static int rey(int y) {
        double d = y;
        d = d - 85 - 132.5;
        d = d / 1.25;
        return new BigDecimal(String.valueOf(d)).intValue();
    }
}


        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>4.9.1</version>
        </dependency>

        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-chrome-driver</artifactId>
            <version>4.9.1</version>
        </dependency>

        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-remote-driver</artifactId>
            <version>4.9.1</version>
        </dependency>

        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-devtools-v111</artifactId>
            <version>4.9.1</version>
        </dependency>

        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-api</artifactId>
            <version>4.9.1</version>
        </dependency>

 

===================== 经过测试,很完美 很专业 ================

将代码放到其他地方测试,没通过,发现 大图变成了 380 * 348, 小图成了 340 * 212,假设大图左上角的坐标是(0,0),小图左上角的坐标就是(20,68)

340 / 2 = 170, 212 / 2 = 106 所以 重新计算坐标

    public static int rex(int x) {
        double d = x;
        d = d - 20 - 170;
        d = d / 1;
        return new BigDecimal(String.valueOf(d)).intValue();
    }

    public static int rey(int y) {
        double d = y;
        d = d - 68 - 106;
        d = d / 1;
        return new BigDecimal(String.valueOf(d)).intValue();
    }

测试发现,上面除以 1.25, 这里除以1,不知道是不是与电脑分辨率有关。

    

 

 大致思路就是这样。

 

posted @ 2023-08-09 01:12  safetys  阅读(246)  评论(0编辑  收藏  举报