10 changed files with 888 additions and 0 deletions
@ -0,0 +1,53 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> |
|||
<modelVersion>4.0.0</modelVersion> |
|||
<groupId>com.example</groupId> |
|||
<artifactId>crossref</artifactId> |
|||
<version>1.0-SNAPSHOT</version> |
|||
<build> |
|||
<plugins> |
|||
<plugin> |
|||
<artifactId>maven-compiler-plugin</artifactId> |
|||
<version>3.11.0</version> |
|||
<configuration> |
|||
<source>8</source> |
|||
<target>8</target> |
|||
</configuration> |
|||
</plugin> |
|||
<plugin> |
|||
<artifactId>maven-shade-plugin</artifactId> |
|||
<version>3.4.1</version> |
|||
<executions> |
|||
<execution> |
|||
<phase>package</phase> |
|||
<goals> |
|||
<goal>shade</goal> |
|||
</goals> |
|||
<configuration> |
|||
<transformers> |
|||
<transformer> |
|||
<mainClass>com.seleniumLib.SeleniumLoginWithCookieRecorder</mainClass> |
|||
</transformer> |
|||
</transformers> |
|||
<filters> |
|||
<filter> |
|||
<artifact>*:*</artifact> |
|||
<excludes> |
|||
<exclude>META-INF/*.SF</exclude> |
|||
<exclude>META-INF/*.DSA</exclude> |
|||
<exclude>META-INF/*.RSA</exclude> |
|||
</excludes> |
|||
</filter> |
|||
</filters> |
|||
</configuration> |
|||
</execution> |
|||
</executions> |
|||
</plugin> |
|||
</plugins> |
|||
</build> |
|||
<properties> |
|||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
|||
<maven.compiler.source>8</maven.compiler.source> |
|||
<maven.compiler.target>8</maven.compiler.target> |
|||
</properties> |
|||
</project> |
|||
@ -0,0 +1,109 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" |
|||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
|||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
|||
<modelVersion>4.0.0</modelVersion> |
|||
|
|||
<groupId>com.example</groupId> |
|||
<artifactId>crossref</artifactId> |
|||
<version>1.0-SNAPSHOT</version> |
|||
|
|||
<properties> |
|||
<maven.compiler.source>8</maven.compiler.source> |
|||
<maven.compiler.target>8</maven.compiler.target> |
|||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
|||
</properties> |
|||
|
|||
<dependencies> |
|||
<dependency> |
|||
<groupId>org.slf4j</groupId> |
|||
<artifactId>slf4j-nop</artifactId> |
|||
<version>1.7.36</version> |
|||
</dependency> |
|||
|
|||
<dependency> |
|||
<groupId>org.seleniumhq.selenium</groupId> |
|||
<artifactId>selenium-java</artifactId> |
|||
<version>4.11.0</version> |
|||
</dependency> |
|||
|
|||
<dependency> |
|||
<groupId>com.alibaba</groupId> |
|||
<artifactId>fastjson</artifactId> |
|||
<version>1.2.37</version> |
|||
</dependency> |
|||
|
|||
<dependency> |
|||
<groupId>com.google.guava</groupId> |
|||
<artifactId>guava</artifactId> |
|||
<version>31.1-jre</version> |
|||
</dependency> |
|||
|
|||
<!-- Apache HttpClient 核心依赖 --> |
|||
<dependency> |
|||
<groupId>org.apache.httpcomponents</groupId> |
|||
<artifactId>httpclient</artifactId> |
|||
<version>4.5.14</version> <!-- 可选用最新版 --> |
|||
</dependency> |
|||
|
|||
<!-- ChromeDriver 管理 --> |
|||
<dependency> |
|||
<groupId>io.github.bonigarcia</groupId> |
|||
<artifactId>webdrivermanager</artifactId> |
|||
<version>5.6.2</version> |
|||
</dependency> |
|||
|
|||
<!-- JSON 处理 --> |
|||
<dependency> |
|||
<groupId>com.fasterxml.jackson.core</groupId> |
|||
<artifactId>jackson-databind</artifactId> |
|||
<version>2.15.2</version> |
|||
</dependency> |
|||
</dependencies> |
|||
<build> |
|||
<plugins> |
|||
<!-- Maven Compiler Plugin --> |
|||
<plugin> |
|||
<groupId>org.apache.maven.plugins</groupId> |
|||
<artifactId>maven-compiler-plugin</artifactId> |
|||
<version>3.11.0</version> |
|||
<configuration> |
|||
<source>8</source> |
|||
<target>8</target> |
|||
</configuration> |
|||
</plugin> |
|||
|
|||
<!-- Maven Shade Plugin for creating executable JAR --> |
|||
<plugin> |
|||
<groupId>org.apache.maven.plugins</groupId> |
|||
<artifactId>maven-shade-plugin</artifactId> |
|||
<version>3.4.1</version> |
|||
<executions> |
|||
<execution> |
|||
<phase>package</phase> |
|||
<goals> |
|||
<goal>shade</goal> |
|||
</goals> |
|||
<configuration> |
|||
<transformers> |
|||
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> |
|||
<mainClass>com.seleniumLib.SeleniumLoginWithCookieRecorder</mainClass> |
|||
</transformer> |
|||
</transformers> |
|||
<filters> |
|||
<filter> |
|||
<artifact>*:*</artifact> |
|||
<excludes> |
|||
<exclude>META-INF/*.SF</exclude> |
|||
<exclude>META-INF/*.DSA</exclude> |
|||
<exclude>META-INF/*.RSA</exclude> |
|||
</excludes> |
|||
</filter> |
|||
</filters> |
|||
</configuration> |
|||
</execution> |
|||
</executions> |
|||
</plugin> |
|||
</plugins> |
|||
</build> |
|||
</project> |
|||
@ -0,0 +1,712 @@ |
|||
package com.seleniumLib; |
|||
|
|||
import org.openqa.selenium.*; |
|||
import org.openqa.selenium.chrome.ChromeDriver; |
|||
import org.openqa.selenium.chrome.ChromeOptions; |
|||
import org.openqa.selenium.support.ui.ExpectedConditions; |
|||
import org.openqa.selenium.support.ui.WebDriverWait; |
|||
import io.github.bonigarcia.wdm.WebDriverManager; |
|||
import com.fasterxml.jackson.databind.ObjectMapper; |
|||
import com.fasterxml.jackson.databind.SerializationFeature; |
|||
import com.google.gson.Gson; |
|||
|
|||
import java.io.BufferedWriter; |
|||
import java.io.File; |
|||
import java.io.FileWriter; |
|||
import java.io.IOException; |
|||
import java.net.URI; |
|||
import java.time.Duration; |
|||
import java.util.List; |
|||
import java.util.Map; |
|||
import java.util.Set; |
|||
import java.util.ArrayList; |
|||
import java.util.Date; |
|||
import java.util.HashMap; |
|||
import java.text.SimpleDateFormat; |
|||
|
|||
import org.apache.http.client.methods.CloseableHttpResponse; |
|||
import org.apache.http.client.methods.HttpPost; |
|||
import org.apache.http.entity.StringEntity; |
|||
import org.apache.http.impl.client.CloseableHttpClient; |
|||
import org.apache.http.impl.client.HttpClients; |
|||
import org.apache.http.util.EntityUtils; |
|||
import com.google.gson.JsonObject; |
|||
import com.google.gson.JsonArray; |
|||
import com.google.gson.JsonParser; |
|||
|
|||
/** |
|||
* Selenium 模拟登录并获取 Cookie 的示例 |
|||
* 支持多种登录方式:表单登录、OAuth、AJAX 登录等 |
|||
*/ |
|||
public class SeleniumLoginWithCookieRecorder { |
|||
|
|||
private WebDriver driver; |
|||
private WebDriverWait wait; |
|||
private String cookiesSavePath = "cookies.json"; |
|||
private ObjectMapper objectMapper = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT); |
|||
private static final String API_URL = "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions"; |
|||
private static final String API_KEY = "sk-e5c86737c99a4c9da5efe3519ca2b539"; |
|||
private static final Gson gson = new Gson(); |
|||
|
|||
/** |
|||
* 识别验证码 |
|||
*/ |
|||
public String recognizeCaptcha(String base64Img) { |
|||
try (CloseableHttpClient httpClient = HttpClients.createDefault()) { |
|||
// 构建请求
|
|||
HttpPost httpPost = new HttpPost(API_URL); |
|||
|
|||
// 设置 headers
|
|||
httpPost.setHeader("Authorization", "Bearer " + API_KEY); |
|||
httpPost.setHeader("Content-Type", "application/json"); |
|||
httpPost.setHeader("Accept", "application/json"); |
|||
|
|||
// 构建请求体
|
|||
Map<String, Object> params = new HashMap<>(); |
|||
params.put("model", "qwen3-vl-plus"); |
|||
params.put("temperature", 0.3); |
|||
|
|||
// 构建 messages 数组
|
|||
List<Map<String, Object>> messages = new ArrayList<>(); |
|||
Map<String, Object> userMessage = new HashMap<>(); |
|||
userMessage.put("role", "user"); |
|||
|
|||
// 构建 content 数组
|
|||
List<Map<String, Object>> content = new ArrayList<>(); |
|||
|
|||
// 图片部分
|
|||
Map<String, Object> imageContent = new HashMap<>(); |
|||
imageContent.put("type", "image_url"); |
|||
imageContent.put("image_url", "data:image/png;base64," + base64Img); |
|||
content.add(imageContent); |
|||
|
|||
// 文本部分
|
|||
Map<String, Object> textContent = new HashMap<>(); |
|||
textContent.put("type", "text"); |
|||
textContent.put("text", "识别图片中验证码,区分大小写,要求只返回验证码即可"); |
|||
content.add(textContent); |
|||
|
|||
userMessage.put("content", content); |
|||
messages.add(userMessage); |
|||
|
|||
params.put("messages", messages); |
|||
|
|||
// 转换为 JSON
|
|||
String jsonParams = gson.toJson(params); |
|||
System.out.println("请求参数: " + jsonParams); |
|||
|
|||
// 设置请求体
|
|||
httpPost.setEntity(new StringEntity(jsonParams, "UTF-8")); |
|||
|
|||
// 发送请求
|
|||
try (CloseableHttpResponse response = httpClient.execute(httpPost)) { |
|||
String responseBody = EntityUtils.toString(response.getEntity(), "UTF-8"); |
|||
System.out.println("API 响应: " + responseBody); |
|||
|
|||
// 解析响应
|
|||
return extractCaptchaFromResponse(responseBody); |
|||
} |
|||
|
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
return null; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 从响应中提取验证码 |
|||
*/ |
|||
private String extractCaptchaFromResponse(String jsonResponse) { |
|||
try { |
|||
JsonObject jsonObject = JsonParser.parseString(jsonResponse).getAsJsonObject(); |
|||
JsonArray choices = jsonObject.getAsJsonArray("choices"); |
|||
|
|||
if (choices != null && choices.size() > 0) { |
|||
JsonObject firstChoice = choices.get(0).getAsJsonObject(); |
|||
JsonObject message = firstChoice.getAsJsonObject("message"); |
|||
String content = message.get("content").getAsString(); |
|||
|
|||
// 清理内容,只返回验证码
|
|||
return content.trim(); |
|||
} |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
/** |
|||
* 初始化 WebDriver |
|||
*/ |
|||
public void setupDriver() { |
|||
|
|||
// 自动下载和管理 ChromeDriver
|
|||
|
|||
String devSystem = System.getProperty("os.name"); |
|||
if (!devSystem.toLowerCase().contains("windows")) { |
|||
System.setProperty("webdriver.chrome.driver", "/datacenter/java/lib/chromedriver"); |
|||
} else { |
|||
WebDriverManager.chromedriver().setup(); |
|||
} |
|||
|
|||
// Chrome 选项配置
|
|||
ChromeOptions options = new ChromeOptions(); |
|||
|
|||
// 可选:无头模式(不显示浏览器界面)
|
|||
// options.addArguments("--headless");
|
|||
options.addArguments("--headless=new"); |
|||
|
|||
// 可选:禁用自动化提示
|
|||
options.addArguments("--disable-blink-features=AutomationControlled"); |
|||
options.setExperimentalOption("excludeSwitches", new String[] { "enable-automation" }); |
|||
options.setExperimentalOption("useAutomationExtension", false); |
|||
|
|||
// 用户代理伪装(模拟真实浏览器)
|
|||
options.addArguments( |
|||
"--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"); |
|||
|
|||
// 其他优化选项
|
|||
options.addArguments("--no-sandbox"); |
|||
options.addArguments("--disable-dev-shm-usage"); |
|||
options.addArguments("--disable-gpu"); |
|||
options.addArguments("--window-size=1920,1080"); |
|||
options.addArguments("--start-maximized"); |
|||
options.addArguments("--disable-extensions"); |
|||
options.addArguments("--disable-plugins"); |
|||
options.addArguments("--disable-popup-blocking"); |
|||
options.addArguments("--disable-default-apps"); |
|||
options.addArguments("--disable-translate"); |
|||
options.addArguments("--disable-background-timer-throttling"); |
|||
options.addArguments("--disable-renderer-backgrounding"); |
|||
options.addArguments("--disable-backgrounding-occluded-windows"); |
|||
options.addArguments("--disable-features=TranslateUI,BlinkGenPropertyTrees"); |
|||
options.addArguments("--disable-component-update"); |
|||
options.addArguments("--disable-domain-reliability"); |
|||
options.addArguments("--disable-ipc-flooding-protection"); |
|||
options.addArguments("--disable-client-side-phishing-detection"); |
|||
options.addArguments("--disable-hang-monitor"); |
|||
options.addArguments("--disable-prompt-on-repost"); |
|||
options.addArguments("--disable-sync"); |
|||
options.addArguments("--disable-web-security"); |
|||
options.addArguments("--disable-site-isolation-trials"); |
|||
options.addArguments("--disable-features=VizDisplayCompositor"); |
|||
options.addArguments("--disable-software-rasterizer"); |
|||
options.addArguments("--disable-logging"); |
|||
options.addArguments("--log-level=3"); |
|||
options.addArguments("--silent"); |
|||
options.addArguments("--mute-audio"); |
|||
|
|||
driver = new ChromeDriver(options); |
|||
|
|||
// 执行JavaScript来隐藏WebDriver特征
|
|||
// driver.executeScript("Object.defineProperty(navigator, 'webdriver', {get: ()
|
|||
// => undefined})");
|
|||
// driver.executeScript("Object.defineProperty(navigator, 'plugins', {get: () =>
|
|||
// [1, 2, 3, 4, 5]})");
|
|||
// driver.executeScript("Object.defineProperty(navigator, 'languages', {get: ()
|
|||
// => ['zh-CN', 'zh', 'en']})");
|
|||
|
|||
wait = new WebDriverWait(driver, Duration.ofSeconds(15)); |
|||
System.out.println("WebDriver 初始化完成"); |
|||
} |
|||
|
|||
/** |
|||
* 通用表单登录 |
|||
*/ |
|||
public void loginToCrossCheck(String username, String password, String filePath) { |
|||
try { |
|||
System.out.println("开始 Crossref 登录流程..."); |
|||
|
|||
// 打开登录页面
|
|||
driver.get("https://crossref-26027.turnitin.com/originality/inbox/713daa1b-0685-4cc7-89ec-6b6c7cbc0411"); |
|||
|
|||
// 增加页面加载等待时间
|
|||
Thread.sleep(3000); // 等待5秒确保页面完全加载
|
|||
|
|||
// 调试:打印页面标题和URL
|
|||
System.out.println("当前页面标题: " + driver.getTitle()); |
|||
System.out.println("当前页面URL: " + driver.getCurrentUrl()); |
|||
|
|||
// 调试:打印页面源代码(前500字符)
|
|||
// String pageSource = driver.getPageSource();
|
|||
// System.out.println("页面源代码片段: " + pageSource.substring(0, Math.min(500,
|
|||
// pageSource.length())));
|
|||
|
|||
// 使用更稳健的等待策略
|
|||
WebDriverWait extendedWait = new WebDriverWait(driver, Duration.ofSeconds(30)); |
|||
|
|||
// 尝试多种元素定位方式
|
|||
WebElement usernameField = null; |
|||
try { |
|||
// 方式1:直接等待元素可见
|
|||
usernameField = extendedWait.until(ExpectedConditions.visibilityOfElementLocated(By.id("username"))); |
|||
System.out.println("通过id定位到username元素"); |
|||
} catch (Exception e1) { |
|||
try { |
|||
// 方式2:尝试CSS选择器
|
|||
usernameField = extendedWait.until( |
|||
ExpectedConditions.visibilityOfElementLocated(By.cssSelector("input[id='username']"))); |
|||
System.out.println("通过CSS选择器定位到username元素"); |
|||
} catch (Exception e2) { |
|||
try { |
|||
// 方式3:尝试name属性
|
|||
usernameField = extendedWait |
|||
.until(ExpectedConditions.visibilityOfElementLocated(By.name("username"))); |
|||
System.out.println("通过name属性定位到username元素"); |
|||
} catch (Exception e3) { |
|||
// 方式4:尝试XPath
|
|||
usernameField = extendedWait.until(ExpectedConditions.visibilityOfElementLocated( |
|||
By.xpath("//input[contains(@id, 'username') or contains(@name, 'username')]"))); |
|||
System.out.println("通过XPath定位到username元素"); |
|||
} |
|||
} |
|||
} |
|||
|
|||
if (usernameField == null) { |
|||
System.err.println("无法定位到用户名输入框,页面可能没有正确加载"); |
|||
// captureScreenshot("element_not_found");
|
|||
return; |
|||
} |
|||
|
|||
// 输入用户名
|
|||
usernameField.clear(); |
|||
usernameField.sendKeys(username); |
|||
System.out.println("已输入用户名"); |
|||
|
|||
// 输入密码
|
|||
WebElement passwordField = extendedWait |
|||
.until(ExpectedConditions.visibilityOfElementLocated(By.id("password"))); |
|||
passwordField.clear(); |
|||
passwordField.sendKeys(password); |
|||
System.out.println("已输入密码"); |
|||
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); |
|||
// 验证码处理
|
|||
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"); |
|||
// captureScreenshot("captcha_done");
|
|||
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()); |
|||
} |
|||
} |
|||
|
|||
// 等待登录结果
|
|||
Thread.sleep(3000); |
|||
|
|||
// 检查登录是否成功
|
|||
try { |
|||
// extendedWait.until(ExpectedConditions.urlContains("crossref-26027.turnitin.com/originality/inbox/"));
|
|||
// System.out.println("登录成功,当前URL: " + driver.getCurrentUrl());
|
|||
|
|||
// 获取并保存 Cookie
|
|||
isLoggedIn = isLoggedIn(); |
|||
if (isLoggedIn) { |
|||
saveNPCookiesToFile("crossref", filePath); |
|||
System.out.println("登录成功"); |
|||
} else { |
|||
System.out.println("登录失败"); |
|||
} |
|||
|
|||
} catch (Exception e) { |
|||
System.err.println("登录可能失败,当前URL: " + driver.getCurrentUrl()); |
|||
// captureScreenshot("login_possible_failure");
|
|||
} |
|||
|
|||
} catch (Exception e) { |
|||
System.err.println("登录过程中发生错误: " + e.getMessage()); |
|||
e.printStackTrace(); |
|||
// captureScreenshot("login_error");
|
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 获取所有 Cookie 并保存到文件 |
|||
*/ |
|||
public void saveCookiesToFile(String siteName) { |
|||
try { |
|||
Set<Cookie> cookies = driver.manage().getCookies(); |
|||
|
|||
System.out.println("\n========== " + siteName.toUpperCase() + " COOKIES =========="); |
|||
System.out.println("共获取到 " + cookies.size() + " 个 Cookie:"); |
|||
|
|||
// 创建 Cookie 数据对象
|
|||
CookieData cookieData = new CookieData(); |
|||
cookieData.setSite(siteName); |
|||
cookieData.setUrl(driver.getCurrentUrl()); |
|||
cookieData.setTimestamp(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); |
|||
|
|||
for (Cookie cookie : cookies) { |
|||
System.out.println("--------------------------------"); |
|||
System.out.println("Name: " + cookie.getName()); |
|||
System.out.println( |
|||
"Value: " + (cookie.getValue().length() > 50 ? cookie.getValue().substring(0, 50) + "..." |
|||
: cookie.getValue())); |
|||
System.out.println("Domain: " + cookie.getDomain()); |
|||
System.out.println("Path: " + cookie.getPath()); |
|||
System.out.println("Expiry: " + cookie.getExpiry()); |
|||
System.out.println("Secure: " + cookie.isSecure()); |
|||
System.out.println("HttpOnly: " + cookie.isHttpOnly()); |
|||
|
|||
// 添加到数据列表
|
|||
cookieData.addCookie(cookie); |
|||
} |
|||
|
|||
// 保存到 JSON 文件
|
|||
String filename = siteName + "_cookies_" + |
|||
new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()) + ".json"; |
|||
|
|||
objectMapper.writeValue(new File(filename), cookieData); |
|||
System.out.println("\nCookie 已保存到文件: " + filename); |
|||
|
|||
} catch (IOException e) { |
|||
System.err.println("保存 Cookie 文件失败: " + e.getMessage()); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 获取所有 Cookie 并保存为 Netscape 格式的 cookie 文件 |
|||
*/ |
|||
public void saveNPCookiesToFile(String siteName, String filePath) { |
|||
try { |
|||
Set<Cookie> cookies = driver.manage().getCookies(); |
|||
|
|||
System.out.println("\n========== " + siteName.toUpperCase() + " COOKIES =========="); |
|||
System.out.println("共获取到 " + cookies.size() + " 个 Cookie:"); |
|||
|
|||
// 创建 Netscape 格式的 cookie 文件
|
|||
// String filename = siteName + "_cookies_" + new
|
|||
// SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()) + ".txt";
|
|||
String filename = filePath; |
|||
|
|||
try (BufferedWriter writer = new BufferedWriter(new FileWriter(filename))) { |
|||
// 写入 Netscape cookie 文件头部
|
|||
writer.write("# Netscape HTTP Cookie File"); |
|||
writer.newLine(); |
|||
writer.write("# https://curl.haxx.se/docs/http-cookies.html"); |
|||
writer.newLine(); |
|||
writer.write("# This file was generated by Selenium Cookie Exporter"); |
|||
writer.newLine(); |
|||
writer.write("# Site: " + siteName); |
|||
writer.newLine(); |
|||
writer.write("# URL: " + driver.getCurrentUrl()); |
|||
writer.newLine(); |
|||
writer.write("# Generated at: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); |
|||
writer.newLine(); |
|||
writer.newLine(); |
|||
|
|||
// Netscape cookie 格式:
|
|||
// domain \t inclusion \t path \t secure \t expiry \t name \t value
|
|||
// - domain: cookie 的域名
|
|||
// - inclusion: 子域名是否可用 (TRUE/FALSE)
|
|||
// - path: cookie 的路径
|
|||
// - secure: 是否只通过 HTTPS 传输 (TRUE/FALSE)
|
|||
// - expiry: Unix 时间戳(秒),0 表示会话 cookie
|
|||
// - name: cookie 名称
|
|||
// - value: cookie 值
|
|||
|
|||
for (Cookie cookie : cookies) { |
|||
System.out.println("--------------------------------"); |
|||
System.out.println("Name: " + cookie.getName()); |
|||
System.out.println( |
|||
"Value: " + (cookie.getValue().length() > 50 ? cookie.getValue().substring(0, 50) + "..." |
|||
: cookie.getValue())); |
|||
System.out.println("Domain: " + cookie.getDomain()); |
|||
System.out.println("Path: " + cookie.getPath()); |
|||
System.out.println("Expiry: " + cookie.getExpiry()); |
|||
System.out.println("Secure: " + cookie.isSecure()); |
|||
System.out.println("HttpOnly: " + cookie.isHttpOnly()); |
|||
|
|||
// 处理域名
|
|||
String domain = cookie.getDomain(); |
|||
if (domain != null && domain.startsWith(".")) { |
|||
domain = domain.substring(1); // 移除开头的点
|
|||
} |
|||
|
|||
// 处理 inclusion 字段
|
|||
// 如果 cookie 域名以 . 开头,则表示可用于所有子域名
|
|||
String inclusion = "FALSE"; |
|||
if (cookie.getDomain() != null && cookie.getDomain().startsWith(".")) { |
|||
inclusion = "TRUE"; |
|||
} |
|||
|
|||
// 处理路径
|
|||
String path = cookie.getPath(); |
|||
if (path == null || path.isEmpty()) { |
|||
path = "/"; |
|||
} |
|||
|
|||
// 处理过期时间
|
|||
long expiry = 0; |
|||
if (cookie.getExpiry() != null) { |
|||
expiry = cookie.getExpiry().getTime() / 1000; // 转换为 Unix 时间戳(秒)
|
|||
} |
|||
|
|||
// 处理 secure 标志
|
|||
String secure = cookie.isSecure() ? "TRUE" : "FALSE"; |
|||
|
|||
// 构建 Netscape cookie 行
|
|||
String cookieLine = String.format("%s\t%s\t%s\t%s\t%d\t%s\t%s", |
|||
domain != null ? domain : "", |
|||
inclusion, |
|||
path, |
|||
secure, |
|||
expiry, |
|||
cookie.getName(), |
|||
cookie.getValue()); |
|||
|
|||
writer.write(cookieLine); |
|||
writer.newLine(); |
|||
} |
|||
|
|||
System.out.println("\nNetscape 格式 Cookie 文件已保存: " + filename); |
|||
|
|||
} catch (IOException e) { |
|||
System.err.println("写入 Cookie 文件失败: " + e.getMessage()); |
|||
} |
|||
|
|||
} catch (Exception e) { |
|||
System.err.println("保存 Cookie 文件失败: " + e.getMessage()); |
|||
e.printStackTrace(); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 从文件加载 Cookie 并设置到浏览器 |
|||
*/ |
|||
public void loadCookiesFromFile(String filename) { |
|||
try { |
|||
CookieData cookieData = objectMapper.readValue(new File(filename), CookieData.class); |
|||
|
|||
// 先导航到 Cookie 的域名
|
|||
driver.get(cookieData.getUrl()); |
|||
|
|||
// 清空现有 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()); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 截图保存 |
|||
*/ |
|||
private void captureScreenshot(String filename) { |
|||
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"); |
|||
com.google.common.io.Files.copy(screenshot, dest); |
|||
System.out.println("截图已保存: " + dest.getAbsolutePath()); |
|||
} catch (Exception e) { |
|||
System.err.println("截图失败: " + e.getMessage()); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 验证登录是否成功 |
|||
*/ |
|||
public boolean isLoggedIn() { |
|||
try { |
|||
Set<Cookie> cookies = driver.manage().getCookies(); |
|||
for (Cookie cookie : cookies) { |
|||
if (cookie.getName().equals("jwtCookie")) { |
|||
return true; |
|||
} |
|||
} |
|||
} catch (Exception e) { |
|||
return false; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
/** |
|||
* 关闭浏览器 |
|||
*/ |
|||
public void teardown() { |
|||
if (driver != null) { |
|||
// captureScreenshot("before_close");
|
|||
driver.quit(); |
|||
System.out.println("浏览器已关闭"); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 主方法 - 示例运行 |
|||
*/ |
|||
public static void main(String[] args) { |
|||
SeleniumLoginWithCookieRecorder recorder = new SeleniumLoginWithCookieRecorder(); |
|||
|
|||
try { |
|||
// 1. 初始化驱动
|
|||
recorder.setupDriver(); |
|||
if (args.length != 3) { |
|||
System.err.println("请提供用户名、密码和文件路径作为参数"); |
|||
return; |
|||
} |
|||
if (args[0].isEmpty() || args[1].isEmpty() || args[2].isEmpty()) { |
|||
System.err.println("用户名、密码或文件路径不能为空"); |
|||
return; |
|||
} |
|||
String user_name = args[0]; |
|||
String password = args[1]; |
|||
String filePath = args[2]; |
|||
|
|||
// 2. Crossref 登录示例(需要替换为真实账号)
|
|||
recorder.loginToCrossCheck(user_name, password, filePath); |
|||
|
|||
// 3. 验证登录状态
|
|||
boolean isLoggedIn = recorder.isLoggedIn(); |
|||
System.out.println("登录状态: " + (isLoggedIn ? "成功" : "失败")); |
|||
|
|||
// 4. 可以在这里使用获取的 Cookie 进行后续操作
|
|||
// recorder.loadCookiesFromFile("github_cookies_20231215_143022.json");
|
|||
|
|||
} catch (Exception e) { |
|||
System.err.println("程序执行异常: " + e.getMessage()); |
|||
e.printStackTrace(); |
|||
} finally { |
|||
// 5. 清理资源
|
|||
recorder.teardown(); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Cookie 数据模型类 |
|||
*/ |
|||
static class CookieData { |
|||
private String site; |
|||
private String url; |
|||
private String timestamp; |
|||
private List<Cookie> cookies; |
|||
|
|||
// 构造函数、getter、setter
|
|||
public CookieData() { |
|||
} |
|||
|
|||
public String getSite() { |
|||
return site; |
|||
} |
|||
|
|||
public void setSite(String site) { |
|||
this.site = site; |
|||
} |
|||
|
|||
public String getUrl() { |
|||
return url; |
|||
} |
|||
|
|||
public void setUrl(String url) { |
|||
this.url = url; |
|||
} |
|||
|
|||
public String getTimestamp() { |
|||
return timestamp; |
|||
} |
|||
|
|||
public void setTimestamp(String timestamp) { |
|||
this.timestamp = timestamp; |
|||
} |
|||
|
|||
public List<Cookie> getCookies() { |
|||
return cookies; |
|||
} |
|||
|
|||
public void setCookies(List<Cookie> cookies) { |
|||
this.cookies = cookies; |
|||
} |
|||
|
|||
public void addCookie(Cookie cookie) { |
|||
// 这里需要将 org.openqa.selenium.Cookie 转换为可序列化的对象
|
|||
// 或者直接使用 Cookie 类(它本身是可序列化的)
|
|||
// 简化处理:直接添加到列表
|
|||
if (this.cookies == null) { |
|||
this.cookies = new java.util.ArrayList<>(); |
|||
} |
|||
this.cookies.add(cookie); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
Manifest-Version: 1.0 |
|||
Main-Class: com.seleniumLib.crossrefDownLib |
|||
|
|||
@ -0,0 +1,3 @@ |
|||
Manifest-Version: 1.0 |
|||
Main-Class: com.seleniumLib.crossrefDownLib |
|||
|
|||
@ -0,0 +1,5 @@ |
|||
#Generated by Maven |
|||
#Tue Dec 23 18:30:25 CST 2025 |
|||
version=1.0-SNAPSHOT |
|||
groupId=com.example |
|||
artifactId=crossref |
|||
@ -0,0 +1,2 @@ |
|||
com\seleniumLib\SeleniumLoginWithCookieRecorder$CookieData.class |
|||
com\seleniumLib\SeleniumLoginWithCookieRecorder.class |
|||
@ -0,0 +1 @@ |
|||
D:\lzh\code\java_selenium_crosscheck_login\src\main\java\com\seleniumLib\SeleniumLoginWithCookieRecorder.java |
|||
Loading…
Reference in new issue