From d0a930d4f20287c8fc094af0a046450688a31d1f Mon Sep 17 00:00:00 2001
From: zhangzijienbplus <17738440858@163.com>
Date: Wed, 29 Oct 2025 16:36:34 +0800
Subject: [PATCH] =?UTF-8?q?feat(selenium):=E9=87=8D=E6=9E=84ChromeDriver?=
=?UTF-8?q?=E9=A2=84=E5=8A=A0=E8=BD=BD=E4=B8=8E=E9=98=B2=E6=A3=80=E6=B5=8B?=
=?UTF-8?q?=E9=85=8D=E7=BD=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 移除旧的WebDriverManager配置逻辑
- 新增SeleniumStealthUtil工具类,集成防检测脚本
- 实现全局单例ChromeDriver Bean管理- 添加驱动生命周期自动清理机制
-优化驱动创建参数,增强浏览器伪装能力
- 移除无用的线程池销毁方法
- 调整配置类注解与加载顺序
---
erp_client_sb/pom.xml | 3 -
.../erp/config/ChromeDriverPreloader.java | 68 +++++++----------
.../tashow/erp/utils/SagawaExpressSdk.java | 9 ---
.../tashow/erp/utils/SeleniumStealthUtil.java | 73 +++++++++++++++++++
.../tashow/erp/utils/TrademarkCheckUtil.java | 37 ++++++++++
5 files changed, 136 insertions(+), 54 deletions(-)
create mode 100644 erp_client_sb/src/main/java/com/tashow/erp/utils/SeleniumStealthUtil.java
create mode 100644 erp_client_sb/src/main/java/com/tashow/erp/utils/TrademarkCheckUtil.java
diff --git a/erp_client_sb/pom.xml b/erp_client_sb/pom.xml
index fcd5c48..7bf475e 100644
--- a/erp_client_sb/pom.xml
+++ b/erp_client_sb/pom.xml
@@ -54,9 +54,7 @@
webmagic-extension
1.0.3
-
-
org.projectlombok
lombok
@@ -118,7 +116,6 @@
0.11.5
runtime
-
com.github.oshi
diff --git a/erp_client_sb/src/main/java/com/tashow/erp/config/ChromeDriverPreloader.java b/erp_client_sb/src/main/java/com/tashow/erp/config/ChromeDriverPreloader.java
index 5d8b2a1..c1ccaa4 100644
--- a/erp_client_sb/src/main/java/com/tashow/erp/config/ChromeDriverPreloader.java
+++ b/erp_client_sb/src/main/java/com/tashow/erp/config/ChromeDriverPreloader.java
@@ -1,58 +1,42 @@
package com.tashow.erp.config;
-
-import io.github.bonigarcia.wdm.WebDriverManager;
+import com.tashow.erp.utils.SeleniumStealthUtil;
+import jakarta.annotation.PreDestroy;
import lombok.extern.slf4j.Slf4j;
import org.openqa.selenium.chrome.ChromeDriver;
-import org.openqa.selenium.chrome.ChromeOptions;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
-import org.springframework.stereotype.Component;
-import java.net.URL;
/**
- * ChromeDriver预加载器
- * 在应用启动时后台下载ChromeDriver,避免用户首次使用时等待
- * 使用国内镜像源加速下载
+ * ChromeDriver 配置类
+ * 启动时后台预加载驱动,提供全局单例 Bean
*/
@Slf4j
-@Component
-@Order(2) // 在DatabaseConfig之后运行
+@Configuration
+@Order(100)
public class ChromeDriverPreloader implements ApplicationRunner {
-
+
+ private ChromeDriver globalDriver;
+
@Override
public void run(ApplicationArguments args) {
- // 使用后台线程执行,不阻塞应用启动
- Thread preloadThread = new Thread(() -> {
- try {
- log.info("开始预加载ChromeDriver驱动(使用国内镜像加速)...");
-
- // 配置WebDriverManager使用国内镜像源
- WebDriverManager.chromedriver()
- .driverRepositoryUrl(new URL("https://registry.npmmirror.com/-/binary/chromedriver/"))
- .setup();
-
- log.info("ChromeDriver驱动下载完成,开始验证...");
-
- // 快速验证驱动可用性
- ChromeOptions options = new ChromeOptions();
- options.addArguments("--headless"); // 无头模式,不显示浏览器
- options.addArguments("--disable-gpu");
- options.addArguments("--no-sandbox");
-
- ChromeDriver driver = new ChromeDriver(options);
- driver.quit(); // 立即关闭
-
- log.info("ChromeDriver驱动预加载成功");
-
- } catch (Exception e) {
- // 预加载失败不影响应用启动,第一次使用时会自动下载
- log.warn("ChromeDriver驱动预加载失败(不影响使用): {}", e.getMessage());
- }
- }, "ChromeDriver-Preloader");
-
- preloadThread.setDaemon(true); // 设置为守护线程
- preloadThread.start();
+ new Thread(() -> {
+ globalDriver = SeleniumStealthUtil.createDriver(true);
+ log.info("ChromeDriver 预加载完成");
+ }, "ChromeDriver-Preloader").start();
+ }
+
+ @Bean
+ public ChromeDriver chromeDriver() {
+ if (globalDriver == null) globalDriver = SeleniumStealthUtil.createDriver(true);
+ return globalDriver;
+ }
+
+ @PreDestroy
+ public void cleanup() {
+ globalDriver.quit();
}
}
diff --git a/erp_client_sb/src/main/java/com/tashow/erp/utils/SagawaExpressSdk.java b/erp_client_sb/src/main/java/com/tashow/erp/utils/SagawaExpressSdk.java
index 8f759df..36e7905 100644
--- a/erp_client_sb/src/main/java/com/tashow/erp/utils/SagawaExpressSdk.java
+++ b/erp_client_sb/src/main/java/com/tashow/erp/utils/SagawaExpressSdk.java
@@ -1,5 +1,4 @@
package com.tashow.erp.utils;
-
import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -7,7 +6,6 @@ import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.Spider;
import us.codecraft.webmagic.processor.PageProcessor;
-
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
@@ -19,13 +17,6 @@ public class SagawaExpressSdk {
private static final Logger logger = LoggerFactory.getLogger(SagawaExpressSdk.class);
private final ExecutorService executorService = Executors.newFixedThreadPool(10);
private int timeout = 5000; // 默认超时时间5秒
- /**
- * 关闭线程池
- */
-// @PreDestroy
- public void destroy() {
- executorService.shutdownNow();
- }
/**
* 查询佐川急便物流信息 - API入口
*/
diff --git a/erp_client_sb/src/main/java/com/tashow/erp/utils/SeleniumStealthUtil.java b/erp_client_sb/src/main/java/com/tashow/erp/utils/SeleniumStealthUtil.java
new file mode 100644
index 0000000..128959d
--- /dev/null
+++ b/erp_client_sb/src/main/java/com/tashow/erp/utils/SeleniumStealthUtil.java
@@ -0,0 +1,73 @@
+package com.tashow.erp.utils;
+
+import io.github.bonigarcia.wdm.WebDriverManager;
+import org.openqa.selenium.chrome.ChromeDriver;
+import org.openqa.selenium.chrome.ChromeOptions;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Collections;
+import java.util.Map;
+
+/**
+ * Selenium 防检测工具类
+ * 提供配置好的 ChromeDriver,隐藏自动化痕迹
+ */
+public class SeleniumStealthUtil {
+
+ /**
+ * 创建防检测的 ChromeDriver
+ * @param headless 是否启用无头模式
+ * @return 配置好的 ChromeDriver
+ */
+ public static ChromeDriver createDriver(boolean headless) {
+ try {
+ WebDriverManager.chromedriver()
+ .driverRepositoryUrl(new URL("https://registry.npmmirror.com/-/binary/chromedriver/"))
+ .setup();
+
+ ChromeOptions options = new ChromeOptions();
+
+ // 三板斧:移除自动化特征
+ options.addArguments("--disable-blink-features=AutomationControlled");
+ options.setExperimentalOption("excludeSwitches", Collections.singletonList("enable-automation"));
+ options.setExperimentalOption("useAutomationExtension", false);
+
+ // 常规参数
+ options.addArguments("--no-sandbox", "--disable-gpu", "--disable-dev-shm-usage");
+ 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");
+
+ // 无头模式
+ if (headless) {
+ options.addArguments("--headless=new");
+ }
+
+ ChromeDriver driver = new ChromeDriver(options);
+
+ // 注入完整 stealth 脚本
+ String stealthScript = """
+ Object.defineProperty(navigator, 'webdriver', {get: () => undefined});
+ Object.defineProperty(navigator, 'plugins', {get: () => [1, 2, 3, 4, 5]});
+ Object.defineProperty(navigator, 'languages', {get: () => ['en-US', 'en']});
+ window.chrome = {runtime: {}};
+ Object.defineProperty(navigator, 'permissions', {
+ get: () => ({
+ query: () => Promise.resolve({state: 'prompt'})
+ })
+ });
+ const getParameter = WebGLRenderingContext.prototype.getParameter;
+ WebGLRenderingContext.prototype.getParameter = function(parameter) {
+ if (parameter === 37445) return 'Intel Inc.';
+ if (parameter === 37446) return 'Intel Iris OpenGL Engine';
+ return getParameter.call(this, parameter);
+ };
+ """;
+
+ driver.executeCdpCommand("Page.addScriptToEvaluateOnNewDocument", Map.of("source", stealthScript));
+ return driver;
+ } catch (Exception e) {
+ throw new RuntimeException("创建浏览器失败", e);
+ }
+ }
+}
+
diff --git a/erp_client_sb/src/main/java/com/tashow/erp/utils/TrademarkCheckUtil.java b/erp_client_sb/src/main/java/com/tashow/erp/utils/TrademarkCheckUtil.java
new file mode 100644
index 0000000..a09a600
--- /dev/null
+++ b/erp_client_sb/src/main/java/com/tashow/erp/utils/TrademarkCheckUtil.java
@@ -0,0 +1,37 @@
+package com.tashow.erp.utils;
+import org.openqa.selenium.JavascriptExecutor;
+import org.openqa.selenium.chrome.ChromeDriver;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class TrademarkCheckUtil {
+ @Autowired
+ private ChromeDriver driver;
+ public boolean checkTrademark(String brandName) {
+ try {
+ driver.get("https://tmsearch.uspto.gov/search/search-results");
+ Thread.sleep(2000);
+ String script = String.format("""
+ return fetch('https://tmsearch.uspto.gov/prod-stage-v1-0-0/tmsearch', {
+ method: 'POST',
+ headers: {'Content-Type': 'application/json'},
+ body: JSON.stringify({
+ query: {bool: {must: [{bool: {should: [
+ {match_phrase: {WM: {query: '%s', boost: 5}}},
+ {match: {WM: {query: '%s', boost: 2}}},
+ {match_phrase: {PM: {query: '%s', boost: 2}}}
+ ]}}]}},
+ size: 1, _source: ['alive']
+ })
+ }).then(r => r.json()).then(d => d?.hits?.hits?.[0]?.source?.alive || false);
+ """, brandName, brandName, brandName);
+ Object result = ((JavascriptExecutor) driver).executeAsyncScript("var callback = arguments[arguments.length - 1];" + script.replace("return", "").replace(";", ".then(callback);"));
+ return Boolean.TRUE.equals(result);
+ } catch (Exception e) {
+ System.err.println("检测失败: " + e.getMessage());
+ return false;
+ }
+ }
+
+}