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,不知道是不是与电脑分辨率有关。
大致思路就是这样。