李昭辉 1 month ago
parent
commit
8d3d8ee7bc
  1. 3
      .gitignore
  2. 390
      src/main/java/com/seleniumLib/SeleniumLoginWithCookieRecorder.java
  3. 2
      src/main/resources/META-INF/MANIFEST.MF

3
.gitignore

@ -22,4 +22,7 @@
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid* hs_err_pid*
.vscode/
target/
target/classes/META-INF/MANIFEST.MF

390
src/main/java/com/seleniumLib/SeleniumLoginWithCookieRecorder.java

@ -15,6 +15,8 @@ import java.io.File;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.net.URI; import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.nio.file.Paths;
import java.time.Duration; import java.time.Duration;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -34,6 +36,8 @@ import com.google.gson.JsonObject;
import com.google.gson.JsonArray; import com.google.gson.JsonArray;
import com.google.gson.JsonParser; import com.google.gson.JsonParser;
import java.nio.file.Files;
/** /**
* Selenium 模拟登录并获取 Cookie 的示例 * Selenium 模拟登录并获取 Cookie 的示例
* 支持多种登录方式表单登录OAuthAJAX 登录等 * 支持多种登录方式表单登录OAuthAJAX 登录等
@ -93,7 +97,7 @@ public class SeleniumLoginWithCookieRecorder {
// 转换为 JSON // 转换为 JSON
String jsonParams = gson.toJson(params); String jsonParams = gson.toJson(params);
System.out.println("请求参数: " + jsonParams); // System.out.println("请求参数: " + jsonParams);
// 设置请求体 // 设置请求体
httpPost.setEntity(new StringEntity(jsonParams, "UTF-8")); httpPost.setEntity(new StringEntity(jsonParams, "UTF-8"));
@ -101,7 +105,7 @@ public class SeleniumLoginWithCookieRecorder {
// 发送请求 // 发送请求
try (CloseableHttpResponse response = httpClient.execute(httpPost)) { try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
String responseBody = EntityUtils.toString(response.getEntity(), "UTF-8"); String responseBody = EntityUtils.toString(response.getEntity(), "UTF-8");
System.out.println("API 响应: " + responseBody); // System.out.println("API 响应: " + responseBody);
// 解析响应 // 解析响应
return extractCaptchaFromResponse(responseBody); return extractCaptchaFromResponse(responseBody);
@ -138,7 +142,7 @@ public class SeleniumLoginWithCookieRecorder {
/** /**
* 初始化 WebDriver * 初始化 WebDriver
*/ */
public void setupDriver() { public void setupDriver(String proxy) {
// 自动下载和管理 ChromeDriver // 自动下载和管理 ChromeDriver
@ -152,6 +156,13 @@ public class SeleniumLoginWithCookieRecorder {
// Chrome 选项配置 // Chrome 选项配置
ChromeOptions options = new ChromeOptions(); 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");
options.addArguments("--headless=new"); options.addArguments("--headless=new");
@ -205,6 +216,9 @@ public class SeleniumLoginWithCookieRecorder {
// [1, 2, 3, 4, 5]})"); // [1, 2, 3, 4, 5]})");
// driver.executeScript("Object.defineProperty(navigator, 'languages', {get: () // driver.executeScript("Object.defineProperty(navigator, 'languages', {get: ()
// => ['zh-CN', 'zh', 'en']})"); // => ['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)); wait = new WebDriverWait(driver, Duration.ofSeconds(15));
System.out.println("WebDriver 初始化完成"); 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 { try {
System.out.println("开始 Crossref 登录流程..."); 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 // 调试:打印页面标题和URL
System.out.println("当前页面标题: " + driver.getTitle()); System.out.println("当前页面标题: " + driver.getTitle());
@ -271,58 +301,18 @@ public class SeleniumLoginWithCookieRecorder {
// 输入用户名 // 输入用户名
usernameField.clear(); usernameField.clear();
usernameField.sendKeys(username); usernameField.sendKeys(username);
System.out.println("已输入用户名"); System.out.println("已输入用户名: " + username);
// 输入密码 // 输入密码
WebElement passwordField = extendedWait WebElement passwordField = extendedWait
.until(ExpectedConditions.visibilityOfElementLocated(By.id("password"))); .until(ExpectedConditions.visibilityOfElementLocated(By.id("password")));
passwordField.clear(); passwordField.clear();
passwordField.sendKeys(password); passwordField.sendKeys(password);
System.out.println("已输入密码"); System.out.println("已输入密码: " + password);
Thread.sleep(3000); Thread.sleep(3000);
// 验证码处理 // 验证码处理
String cap_first = "0"; // String cap_first = "0";
try { for (int i = 0; i < 3; i++) {
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);
// 验证码处理
try { try {
WebElement captchaImage = extendedWait WebElement captchaImage = extendedWait
.until(ExpectedConditions .until(ExpectedConditions
@ -331,36 +321,157 @@ public class SeleniumLoginWithCookieRecorder {
if (src1 != null && !src1.isEmpty()) { if (src1 != null && !src1.isEmpty()) {
src1 = src1.replace("data:image/png;base64,", "").replace("\n", "").trim(); 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="); 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()) { if (result_cap != null && !result_cap.trim().isEmpty()) {
result_cap = result_cap.replace(" ", ""); result_cap = result_cap.replace(" ", "");
WebElement captchaField = extendedWait WebElement captchaField = extendedWait
.until(ExpectedConditions.visibilityOfElementLocated(By.id("captcha-input"))); .until(ExpectedConditions.visibilityOfElementLocated(By.id("captcha-input")));
captchaField.clear(); captchaField.clear();
captchaField.sendKeys(result_cap); captchaField.sendKeys(result_cap);
System.out.println("已输入验证码2"); System.out.println("已输入验证码" + (i + 1) + ": " + result_cap);
// captureScreenshot("captcha_done"); if (!capture_path.isEmpty()) {
captureScreenshot("captcha_write_done" + (i + 1), capture_path);
}
Thread.sleep(3000); 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) { } 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 { try {
@ -368,12 +479,20 @@ public class SeleniumLoginWithCookieRecorder {
// System.out.println("登录成功,当前URL: " + driver.getCurrentUrl()); // System.out.println("登录成功,当前URL: " + driver.getCurrentUrl());
// 获取并保存 Cookie // 获取并保存 Cookie
isLoggedIn = isLoggedIn(); boolean isLoggedIn = isLoggedIn();
if (isLoggedIn) { if (isLoggedIn) {
saveNPCookiesToFile("crossref", filePath); saveNPCookiesToFile("crossref", filePath);
System.out.println("登录成功"); System.out.println("登录成功");
} else { } else {
System.out.println("登录失败"); 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) { } catch (Exception e) {
@ -544,10 +663,13 @@ public class SeleniumLoginWithCookieRecorder {
*/ */
public void loadCookiesFromFile(String filename) { public void loadCookiesFromFile(String filename) {
try { try {
// 文件中保存的是Netscape 格式的 Cookie 怎么改下面的代码
CookieData cookieData = objectMapper.readValue(new File(filename), CookieData.class); CookieData cookieData = objectMapper.readValue(new File(filename), CookieData.class);
// 先导航到 Cookie 的域名 // 先导航到 Cookie 的域名,https://crossref-26027.turnitin.com/home/
driver.get(cookieData.getUrl()); // driver.get(cookieData.getUrl());
driver.get("https://crossref-26027.turnitin.com/home/");
// 清空现有 Cookie // 清空现有 Cookie
driver.manage().deleteAllCookies(); 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<String> 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 { try {
File screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE); File screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); 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); com.google.common.io.Files.copy(screenshot, dest);
System.out.println("截图已保存: " + dest.getAbsolutePath()); System.out.println("截图已保存: " + dest.getAbsolutePath());
} catch (Exception e) { } catch (Exception e) {
@ -621,22 +801,72 @@ public class SeleniumLoginWithCookieRecorder {
SeleniumLoginWithCookieRecorder recorder = new SeleniumLoginWithCookieRecorder(); SeleniumLoginWithCookieRecorder recorder = new SeleniumLoginWithCookieRecorder();
try { try {
// 1. 初始化驱动 String user_name = "";
recorder.setupDriver(); String password = "";
if (args.length != 3) { String filePath = "";
System.err.println("请提供用户名、密码和文件路径作为参数"); 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; 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; 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 登录示例(需要替换为真实账号) // 2. Crossref 登录示例(需要替换为真实账号)
recorder.loginToCrossCheck(user_name, password, filePath);
recorder.loginToCrossCheck(user_name, password, filePath, tenant, capture_path);
// 3. 验证登录状态 // 3. 验证登录状态
boolean isLoggedIn = recorder.isLoggedIn(); boolean isLoggedIn = recorder.isLoggedIn();

2
src/main/resources/META-INF/MANIFEST.MF

@ -1,3 +1,3 @@
Manifest-Version: 1.0 Manifest-Version: 1.0
Main-Class: com.seleniumLib.crossrefDownLib Main-Class: com.seleniumLib.SeleniumLoginWithCookieRecorder

Loading…
Cancel
Save