Browse Source

增加多账号登录/保活

v3
李昭辉 1 month ago
parent
commit
0750ba5ed5
  1. 313
      src/main/java/com/seleniumLib/SeleniumLoginWithCookieRecorder.java

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

@ -227,7 +227,7 @@ public class SeleniumLoginWithCookieRecorder {
/** /**
* 通用表单登录 * 通用表单登录
*/ */
public void loginToCrossCheck(String username, String password, String filePath, String tenant, public boolean loginToCrossCheck(String username, String password, String filePath, String tenant,
String capture_path) { String capture_path) {
try { try {
System.out.println("开始 Crossref 登录流程..."); System.out.println("开始 Crossref 登录流程...");
@ -295,7 +295,7 @@ public class SeleniumLoginWithCookieRecorder {
if (usernameField == null) { if (usernameField == null) {
System.err.println("无法定位到用户名输入框,页面可能没有正确加载"); System.err.println("无法定位到用户名输入框,页面可能没有正确加载");
// captureScreenshot("element_not_found"); // captureScreenshot("element_not_found");
return; return false;
} }
// 输入用户名 // 输入用户名
@ -376,119 +376,20 @@ public class SeleniumLoginWithCookieRecorder {
Thread.sleep(15000); 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(5000); Thread.sleep(5000);
// 检查登录是否成功 // 检查登录是否成功
try { try {
// extendedWait.until(ExpectedConditions.urlContains("crossref-26027.turnitin.com/originality/inbox/"));
// System.out.println("登录成功,当前URL: " + driver.getCurrentUrl());
// 获取并保存 Cookie // 获取并保存 Cookie
boolean isLoggedIn = isLoggedIn(); boolean isLoggedIn = isLoggedIn();
if (isLoggedIn) { if (isLoggedIn) {
saveNPCookiesToFile("crossref", filePath); saveNPCookiesToFile("crossref", filePath);
System.out.println("登录成功"); System.out.println("登录成功");
// 每隔五分钟刷新一下页面,保持登录状态 // 清空cookie
// for (int i = 0; i < 12; i++) { driver.manage().deleteAllCookies();
// Thread.sleep(300000); // 5分钟 return true;
// driver.navigate().refresh();
// System.out.println("已刷新页面");
// }
} else { } else {
System.out.println("登录失败"); System.out.println("登录失败");
// // 获取错误提示文本 // // 获取错误提示文本
@ -499,17 +400,24 @@ public class SeleniumLoginWithCookieRecorder {
if (!capture_path.isEmpty()) { if (!capture_path.isEmpty()) {
captureScreenshot("login_error", capture_path); captureScreenshot("login_error", capture_path);
} }
// 清空cookie
driver.manage().deleteAllCookies();
return false;
} }
} catch (Exception e) { } catch (Exception e) {
System.err.println("登录可能失败,当前URL: " + driver.getCurrentUrl()); System.err.println("登录可能失败,当前URL: " + driver.getCurrentUrl());
// captureScreenshot("login_possible_failure"); // captureScreenshot("login_possible_failure");
return false;
} }
} catch (Exception e) { } catch (Exception e) {
// 清空cookie
driver.manage().deleteAllCookies();
System.err.println("登录过程中发生错误: " + e.getMessage()); System.err.println("登录过程中发生错误: " + e.getMessage());
e.printStackTrace(); e.printStackTrace();
// captureScreenshot("login_error"); // captureScreenshot("login_error");
return false;
} }
} }
@ -664,41 +572,6 @@ public class SeleniumLoginWithCookieRecorder {
} }
} }
/**
* 从文件加载 Cookie 并设置到浏览器
*/
public void loadCookiesFromFile(String filename) {
try {
// 文件中保存的是Netscape 格式的 Cookie 怎么改下面的代码
CookieData cookieData = objectMapper.readValue(new File(filename), CookieData.class);
// 先导航到 Cookie 的域名,https://crossref-26027.turnitin.com/home/
// driver.get(cookieData.getUrl());
driver.get("https://crossref-26027.turnitin.com/home/");
// 清空现有 Cookie
driver.manage().deleteAllCookies();
// 添加 Cookie
for (Cookie cookie : cookieData.getCookies()) {
try {
driver.manage().addCookie(cookie);
System.out.println("已添加 Cookie: " + cookie.getName());
} catch (Exception e) {
System.err.println("添加 Cookie 失败 (" + cookie.getName() + "): " + e.getMessage());
}
}
// 刷新页面使 Cookie 生效
driver.navigate().refresh();
System.out.println("Cookie 加载完成,页面已刷新");
} catch (IOException e) {
System.err.println("加载 Cookie 文件失败: " + e.getMessage());
}
}
public boolean loadCookiesAndAccessSite(String cookieFile, String tenant, String capture_path) { public boolean loadCookiesAndAccessSite(String cookieFile, String tenant, String capture_path) {
try { try {
try { try {
@ -797,22 +670,50 @@ public class SeleniumLoginWithCookieRecorder {
driver.navigate().refresh(); driver.navigate().refresh();
Thread.sleep(5000); Thread.sleep(5000);
// 使用CSS选择器 // 使用CSS选择器
WebElement element = driver.findElement(By.cssSelector("h1[data-test-id='page-title']")); WebElement element = driver.findElement(By.cssSelector("h1[data-test-id='page-title']"));
String text = element.getText(); String text = element.getText();
element.click();
element.click(); // 随机点击次数1~3下,确保元素可见
int clickCount = (int) (Math.random() * 3) + 1;
for (int i = 0; i < clickCount; i++) {
element.click();
}
// 随机获取一个元素点击,不包括链接元素,按钮元素。
try {
List<WebElement> elements = driver.findElements(By.cssSelector("*:not(a):not(button)"));
System.out.println("页面元素数量: " + elements.size());
if (!elements.isEmpty()) {
int clickElementCount = (int) (Math.random() * 2) + 1;
for (int i = 0; i < clickElementCount; i++) {
int randomIndex = (int) (Math.random() * elements.size());
WebElement randomElement = elements.get(randomIndex);
randomElement.click();
}
}
} catch (Exception e) {
System.out.println("随机元素不存在");
}
System.out.println("获取的文字是: " + text); System.out.println("获取的文字是: " + text);
// 包含指定文本 // 包含指定文本
if (text.contains("Welcome")) { if (text.contains("Welcome")) {
System.out.println("使用cookie刷新成功"); System.out.println("使用cookie刷新成功");
saveNPCookiesToFile("crossref", cookieFile); saveNPCookiesToFile("crossref", cookieFile);
// 清空cookie
driver.manage().deleteAllCookies();
return true; return true;
} else { } else {
System.out.println("使用cookie刷新失败"); System.out.println("使用cookie刷新失败");
// 清空cookie
driver.manage().deleteAllCookies();
return false; return false;
} }
} catch (Exception e) { } catch (Exception e) {
System.err.println("Cookie 刷新失败: " + e.getMessage()); System.err.println("Cookie 刷新失败: " + e.getMessage());
// 清空cookie
driver.manage().deleteAllCookies();
return false; return false;
} }
// return false; // return false;
@ -877,6 +778,9 @@ public class SeleniumLoginWithCookieRecorder {
String capture_path = ""; String capture_path = "";
String only_keep_cookie = "0"; String only_keep_cookie = "0";
String only_login = "0"; String only_login = "0";
String json_accounts = "";
String waitTime = "";
ArrayList arr_accounts = new ArrayList<>();
// 传的参数增加参数名 // 传的参数增加参数名
for (int i = 0; i < args.length; i++) { for (int i = 0; i < args.length; i++) {
@ -890,6 +794,9 @@ public class SeleniumLoginWithCookieRecorder {
proxy = args[i + 1]; proxy = args[i + 1];
} else if (args[i].equals("-t")) { } else if (args[i].equals("-t")) {
tenant = args[i + 1]; tenant = args[i + 1];
} else if (args[i].equals("-json_accounts")) {
json_accounts = args[i + 1];
arr_accounts = new Gson().fromJson(json_accounts, ArrayList.class);
} else if (args[i].equals("-help")) { } else if (args[i].equals("-help")) {
help = "1"; help = "1";
} else if (args[i].equals("-only_keep_cookie")) { } else if (args[i].equals("-only_keep_cookie")) {
@ -911,10 +818,12 @@ public class SeleniumLoginWithCookieRecorder {
} }
if (help.equals("1")) { if (help.equals("1")) {
System.out.println("参数说明:"); System.out.println("参数说明:");
System.out.println("-u '用户名',必填"); System.out.println("-u '用户名',无-json_accounts时必填");
System.out.println("-p '密码',必填"); System.out.println("-p '密码',无-json_accounts时填,-only_keep_cookie时可不填");
System.out.println("-f '保存 Cookie 的文件路径及文件名',必填"); System.out.println("-f '保存 Cookie 的文件路径及文件名',无-json_accounts时必填");
System.out.println("-t '租户 ID'(可选,默认crossref-26027)"); System.out.println("-t '租户 ID'(可选,默认crossref-26027)");
System.out.println(
"-json_accounts '多个账号json格式:[{\"username\":\"\",\"password\":\"\",\"tenant\":\"\",\"filePath\":\"\",\"waitTime\":\"\"},...]',选填,可替代-u/-p/-t/-f参数");
System.out.println("-proxy '代理配置字串'(可选,例如 'socks5://host:port') "); System.out.println("-proxy '代理配置字串'(可选,例如 'socks5://host:port') ");
System.out.println("-capture_path '截图保存路径'(可选,没有此参数,则不截图)"); System.out.println("-capture_path '截图保存路径'(可选,没有此参数,则不截图)");
System.out.println("-only_keep_cookie: 只做cookie保活,不登录"); System.out.println("-only_keep_cookie: 只做cookie保活,不登录");
@ -923,26 +832,81 @@ public class SeleniumLoginWithCookieRecorder {
return; return;
} }
if (user_name.isEmpty() || password.isEmpty() || filePath.isEmpty()) { if ((user_name.isEmpty() || (password.isEmpty() && !only_keep_cookie.equals("1")) || filePath.isEmpty())
System.err.println("用户名、密码、文件路径不能为空。-help 查看帮助信息"); && arr_accounts.isEmpty()) {
System.err.println("-help 查看帮助信息。用户名、密码、文件路径不能为空或-json_accounts参数不能为空。");
return; return;
} }
// 将-u/-p/-t/-f参数添加到arr_accounts中
if (arr_accounts.isEmpty()) {
Map<String, Object> accountMap = new HashMap<>();
accountMap.put("username", user_name);
accountMap.put("password", password);
accountMap.put("tenant", tenant);
accountMap.put("filePath", filePath);
accountMap.put("waitTime", "1");
arr_accounts.add(accountMap);
}
// 检查元素是否有username、password、tenant、filePath
for (Object obj : arr_accounts) {
// 检查元素是否为 Map 类型
if (obj instanceof Map) {
Map<String, Object> accountMap = (Map<String, Object>) obj;
user_name = (String) accountMap.get("username");
password = (String) accountMap.get("password");
tenant = (String) accountMap.get("tenant");
filePath = (String) accountMap.get("filePath");
// 检测是否有username、password、tenant、filePath,并且不能为空,为空则删除
if (user_name.isEmpty() || tenant.isEmpty() || filePath.isEmpty()) {
arr_accounts.remove(accountMap);
String currentTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
System.out.println("<res>" + currentTime + "|" + user_name
+ "|保活失败|数组元素删除,因为username、password、tenant、filePath不能为空</res>");
}
} else {
System.out.println("数组元素不是 Map 类型");
}
}
// 1. 初始化驱动(带代理配置) // 1. 初始化驱动(带代理配置)
recorder.setupDriver(proxy); recorder.setupDriver(proxy);
if (only_login.equals("1")) { if (only_login.equals("1")) {
System.out.println("-only_login: 只登录,不做cookie保活"); System.out.println("-only_login: 只登录,不做cookie保活");
} else { } else {
// 如果文件存在,加载文件中的 Cookie // 遍历数组中的每个元素,保活cookie
if (Files.exists(Paths.get(filePath))) { for (Object obj : arr_accounts) {
System.out.println("文件存在,加载文件中的 Cookie:" + filePath); // 检查元素是否为 Map 类型
boolean testLoggedIn = recorder.loadCookiesAndAccessSite(filePath, tenant, capture_path); Map<String, Object> accountMap = (Map<String, Object>) obj;
if (testLoggedIn) { user_name = (String) accountMap.get("username");
System.out.println("cookie保活成功"); password = (String) accountMap.get("password");
return; tenant = (String) accountMap.get("tenant");
} else { filePath = (String) accountMap.get("filePath");
System.out.println("cookie保活失败"); waitTime = String.valueOf(accountMap.get("waitTime"));
// 如果文件存在,加载文件中的 Cookie
if (Files.exists(Paths.get(filePath))) {
System.out.println("文件存在,加载文件中的 Cookie:" + filePath);
boolean testLoggedIn = recorder.loadCookiesAndAccessSite(filePath, tenant, capture_path);
String currentTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
if (testLoggedIn) {
System.out.println("<res>" + currentTime + "|" + user_name + "|cookie保活成功</res>");
// return;
} else {
System.out.println("<res>" + currentTime + "|" + user_name + "|cookie保活失败</res>");
}
}
// 等待间隔
if (waitTime != null && !waitTime.isEmpty()) {
try {
System.out.println("等待 " + waitTime + " 秒后继续下一个账号");
Thread.sleep((int) Double.parseDouble(waitTime) * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} }
} }
} }
@ -951,18 +915,37 @@ public class SeleniumLoginWithCookieRecorder {
System.out.println("-only_keep_cookie: 只做cookie保活,不登录"); System.out.println("-only_keep_cookie: 只做cookie保活,不登录");
return; return;
} }
// System.exit(0);
// return;
// 2. Crossref 登录示例(需要替换为真实账号)
recorder.loginToCrossCheck(user_name, password, filePath, tenant, capture_path);
// 3. 验证登录状态 // 遍历数组中的每个元素,登录并保存cookie
boolean isLoggedIn = recorder.isLoggedIn(); for (Object obj : arr_accounts) {
System.out.println("登录状态: " + (isLoggedIn ? "成功" : "失败")); // 检查元素是否为 Map 类型
Map<String, Object> accountMap = (Map<String, Object>) obj;
user_name = (String) accountMap.get("username");
password = (String) accountMap.get("password");
tenant = (String) accountMap.get("tenant");
filePath = (String) accountMap.get("filePath");
waitTime = String.valueOf(accountMap.get("waitTime"));
// 2. Crossref 登录示例(需要替换为真实账号)
boolean isLoggedIn = recorder.loginToCrossCheck(user_name, password, filePath, tenant, capture_path);
// 3. 验证登录状态
// boolean isLoggedIn = recorder.isLoggedIn();
String currentTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
System.out.println(
"<res>" + currentTime + "|" + user_name + "|登录" + (isLoggedIn ? "成功" : "失败") + "</res>");
// 4. 可以在这里使用获取的 Cookie 进行后续操作 // 清空cookie
// recorder.loadCookiesFromFile("github_cookies_20231215_143022.json"); recorder.driver.manage().deleteAllCookies();
// 等待间隔
if (waitTime != null && !waitTime.isEmpty()) {
try {
System.out.println("等待 " + waitTime + " 秒后继续下一个账号");
Thread.sleep((int) Double.parseDouble(waitTime) * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} catch (Exception e) { } catch (Exception e) {
System.err.println("程序执行异常: " + e.getMessage()); System.err.println("程序执行异常: " + e.getMessage());

Loading…
Cancel
Save