From 8d3d8ee7bc3a926db16a995bc8fd0a8362a28d54 Mon Sep 17 00:00:00 2001 From: zhaohui Date: Mon, 29 Dec 2025 10:05:22 +0800 Subject: [PATCH] init3 --- .gitignore | 3 + .../SeleniumLoginWithCookieRecorder.java | 390 ++++++++++++++++----- src/main/resources/META-INF/MANIFEST.MF | 2 +- 3 files changed, 314 insertions(+), 81 deletions(-) diff --git a/.gitignore b/.gitignore index 84adb3f..8811092 100644 --- a/.gitignore +++ b/.gitignore @@ -22,4 +22,7 @@ # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* +.vscode/ +target/ +target/classes/META-INF/MANIFEST.MF diff --git a/src/main/java/com/seleniumLib/SeleniumLoginWithCookieRecorder.java b/src/main/java/com/seleniumLib/SeleniumLoginWithCookieRecorder.java index 7c38282..171e157 100644 --- a/src/main/java/com/seleniumLib/SeleniumLoginWithCookieRecorder.java +++ b/src/main/java/com/seleniumLib/SeleniumLoginWithCookieRecorder.java @@ -15,6 +15,8 @@ import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.nio.file.Paths; import java.time.Duration; import java.util.List; import java.util.Map; @@ -34,6 +36,8 @@ import com.google.gson.JsonObject; import com.google.gson.JsonArray; import com.google.gson.JsonParser; +import java.nio.file.Files; + /** * Selenium 模拟登录并获取 Cookie 的示例 * 支持多种登录方式:表单登录、OAuth、AJAX 登录等 @@ -93,7 +97,7 @@ public class SeleniumLoginWithCookieRecorder { // 转换为 JSON String jsonParams = gson.toJson(params); - System.out.println("请求参数: " + jsonParams); + // System.out.println("请求参数: " + jsonParams); // 设置请求体 httpPost.setEntity(new StringEntity(jsonParams, "UTF-8")); @@ -101,7 +105,7 @@ public class SeleniumLoginWithCookieRecorder { // 发送请求 try (CloseableHttpResponse response = httpClient.execute(httpPost)) { String responseBody = EntityUtils.toString(response.getEntity(), "UTF-8"); - System.out.println("API 响应: " + responseBody); + // System.out.println("API 响应: " + responseBody); // 解析响应 return extractCaptchaFromResponse(responseBody); @@ -138,7 +142,7 @@ public class SeleniumLoginWithCookieRecorder { /** * 初始化 WebDriver */ - public void setupDriver() { + public void setupDriver(String proxy) { // 自动下载和管理 ChromeDriver @@ -152,6 +156,13 @@ public class SeleniumLoginWithCookieRecorder { // Chrome 选项配置 ChromeOptions options = new ChromeOptions(); + // 配置SOCKS5代理 + if (proxy != null && !proxy.isEmpty()) { + String proxyConfig = "--proxy-server=" + proxy; + options.addArguments(proxyConfig); + System.out.println("已配置SOCKS5代理: " + proxyConfig); + } + // 可选:无头模式(不显示浏览器界面) // options.addArguments("--headless"); options.addArguments("--headless=new"); @@ -205,6 +216,9 @@ public class SeleniumLoginWithCookieRecorder { // [1, 2, 3, 4, 5]})"); // driver.executeScript("Object.defineProperty(navigator, 'languages', {get: () // => ['zh-CN', 'zh', 'en']})"); + // 设置超时时间 + driver.manage().timeouts().pageLoadTimeout(Duration.ofSeconds(60)); + driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10)); wait = new WebDriverWait(driver, Duration.ofSeconds(15)); System.out.println("WebDriver 初始化完成"); @@ -213,15 +227,31 @@ public class SeleniumLoginWithCookieRecorder { /** * 通用表单登录 */ - public void loginToCrossCheck(String username, String password, String filePath) { + public void loginToCrossCheck(String username, String password, String filePath, String tenant, + String capture_path) { try { System.out.println("开始 Crossref 登录流程..."); // 打开登录页面 - driver.get("https://crossref-26027.turnitin.com/originality/inbox/713daa1b-0685-4cc7-89ec-6b6c7cbc0411"); - + // driver.get("https://crossref-26027.turnitin.com/originality/inbox/713daa1b-0685-4cc7-89ec-6b6c7cbc0411"); + // driver.get("https://" + tenant + ".turnitin.com/home/sign-in"); // 增加页面加载等待时间 - Thread.sleep(3000); // 等待5秒确保页面完全加载 + // Thread.sleep(3000); // 等待5秒确保页面完全加载 + try { + // 增加超时设置 + driver.manage().timeouts().pageLoadTimeout(Duration.ofSeconds(60)); + driver.get("https://" + tenant + ".turnitin.com/home/sign-in"); + // 等待页面元素出现而不是固定等待 + WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(30)); + wait.until(ExpectedConditions.presenceOfElementLocated(By.id("username"))); + } catch (TimeoutException e) { + // 记录日志并尝试刷新页面 + System.err.println("页面加载超时,尝试刷新..."); + driver.navigate().refresh(); + // 再次等待元素出现 + WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(30)); + wait.until(ExpectedConditions.presenceOfElementLocated(By.id("username"))); + } // 调试:打印页面标题和URL System.out.println("当前页面标题: " + driver.getTitle()); @@ -271,58 +301,18 @@ public class SeleniumLoginWithCookieRecorder { // 输入用户名 usernameField.clear(); usernameField.sendKeys(username); - System.out.println("已输入用户名"); + System.out.println("已输入用户名: " + username); // 输入密码 WebElement passwordField = extendedWait .until(ExpectedConditions.visibilityOfElementLocated(By.id("password"))); passwordField.clear(); passwordField.sendKeys(password); - System.out.println("已输入密码"); + System.out.println("已输入密码: " + password); Thread.sleep(3000); // 验证码处理 - String cap_first = "0"; - try { - WebElement captchaImage = extendedWait - .until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("img[alt='Captcha image']"))); - String src1 = captchaImage.getAttribute("src"); - - if (src1 != null && !src1.isEmpty()) { - src1 = src1.replace("data:image/png;base64,", "").replace("\n", "").trim(); - System.out.println("验证码图片URL: " + src1); - - String result_cap = this.recognizeCaptcha(src1 + "YII="); - System.out.println("验证码识别结果: " + result_cap); - - if (result_cap != null && !result_cap.trim().isEmpty()) { - result_cap = result_cap.replace(" ", ""); - WebElement captchaField = extendedWait - .until(ExpectedConditions.visibilityOfElementLocated(By.id("captcha-input"))); - captchaField.clear(); - captchaField.sendKeys(result_cap); - System.out.println("已输入验证码"); - // captureScreenshot("captcha_done"); - Thread.sleep(3000); - } - } - } catch (Exception e) { - System.out.println("未找到验证码或验证码处理失败: " + e.getMessage()); - cap_first = "1"; - - } - - // 点击登录按钮 - WebElement signinButton = extendedWait.until( - ExpectedConditions.elementToBeClickable(By.cssSelector("button[data-testid='sign-in-btn']"))); - signinButton.click(); - System.out.println("已点击登录按钮"); - - boolean isLoggedIn = isLoggedIn(); - - // 处理验证码 - if (cap_first.equals("1") && !isLoggedIn) { - Thread.sleep(3000); - // 验证码处理 + // String cap_first = "0"; + for (int i = 0; i < 3; i++) { try { WebElement captchaImage = extendedWait .until(ExpectedConditions @@ -331,36 +321,157 @@ public class SeleniumLoginWithCookieRecorder { if (src1 != null && !src1.isEmpty()) { src1 = src1.replace("data:image/png;base64,", "").replace("\n", "").trim(); - System.out.println("验证码图片URL2: " + src1); + // System.out.println("验证码图片URL: " + src1); String result_cap = this.recognizeCaptcha(src1 + "YII="); - System.out.println("验证码识别结果2: " + result_cap); - + System.out.println("验证码识别结果" + (i + 1) + ": " + result_cap); if (result_cap != null && !result_cap.trim().isEmpty()) { result_cap = result_cap.replace(" ", ""); WebElement captchaField = extendedWait .until(ExpectedConditions.visibilityOfElementLocated(By.id("captcha-input"))); captchaField.clear(); captchaField.sendKeys(result_cap); - System.out.println("已输入验证码2"); - // captureScreenshot("captcha_done"); + System.out.println("已输入验证码" + (i + 1) + ": " + result_cap); + if (!capture_path.isEmpty()) { + captureScreenshot("captcha_write_done" + (i + 1), capture_path); + } Thread.sleep(3000); } - - // 点击登录按钮 - WebElement signinButton2 = extendedWait.until( - ExpectedConditions - .elementToBeClickable(By.cssSelector("button[data-testid='sign-in-btn']"))); - signinButton2.click(); - System.out.println("已点击登录按钮2"); } } catch (Exception e) { - System.out.println("未找到验证码或验证码处理失败2: " + e.getMessage()); + System.out.println("未找到验证码或验证码处理失败" + (i + 1) + ": " + e.getMessage()); + // cap_first = "1"; + } + + // 点击登录按钮 + WebElement signinButton = extendedWait.until( + ExpectedConditions.elementToBeClickable(By.cssSelector("button[data-testid='sign-in-btn']"))); + signinButton.click(); + Thread.sleep(13000); + System.out.println("已点击登录按钮" + (i + 1)); + if (!capture_path.isEmpty()) { + captureScreenshot("login_button_click" + (i + 1), capture_path); + } + + boolean isLoggedIn = isLoggedIn(); + if (isLoggedIn) { + // System.out.println("登录成功"); + break; + } else { + try { + // 获取错误提示文本 + WebElement boldText = driver.findElement(By.cssSelector("wi-banner.error b")); + String errorText = boldText.getText(); + System.out.println("登录错误提示" + (i + 1) + ": " + errorText); + // 如果错误提示包含"Invalid username or password",则继续循环 + if (errorText.contains("Too many attempts")) { + System.out.println("登录次数太多"); + break; + } + } catch (Exception e) { + System.out.println("未找到登录错误提示处理失败" + (i + 1) + ": " + e.getMessage()); + // cap_first = "1"; + } } + Thread.sleep(15000); } + /* + * // 第二次处理验证码 + * if (cap_first.equals("1") || !isLoggedIn) { + * Thread.sleep(3000); + * // 验证码处理 + * try { + * WebElement captchaImage = extendedWait + * .until(ExpectedConditions + * .presenceOfElementLocated(By.cssSelector("img[alt='Captcha image']"))); + * String src1 = captchaImage.getAttribute("src"); + * + * if (src1 != null && !src1.isEmpty()) { + * src1 = src1.replace("data:image/png;base64,", "").replace("\n", "").trim(); + * // System.out.println("验证码图片URL2: " + src1); + * + * String result_cap = this.recognizeCaptcha(src1 + "YII="); + * System.out.println("验证码识别结果2: " + result_cap); + * + * if (result_cap != null && !result_cap.trim().isEmpty()) { + * result_cap = result_cap.replace(" ", ""); + * WebElement captchaField = extendedWait + * .until(ExpectedConditions.visibilityOfElementLocated(By.id("captcha-input"))) + * ; + * captchaField.clear(); + * captchaField.sendKeys(result_cap); + * System.out.println("已输入验证码2: " + result_cap); + * if (!capture_path.isEmpty()) { + * captureScreenshot("captcha_write_done2", capture_path); + * } + * Thread.sleep(3000); + * } + * + * // 点击登录按钮 + * WebElement signinButton2 = extendedWait.until( + * ExpectedConditions + * .elementToBeClickable(By.cssSelector("button[data-testid='sign-in-btn']"))); + * signinButton2.click(); + * System.out.println("已点击登录按钮2"); + * if (!capture_path.isEmpty()) { + * captureScreenshot("login_button_click2", capture_path); + * } + * } + * } catch (Exception e) { + * System.out.println("未找到验证码或验证码处理失败2: " + e.getMessage()); + * } + * } + * + * isLoggedIn = isLoggedIn(); + * // 第三次次处理验证码 + * if (!isLoggedIn) { + * Thread.sleep(3000); + * // 验证码处理 + * try { + * WebElement captchaImage = extendedWait + * .until(ExpectedConditions + * .presenceOfElementLocated(By.cssSelector("img[alt='Captcha image']"))); + * String src1 = captchaImage.getAttribute("src"); + * + * if (src1 != null && !src1.isEmpty()) { + * src1 = src1.replace("data:image/png;base64,", "").replace("\n", "").trim(); + * // System.out.println("验证码图片URL2: " + src1); + * + * String result_cap = this.recognizeCaptcha(src1 + "YII="); + * System.out.println("验证码识别结果3: " + result_cap); + * + * if (result_cap != null && !result_cap.trim().isEmpty()) { + * result_cap = result_cap.replace(" ", ""); + * WebElement captchaField = extendedWait + * .until(ExpectedConditions.visibilityOfElementLocated(By.id("captcha-input"))) + * ; + * captchaField.clear(); + * captchaField.sendKeys(result_cap); + * System.out.println("已输入验证码3: " + result_cap); + * if (!capture_path.isEmpty()) { + * captureScreenshot("captcha_write_done3", capture_path); + * } + * Thread.sleep(3000); + * } + * + * // 点击登录按钮 + * WebElement signinButton3 = extendedWait.until( + * ExpectedConditions + * .elementToBeClickable(By.cssSelector("button[data-testid='sign-in-btn']"))); + * signinButton3.click(); + * System.out.println("已点击登录按钮3"); + * if (!capture_path.isEmpty()) { + * captureScreenshot("login_button_click3", capture_path); + * } + * } + * } catch (Exception e) { + * System.out.println("未找到验证码或验证码处理失败3: " + e.getMessage()); + * } + * } + */ // 等待登录结果 - Thread.sleep(3000); + Thread.sleep(5000); // 检查登录是否成功 try { @@ -368,12 +479,20 @@ public class SeleniumLoginWithCookieRecorder { // System.out.println("登录成功,当前URL: " + driver.getCurrentUrl()); // 获取并保存 Cookie - isLoggedIn = isLoggedIn(); + boolean isLoggedIn = isLoggedIn(); if (isLoggedIn) { saveNPCookiesToFile("crossref", filePath); System.out.println("登录成功"); } else { System.out.println("登录失败"); + // // 获取错误提示文本 + WebElement boldText2 = driver.findElement(By.cssSelector("wi-banner.error b")); + String errorText2 = boldText2.getText(); + System.out.println("登录错误提示: " + errorText2); + + if (!capture_path.isEmpty()) { + captureScreenshot("login_error", capture_path); + } } } catch (Exception e) { @@ -544,10 +663,13 @@ public class SeleniumLoginWithCookieRecorder { */ public void loadCookiesFromFile(String filename) { try { + // 文件中保存的是Netscape 格式的 Cookie 怎么改下面的代码 + CookieData cookieData = objectMapper.readValue(new File(filename), CookieData.class); - // 先导航到 Cookie 的域名 - driver.get(cookieData.getUrl()); + // 先导航到 Cookie 的域名,https://crossref-26027.turnitin.com/home/ + // driver.get(cookieData.getUrl()); + driver.get("https://crossref-26027.turnitin.com/home/"); // 清空现有 Cookie driver.manage().deleteAllCookies(); @@ -571,14 +693,72 @@ public class SeleniumLoginWithCookieRecorder { } } + public void loadCookiesAndAccessSite(String cookieFile, String targetUrl, String capture_path) { + try { + // 先导航到目标网站 + driver.get(targetUrl); + + // 读取 Cookie 文件 + List lines = Files.readAllLines(Paths.get(cookieFile), StandardCharsets.UTF_8); + + // 清空现有 Cookie + driver.manage().deleteAllCookies(); + + // 解析并添加 Cookie + for (String line : lines) { + line = line.trim(); + if (line.isEmpty() || line.startsWith("#")) { + continue; + } + + String[] parts = line.split("\t"); + if (parts.length >= 6) { + try { + String domain = parts[0].startsWith(".") ? parts[0].substring(1) : parts[0]; + String name = parts[5]; + String value = parts.length > 6 ? parts[6] : ""; + + // 移除值中的引号 + if (value.startsWith("\"") && value.endsWith("\"")) { + value = value.substring(1, value.length() - 1); + } + + // 创建并添加 Cookie + Cookie cookie = new Cookie.Builder(name, value) + .domain(domain) + .path(parts[2]) + .isSecure("TRUE".equalsIgnoreCase(parts[3])) + .build(); + + driver.manage().addCookie(cookie); + System.out.println("已添加 Cookie: " + name); + + } catch (Exception e) { + // 简单忽略解析错误的行 + } + } + } + + // 刷新页面使 Cookie 生效 + driver.navigate().refresh(); + System.out.println("Cookie 加载完成,页面已刷新"); + Thread.sleep(5000); + if (!capture_path.isEmpty()) { + captureScreenshot("login_refresh", capture_path); + } + } catch (Exception e) { + System.err.println("处理 Cookie 文件失败: " + e.getMessage()); + } + } + /** * 截图保存 */ - private void captureScreenshot(String filename) { + private void captureScreenshot(String filename, String capture_path) { try { File screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE); String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); - File dest = new File("screenshot_" + filename + "_" + timestamp + ".png"); + File dest = new File(capture_path + "screenshot_" + filename + "_" + timestamp + ".png"); com.google.common.io.Files.copy(screenshot, dest); System.out.println("截图已保存: " + dest.getAbsolutePath()); } catch (Exception e) { @@ -621,22 +801,72 @@ public class SeleniumLoginWithCookieRecorder { SeleniumLoginWithCookieRecorder recorder = new SeleniumLoginWithCookieRecorder(); try { - // 1. 初始化驱动 - recorder.setupDriver(); - if (args.length != 3) { - System.err.println("请提供用户名、密码和文件路径作为参数"); + String user_name = ""; + String password = ""; + String filePath = ""; + String proxy = ""; + String tenant = "crossref-26027"; + String help = "0"; + String capture_path = ""; + + // 传的参数增加参数名 + for (int i = 0; i < args.length; i++) { + if (args[i].equals("-u")) { + user_name = args[i + 1]; + } else if (args[i].equals("-p")) { + password = args[i + 1]; + } else if (args[i].equals("-f")) { + filePath = args[i + 1]; + } else if (args[i].equals("-proxy")) { + proxy = args[i + 1]; + } else if (args[i].equals("-t")) { + tenant = args[i + 1]; + } else if (args[i].equals("-help")) { + help = "1"; + } else if (args[i].equals("-capture_path")) { + capture_path = args[i + 1]; + // capture_path 以-开头或为空,默认当前目录 + if (capture_path.startsWith("-") || capture_path.isEmpty()) { + capture_path = "./"; + } + // 如果 capture_path 不以/结尾,添加/ + if (!capture_path.endsWith("/")) { + capture_path += "/"; + } + + } + } + if (help.equals("1")) { + System.out.println("参数说明:"); + System.out.println("-u '用户名',必填"); + System.out.println("-p '密码',必填"); + System.out.println("-f 保存 Cookie 的文件路径及文件名,必填"); + System.out.println("-t 租户 ID(可选,默认crossref-26027)"); + System.out.println("-proxy 代理配置,可选(例如 'socks5://host:port')"); + System.out.println("-capture_path '截图保存路径'(没有此参数,则不截图;有参数不设置路径,默认当前目录'./')"); + System.out.println("-help: 显示帮助信息"); return; } - if (args[0].isEmpty() || args[1].isEmpty() || args[2].isEmpty()) { - System.err.println("用户名、密码或文件路径不能为空"); + + if (user_name.isEmpty() || password.isEmpty() || filePath.isEmpty()) { + System.err.println("用户名、密码、文件路径不能为空。-help 查看帮助信息1111"); return; } - String user_name = args[0]; - String password = args[1]; - String filePath = args[2]; + // 1. 初始化驱动(带代理配置) + recorder.setupDriver(proxy); + + // 如果文件存在,加载文件中的 Cookie + // if (Files.exists(Paths.get(filePath))) { + // System.out.println("文件存在,加载文件中的 Cookie:" + filePath); + // String loginUrl = "https://" + tenant + ".turnitin.com/home"; + // recorder.loadCookiesAndAccessSite(filePath, loginUrl, capture_path); + // } + // System.exit(0); + // return; // 2. Crossref 登录示例(需要替换为真实账号) - recorder.loginToCrossCheck(user_name, password, filePath); + + recorder.loginToCrossCheck(user_name, password, filePath, tenant, capture_path); // 3. 验证登录状态 boolean isLoggedIn = recorder.isLoggedIn(); diff --git a/src/main/resources/META-INF/MANIFEST.MF b/src/main/resources/META-INF/MANIFEST.MF index c9b9b69..8687f1e 100644 --- a/src/main/resources/META-INF/MANIFEST.MF +++ b/src/main/resources/META-INF/MANIFEST.MF @@ -1,3 +1,3 @@ Manifest-Version: 1.0 -Main-Class: com.seleniumLib.crossrefDownLib +Main-Class: com.seleniumLib.SeleniumLoginWithCookieRecorder