初始代码

This commit is contained in:
wangmingwei
2026-04-21 17:41:09 +08:00
parent 186ec6683a
commit b686ecac5f
493 changed files with 52349 additions and 0 deletions

View File

@@ -0,0 +1,35 @@
<?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>
<parent>
<groupId>com.yunzhupaas</groupId>
<artifactId>yunzhupaas-boot-common</artifactId>
<version>5.2.0-RELEASE</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>yunzhupaas-common-selenium</artifactId>
<dependencyManagement>
<dependencies>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,34 @@
package com.yunzhupaas.selenium;
import com.yunzhupaas.selenium.consts.SeleniumConsts;
import com.yunzhupaas.selenium.driver.SeleniumBrowser;
import com.yunzhupaas.selenium.properties.SeleniumProperties;
import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class SeleniumHelper implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Getter
@Setter
private static SeleniumProperties seleniumProperties;
public static <T extends SeleniumBrowser<?, ?, ?>> T getBrowser() {
SeleniumBrowser<?, ?, ?> seleniumBrowser = (SeleniumBrowser<?, ?, ?>) applicationContext.getBean(SeleniumConsts.BROWSER_BEAN_PREFIX + seleniumProperties.getBrowserType());
return (T) seleniumBrowser;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SeleniumHelper.applicationContext = applicationContext;
SeleniumHelper.seleniumProperties =applicationContext.getBean(SeleniumProperties.class);
}
}

View File

@@ -0,0 +1,35 @@
package com.yunzhupaas.selenium.autoconfiguration;
import com.yunzhupaas.selenium.SeleniumHelper;
import com.yunzhupaas.selenium.consts.SeleniumConsts;
import com.yunzhupaas.selenium.driver.ChromeBrowser;
import com.yunzhupaas.selenium.properties.SeleniumProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.*;
@Configuration(proxyBeanMethods = false)
@Import(SeleniumHelper.class)
@Slf4j
public class SeleniumAutoConfiguration {
@Bean
@ConfigurationProperties(SeleniumConsts.SELENIUM)
public SeleniumProperties getSeleniumProperties() {
return new SeleniumProperties();
}
@Lazy
@ConditionalOnMissingBean(name = SeleniumConsts.BROWSER_BEAN_PREFIX + SeleniumConsts.BROWSER_TYPE_CHROME)
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Bean(value = SeleniumConsts.BROWSER_BEAN_PREFIX + SeleniumConsts.BROWSER_TYPE_CHROME, initMethod = "init", destroyMethod = "close")
public ChromeBrowser getChromeBrowser() {
if(log.isDebugEnabled()){
log.debug(SeleniumConsts.MARKER, "Init New Chrome");
}
return new ChromeBrowser();
}
}

View File

@@ -0,0 +1,19 @@
package com.yunzhupaas.selenium.consts;
import org.slf4j.Marker;
import org.slf4j.MarkerFactory;
public class SeleniumConsts {
private SeleniumConsts() {
}
public static final String SELENIUM = "selenium";
public static final Marker MARKER = MarkerFactory.getMarker(SELENIUM);
public static final String BROWSER_TYPE_CHROME = "chrome";
public static final String BROWSER_BEAN_PREFIX = "selenium_";
}

View File

@@ -0,0 +1,100 @@
package com.yunzhupaas.selenium.driver;
import com.yunzhupaas.selenium.SeleniumHelper;
import com.yunzhupaas.selenium.consts.SeleniumConsts;
import com.yunzhupaas.selenium.properties.SeleniumProperties;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.openqa.selenium.remote.AbstractDriverOptions;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.remote.service.DriverService;
@Data
@Slf4j
public abstract class AbstractBrowser<D extends RemoteWebDriver, S extends DriverService, O extends AbstractDriverOptions<?>> implements SeleniumBrowser<D, S, O> {
protected D driverInstance;
protected S driverServiceInstance;
protected O driverOptionsInstance;
protected AbstractBrowser() {
this(null, null, null);
}
protected AbstractBrowser(D driver, S driverService, O driverOptions) {
this.driverInstance = driver;
this.driverServiceInstance = driverService;
this.driverOptionsInstance = driverOptions;
if (this.driverInstance == null) {
if (this.driverServiceInstance == null && this.driverOptionsInstance == null) {
this.driverServiceInstance = buildDriverService();
this.driverOptionsInstance = buildDriverOptions();
}
if(log.isDebugEnabled()){
log.debug(SeleniumConsts.MARKER, "创建浏览器, {}, {}", this.driverServiceInstance, this.driverOptionsInstance);
}
this.driverInstance = buildDriver(this.driverServiceInstance, this.driverOptionsInstance);
}
}
protected static SeleniumProperties getProperties() {
return SeleniumHelper.getSeleniumProperties();
}
protected abstract O buildDriverOptions();
protected abstract S buildDriverService();
protected abstract D buildDriver(S driverService, O driverOptions);
D buildDriver() {
return buildDriver(buildDriverService(), buildDriverOptions());
}
@Override
public D getDriver() {
return this.driverInstance;
}
@Override
public S getDriverService() {
return this.driverServiceInstance;
}
@Override
public O getDriverOptions() {
return this.driverOptionsInstance;
}
/**
* 初始化调用
*/
public void init() {
if(log.isDebugEnabled()){
log.debug(SeleniumConsts.MARKER, "浏览器实例初始化方法调用");
}
if(driverInstance != null) {
setScriptTimeout(getProperties().getScriptTimeout());
setPageLoadTimeout(getProperties().getPageLoadTimeout());
setImplicaitlyWaitTimeout(getProperties().getImplicaitlyWaitTimeout());
}
}
@Override
public void close() {
if(log.isDebugEnabled()){
log.debug(SeleniumConsts.MARKER, "浏览器实例销毁化方法调用");
}
if (driverInstance != null) {
try {
driverInstance.quit();
} catch (Exception e) {
log.error(SeleniumConsts.MARKER, "关闭浏览器出错", e);
}
}
}
}

View File

@@ -0,0 +1,62 @@
package com.yunzhupaas.selenium.driver;
import lombok.extern.slf4j.Slf4j;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeDriverService;
import org.openqa.selenium.chrome.ChromeOptions;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import java.util.function.Supplier;
@Slf4j
public class ChromeBrowser extends AbstractBrowser<ChromeDriver, ChromeDriverService, ChromeOptions> {
public static Supplier<ChromeOptions> defaultDriverOptionsSupplier = () -> {
System.setProperty(ChromeDriverService.CHROME_DRIVER_EXE_PROPERTY, getProperties().getDriverPath());
ChromeOptions options = new ChromeOptions();
//设置浏览器参数
options.addArguments("--headless");
options.addArguments("--disable-gpu");
options.addArguments("--no-sandbox");
options.addArguments("lang=zh_CN.UTF-8");
options.addArguments("--disable-dev-shm-usage");
//指定浏览器分辨率
options.addArguments("window-size=1920x1080");
//浏览器文件
if (StringUtils.hasText(getProperties().getBrowserPath())) {
options.setBinary(getProperties().getBrowserPath());
}
return options;
};
public static Supplier<ChromeDriverService> defaultDriverServiceSupplier = () -> null;
@Override
public ChromeOptions buildDriverOptions() {
return defaultDriverOptionsSupplier.get();
}
@Override
public ChromeDriverService buildDriverService() {
return defaultDriverServiceSupplier.get();
}
@Override
public ChromeDriver buildDriver(ChromeDriverService driverService, ChromeOptions driverOptions) {
Assert.notNull(System.getProperty(ChromeDriverService.CHROME_DRIVER_EXE_PROPERTY), "未设置浏览器驱动路径");
ChromeDriver driver;
if (driverService != null && driverOptions != null) {
driver = new ChromeDriver(driverService, driverOptions);
} else if (driverOptions != null) {
driver = new ChromeDriver(driverOptions);
} else if (driverService != null) {
driver = new ChromeDriver(driverService);
} else {
throw new IllegalArgumentException("service 或 options 不允许都为空");
}
return driver;
}
}

View File

@@ -0,0 +1,149 @@
package com.yunzhupaas.selenium.driver;
import com.yunzhupaas.selenium.SeleniumHelper;
import com.yunzhupaas.selenium.properties.SeleniumProperties;
import org.openqa.selenium.*;
import org.openqa.selenium.remote.AbstractDriverOptions;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.remote.service.DriverService;
import java.time.Duration;
import java.util.List;
import java.util.Map;
public interface SeleniumBrowser<D extends RemoteWebDriver, S extends DriverService, O extends AbstractDriverOptions<?>> {
D getDriver();
S getDriverService();
O getDriverOptions();
/**
* 关闭驱动和浏览器
*/
void close();
/**
* 设置页面加载超时时间
*/
default void setPageLoadTimeout(Duration duration) {
getDriver().manage().timeouts().pageLoadTimeout(duration);
}
/**
* 设置查找元素超时时间
*/
default void setImplicaitlyWaitTimeout(Duration duration) {
getDriver().manage().timeouts().implicitlyWait(duration);
}
/**
* 设置执行脚本超时时间
*/
default void setScriptTimeout(Duration duration) {
getDriver().manage().timeouts().scriptTimeout(duration);
}
/**
* 寻找元素, 若不存在抛出未找到元素异常
* 如需判断元素是否存在可调用{@link #findElements} 进行判空处理, 为空获取默认超时配置 {@link SeleniumProperties#getImplicaitlyWaitTimeout()}
*
* @param locator 查找条件
* @param findTimeout 最长等待时间
*/
default WebElement findElement(By locator, Duration findTimeout) {
findTimeout = findTimeout == null ? SeleniumHelper.getSeleniumProperties().getImplicaitlyWaitTimeout() : findTimeout;
setImplicaitlyWaitTimeout(findTimeout);
return getDriver().findElement(locator);
}
/**
* 寻找元素, 未找到元素返回空
*
* @param locator 查找条件
* @param findTimeout 最长等待时间, 为空获取默认超时配置 {@link SeleniumProperties#getImplicaitlyWaitTimeout()}
*/
default List<WebElement> findElements(By locator, Duration findTimeout) {
findTimeout = findTimeout == null ? SeleniumHelper.getSeleniumProperties().getImplicaitlyWaitTimeout() : findTimeout;
setImplicaitlyWaitTimeout(findTimeout);
return getDriver().findElements(locator);
}
/**
* 加载页面
* @param url 网页地址
* @param loadTimeout 加载超时时间, 为空获取默认超时配置 {@link SeleniumProperties#getPageLoadTimeout()}
* @param newTab 新窗口打开链接
*/
default void loadPage(String url, Duration loadTimeout, WindowType newTab) {
if (newTab != null) {
getDriver().switchTo().newWindow(newTab);
}
loadTimeout = loadTimeout == null ? SeleniumHelper.getSeleniumProperties().getPageLoadTimeout() : loadTimeout;
setPageLoadTimeout(loadTimeout);
getDriver().get(url);
}
/**
* 执行JS脚本
* @param script 脚本内容
* @param scriptTimeout 脚本执行超时时间, 为空获取默认超时配置 {@link SeleniumProperties#getScriptTimeout()}
* @param args 脚本内容参数
*/
default Object executeScript(String script, Duration scriptTimeout, Object... args){
scriptTimeout = scriptTimeout == null ? SeleniumHelper.getSeleniumProperties().getScriptTimeout() : scriptTimeout;
setScriptTimeout(scriptTimeout);
return getDriver().executeScript(script, args);
}
/**
* 获取最大的页面大小
*/
default Dimension getDocumentSize() {
Map<String, Long> result = (Map<String, Long>) getDriver().executeScript("return {'w':Math.max(document.body.scrollWidth, document.body.offsetWidth, document.documentElement.clientWidth, document.documentElement.scrollWidth, document.documentElement.offsetWidth), 'h':Math.max(document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight)}");
return new Dimension(Math.toIntExact(result.get("w")), Math.toIntExact(result.get("h")));
}
/**
* 窗口最大化, 截取全部网页内容
*/
default byte[] screenShotByWindow() {
getDriver().manage().window().setSize(getDocumentSize());
return getDriver().getScreenshotAs(OutputType.BYTES);
}
/**
* 窗口最大化, 截取指定元素
*/
default byte[] screenShotByElement(WebElement element) {
getDriver().manage().window().setSize(getDocumentSize());
return element.getScreenshotAs(OutputType.BYTES);
}
/**
* 可能存在懒加载, 滚动页面到底部进行触发, 每次滚动完后延时指定时间等待触发
* @param scrollDelay 每次滚动完后延时, 等待触发
*/
default void scrollToBottom(Duration scrollDelay) {
Dimension documentSize = getDocumentSize();
long height = documentSize.getHeight();
//这里需要模拟滑动,有些是滑动的时候才加载的
long temp_height = 0;
while (true) {
temp_height += 500;
if (temp_height >= height) {
break;
}
getDriver().executeScript("window.scrollBy(0,500)");
try {
Thread.sleep(scrollDelay.toMillis());
} catch (Exception e) {
}
}
}
}

View File

@@ -0,0 +1,44 @@
package com.yunzhupaas.selenium.properties;
import com.yunzhupaas.selenium.consts.SeleniumConsts;
import lombok.Data;
import java.time.Duration;
@Data
public class SeleniumProperties {
/**
* 浏览器类型
*/
private String browserType = SeleniumConsts.BROWSER_TYPE_CHROME;
/**
* 浏览器路径
*/
private String browserPath;
/**
* 浏览器驱动路径
*/
private String driverPath;
/**
* 页面加载超时时间
*/
private Duration pageLoadTimeout = Duration.ofSeconds(30L);
/**
* 查找元素超时时间
*/
private Duration implicaitlyWaitTimeout = Duration.ofSeconds(30L);
/**
* 执行脚本超时时间
*/
private Duration scriptTimeout = Duration.ofSeconds(30L);
}

View File

@@ -0,0 +1 @@
com.yunzhupaas.selenium.autoconfiguration.SeleniumAutoConfiguration