借助Selenium实现网页截图来生成应用封面

news/2025/10/13 17:20:19/文章来源:https://www.cnblogs.com/lxjshuju/p/19138942

一. 什么是Selenium

Selenium 是一个开源的 Web 应用程序自动化测试工具集,主要用于模拟用户在浏览器中的各种操作,实现对 Web 应用的自动化测试、数据爬取、定期任务执行等功能。其核心是 WebDriver,它提供了一套跨编程语言、跨浏览器的 API,让开发者可以通过代码控制浏览器行为(如点击、输入、跳转、截图等)。

Selenium的官方文档:Selenium 浏览器自动化项目 | Selenium

在实际使用建议搭配WebDriverManager使用,可以自动化管理浏览器驱动。解决了开发中的许多痛点:

1. 无需手动下载浏览器驱动,告别找版本、下文件的繁琐;

2. 自动匹配浏览器版本,避免因版本不兼容导致的运行失败;

3. 省去环境变量配置,代码无需硬编码驱动路径,跨机器/系统运行更顺畅;

4. 简化跨环境和团队协作,不用手动同步各环境的驱动版本,降低维护成本。

对比维度不使用 WebDriverManager使用 WebDriverManager
驱动与版本手动下载,需人工匹配浏览器版本,易因更新报错自动检测浏览器版本,下载匹配驱动,适配更新
环境配置需手动配置环境变量或硬编码路径,换环境需重配无需配置,自动管理驱动路径,跨环境通用
跨环境 / 团队协作需手动同步所有环境驱动,易出现不一致问题自动适配环境,代码一次编写多环境可用
维护与错误风险需人工维护驱动,版本 / 路径问题易导致运行失败全自动化管理,大幅降低维护成本和错误风险

二. 开发实现

1. 本地生成截图

1.1 引入Selenium网页截图依赖

org.seleniumhq.seleniumselenium-java4.33.0

io.github.bonigarciawebdrivermanager6.1.0

1.2 提供根据URL生成截图文件并返回路径的方法,用于网页截图

1.初始化驱动

@Slf4j
public class WebScreenshotUtils {private static final WebDriver webDriver;static {final int DEFAULT_WIDTH = 1600;final int DEFAULT_HEIGHT = 900;webDriver = initChromeDriver(DEFAULT_WIDTH, DEFAULT_HEIGHT);}@PreDestroypublic void destroy() {webDriver.quit();}/*** 初始化 Chrome 浏览器驱动*/private static WebDriver initChromeDriver(int width, int height) {try {// 自动管理 ChromeDriverWebDriverManager.chromedriver().setup();// 配置 Chrome 选项ChromeOptions options = new ChromeOptions();// 无头模式(Chrome浏览器在后台运行,不会弹出窗口)options.addArguments("--headless");// 禁用GPU(在某些环境下避免问题)options.addArguments("--disable-gpu");// 禁用沙盒模式(Docker环境需要)options.addArguments("--no-sandbox");// 禁用开发者shm使用options.addArguments("--disable-dev-shm-usage");// 设置窗口大小options.addArguments(String.format("--window-size=%d,%d", width, height));// 禁用扩展options.addArguments("--disable-extensions");// 设置用户代理options.addArguments("--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36");// 创建驱动WebDriver driver = new ChromeDriver(options);// 设置页面加载超时driver.manage().timeouts().pageLoadTimeout(Duration.ofSeconds(30));// 设置隐式等待driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));return driver;} catch (Exception e) {log.error("初始化 Chrome 浏览器失败", e);throw new BusinessException(ErrorCode.SYSTEM_ERROR, "初始化 Chrome 浏览器失败");}}
}

这是样板代码。

重点:

(1)在静态代码块里初始化驱动,确保整个应用生命周期内只初始化一次

(2)默认使用已经初始化好的驱动实例

(3)在项目停止前正确销毁驱动,释放资源

2. 编写子方法

/*** 保存图片到文件*/
private static void saveImage(byte[] imageBytes, String imagePath) {try {FileUtil.writeBytes(imageBytes, imagePath);} catch (Exception e) {log.error("保存图片失败: {}", imagePath, e);throw new BusinessException(ErrorCode.SYSTEM_ERROR, "保存图片失败");}
}
/*** 压缩图片*/
private static void compressImage(String originalImagePath, String compressedImagePath) {// 压缩图片质量(0.1 = 10% 质量)清晰度还行,且减少文件大小final float COMPRESSION_QUALITY = 0.3f;try {ImgUtil.compress(FileUtil.file(originalImagePath),FileUtil.file(compressedImagePath),COMPRESSION_QUALITY);} catch (Exception e) {log.error("压缩图片失败: {} -> {}", originalImagePath, compressedImagePath, e);throw new BusinessException(ErrorCode.SYSTEM_ERROR, "压缩图片失败");}
}
/*** 等待页面加载完成*/
private static void waitForPageLoad(WebDriver driver) {try {// 创建等待页面加载对象WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));// 等待 document.readyState 为completewait.until(webDriver ->((JavascriptExecutor) webDriver).executeScript("return document.readyState").equals("complete"));// 额外等待一段时间,确保动态内容加载完成Thread.sleep(2000);log.info("页面加载完成");} catch (Exception e) {log.error("等待页面加载时出现异常,继续执行截图", e);}
}

3. 编写完整的截图方法,思路是访问页面->等待页面加载完成->截图->保存截图文件并压缩->返回压缩后的路径。

/*** 生成网页截图** @param webUrl 网页URL* @return 压缩后的截图文件路径,失败返回null*/
public static String saveWebPageScreenshot(String webUrl) {if (StrUtil.isBlank(webUrl)) {log.error("网页URL不能为空");return null;}try {// 创建临时目录String rootPath = System.getProperty("user.dir") + File.separator + "tmp" + File.separator + "screenshots"+ File.separator + UUID.randomUUID().toString().substring(0, 8);FileUtil.mkdir(rootPath);// 图片后缀final String IMAGE_SUFFIX = ".png";// 原始截图文件路径String imageSavePath = rootPath + File.separator + RandomUtil.randomNumbers(5) + IMAGE_SUFFIX;// 访问网页webDriver.get(webUrl);// 等待页面加载完成waitForPageLoad(webDriver);// 截图byte[] screenshotBytes = ((TakesScreenshot) webDriver).getScreenshotAs(OutputType.BYTES);// 保存原始图片saveImage(screenshotBytes, imageSavePath);log.info("原始截图保存成功: {}", imageSavePath);// 压缩图片final String COMPRESSION_SUFFIX = "_compressed.jpg";String compressedImagePath = rootPath + File.separator + RandomUtil.randomNumbers(5) + COMPRESSION_SUFFIX;compressImage(imageSavePath, compressedImagePath);log.info("压缩图片保存成功: {}", compressedImagePath);// 删除原始图片,只保留压缩图片FileUtil.del(imageSavePath);return compressedImagePath;} catch (Exception e) {log.error("网页截图失败: {}", webUrl, e);return null;}
}

2. 保存截图到对象存储

将生成的封面图上传到腾讯云COS对象存储,使得其能够持久化存储并快速访问。

1.1 在腾讯云控制台中创建一个存储桶:存储桶列表 - 对象存储 - 控制台

1.2 在配置文件中添加COS相关配置

cos:client:host: your-custom-domain.comsecretId: your-secret-idsecretKey: your-secret-keyregion: ap-shanghaibucket: your-bucket-name

1.3 引入依赖

com.qcloudcos_api5.6.227

1.4 创建COS客户端配置类

/*** 腾讯云COS配置类*/
@Configuration
@ConfigurationProperties(prefix = "cos.client")
@Data
public class CosClientConfig {/*** 域名*/private String host;/*** secretId*/private String secretId;/*** 密钥(注意不要泄露)*/private String secretKey;/*** 区域*/private String region;/*** 桶名*/private String bucket;@Beanpublic COSClient cosClient() {// 初始化用户身份信息(secretId, secretKey)COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);// 设置bucket的区域, COS地域的简称请参照 https://www.qcloud.com/document/product/436/6224ClientConfig clientConfig = new ClientConfig(new Region(region));// 生成cos客户端return new COSClient(cred, clientConfig);}
}

1.5 创建可复用的CosManager类,专门负责和COS对象存储进行交互,提供文件上传功能。

/*** COS对象存储管理器*/
@Component
@Slf4j
public class CosManager {@Resourceprivate CosClientConfig cosClientConfig;@Resourceprivate COSClient cosClient;/*** 上传对象** @param key  唯一键* @param file 文件* @return 上传结果*/public PutObjectResult putObject(String key, File file) {PutObjectRequest putObjectRequest = new PutObjectRequest(cosClientConfig.getBucket(), key, file);return cosClient.putObject(putObjectRequest);}/*** 上传文件到 COS 并返回访问 URL** @param key  COS对象键(完整路径)* @param file 要上传的文件* @return 文件的访问URL,失败返回null*/public String uploadFile(String key, File file) {// 上传文件PutObjectResult result = putObject(key, file);if (result != null) {// 构建访问URLString url = String.format("%s%s", cosClientConfig.getHost(), key);log.info("文件上传COS成功: {} -> {}", file.getName(), url);return url;} else {log.error("文件上传COS失败,返回结果为空");return null;}}
}

3. 服务优化

在生成截图时,提供静态方法初始化了一个全局公用的WebDriver来避免重复加载。

优点是性能高,但是在并发截图的场景下,如果共用一个WebDriver,可能会导致截图错误的页面。

// 危险:多线程共享同一个driver
private static final WebDriver webDriver = new ChromeDriver();
// 线程A: driver.get("page1.html") -> 截图
// 线程B: driver.get("page2.html") -> 截图
// 结果:线程 A 可能截到 page2 的内容

优化思路:

ThreadLocal 模式,每个线程使用同一个WebDriver:

private static final ThreadLocal driverThreadLocal = new ThreadLocal<>();
public static WebDriver getDriver() {WebDriver driver = driverThreadLocal.get();if (driver == null) {driver = initChromeDriver();driverThreadLocal.set(driver);}return driver;
}

优点是实现简单,能够解决并发问题,缺点是当线程较多时可能会导致内存溢出。

4. 功能优化

定期清理本地临时生成的封面文件,以及在应用删除时关联删除对应的封面图,避免资源浪费。

用Spring Scheduler写一个定时任务:

@Configuration
@EnableScheduling
@Slf4j
public class ScreenshotConfig {/*** 每天凌晨2点清理过期的临时截图文件*/@Scheduled(cron = "0 0 2 * * ?")public void cleanupTempScreenshots() {log.info("开始定时清理过期的临时截图文件");try {WebScreenshotUtils.cleanupTempFiles();log.info("定时清理临时截图文件完成");} catch (Exception e) {log.error("定时清理临时截图文件失败", e);}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/936282.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

恒温恒湿试验箱多少钱一台?2025年最新价格,由上海柏毅提供!

恒温恒湿试验箱的价格受容积、温湿度范围、控制精度、品牌及功能配置等多因素影响,市场价格跨度较大。以下是上海柏毅提供的最新数据的详细分析: 设备名称 内箱容积 建议起售价 48L …

从底层到应用:开散列哈希表与_map/_set 的完整实现(附逐行注释) - 实践

从底层到应用:开散列哈希表与_map/_set 的完整实现(附逐行注释) - 实践pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family…

学习日报 20250928|React 中实现 “实时检测”:useEffect 依赖项触发机制详解 - 实践

学习日报 20250928|React 中实现 “实时检测”:useEffect 依赖项触发机制详解 - 实践pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important;…

日志|JavaScript

XML数据没多少标签一大堆事件监听事件种类

UNION类SQL注入步骤总结

UNION类SQL注入步骤总结

MQTT的使用

客户端重连机制public static void Reconnect_Using_Timer(){/** This sample shows how to reconnect when the connection was dropped.* This approach uses a custom Task/Thread which will monitor the connecti…

iOS 26 电耗监测与优化,耗电问题实战 + 多工具 辅助策略

本文聚焦 iOS 26 电耗 /耗电监测 /省电策略 /电量优化,结合媒体实测与 Apple 正式声明,分析 Liquid Glass 界面、Adaptive Power 模式、系统后台任务等对电量的影响,设计详细的电耗监测指标体系与实战流程。很多用户…

详细介绍:[wps_clear]wps清理残余 ——注册表不干净

详细介绍:[wps_clear]wps清理残余 ——注册表不干净2025-10-13 17:02 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; dis…

moectf2025

misc ez_LSB 放入stegsolve.jarbase64解密为:SSTV查询到可以用qsstv程序进行解码来恢复图片。 初次尝试发现附件不能直接放进qsstv,需要删掉下图LIST蓝色部分(生成软件FFmpeg(Lavf57.52.100)的标识)才能被qsstv正…

VRay 6.1 for Rhino 6-8 安装教程与功能详解(含图文步骤)

软件介绍 VRay 6.1 for Rhino 6-8是由Chaos Group推出的专业三维模型渲染插件,专为Rhino 6至8版本设计。该软件集成多平台兼容性,支持Windows与Mac OS系统无缝运行,可实现跨设备数据交换与协同工作。其核心渲染引擎…

网络编程实践笔记_3_阿贝云_免费云服务器_远程操作的一些小提示

git bash 操作记录如果你已经把服务启动了,应该就不用看这里了,不过先给启动起来的做个小提醒: 后台模式 用 nohup gunicorn 启动起来的服务,要额外 kill 掉才会终止,不然还是会一直运行并占用端口的哦。 执行命令…

读书笔记:深入理解 Oracle 的 DATE 类型:存储、计算与最佳实践

我们的文章会在微信公众号IT民工的龙马人生和博客网站( www.htz.pw )同步更新 ,欢迎关注收藏,也欢迎大家转载,但是请在文章开始地方标注文章出处,谢谢! 由于博客中有大量代码,通过页面浏览效果更佳。本文为个人学…

一文读懂:C++ STL 学生与竞赛选手都会遇到的容器默认排序的疑惑

C++ STL 学生与竞赛选手都会遇到的疑惑。 下面我们系统讲清楚:🧩 一、结论速览表:STL 常见数据结构默认排序方向容器类型 默认排序方向 底层实现 比较器默认类型 改为从大到小的写法std::set 从小到大(升序) 红黑…

零基础新手的以太坊质押(Staking)终极科普文章

零基础新手的以太坊质押(Staking)终极科普文章。我们将用最生活化的比喻,揭开它神秘的面纱。不再挖矿,变身“数字银行股东”:一文读懂以太坊质押 想象一下,以前的以太坊就像一个巨大的“数字挖矿游戏”,而今天,…

常见应用案例,AI应用开发流程

AI应用开发流程: 1.分析需求; 2.找对应的模型,分析匹配合适的模型; 3.下载模型,跑数据集测试 4.应用 1 文生图模型: 2 图生文: 图片文本识别,提取文本,识别车牌号: 3.识别表单文本 https://github.com/Paddl…

对数据要求高的On-the-fly

必须是有序序列(Sequence is Mandatory) 不支持无序数据集(如 Zip-NeRF 风格或许多 DeepBlending 场景)。 要求图像按顺序捕获,且连续帧之间必须有足够的重叠(理想情况下超过 2/3 的内容)。 严格的运动要求(Tr…

计算机视觉(opencv)——基于 dlib 的实时摄像头人脸检测 - 教程

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

【开题答辩全过程】以 springboot+美食电子商城的设计与实现为例,含有答辩的问题和答案

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

程序设计实践训练(Day1) - --YZ-

程序设计实践训练(Day1)Posted on 2025-10-13 16:46 --YZ-- 阅读(0) 评论(0) 收藏 举报程序设计实践训练(Day1) 第一——判断 对任何一个正整数 n,如果它是偶数,那么把它砍掉一半;如果它是奇数,那么把 (3n+…

vmware部署win7,win2008,win2012等系统如何手动安装vmware tools

vmware部署win7,win2008,win2012等系统如何手动安装vmware toolswin10和win11都能自动安装vmware tools,但win7,win2008和win2012必须手动安装,Windows版的vmware toos镜像名称是windows.iso,路径在VMware Works…