java 生成浏览器截长图
项目中有需要用到截网页图片的功能
技术方案
使用 selenium 结合 chrome 模拟浏览器打开网页,然后对网页进行截图保存
实现
引入依赖
<dependency>
<groupId>ru.yandex.qatools.ashot</groupId>
<artifactId>ashot</artifactId>
<version>1.5.4</version>
</dependency>
<!--selenium-java 版本要和chrome一致-->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.20.0</version>
</dependency>
<dependency>
下载浏览器驱动
- 查看chrome版本
- 在chrome浏览器地址栏输入:
chrome://version/
, 我这里是 124版本
- 在chrome浏览器地址栏输入:
- 下载驱动
代码实现
package com.icmp.dt.datongbak.banner;
import cn.hutool.core.io.FileUtil;
import com.sun.source.doctree.SeeTree;
import lombok.extern.slf4j.Slf4j;
import org.openqa.selenium.Dimension;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.Platform;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.support.ui.WebDriverWait;
import ru.yandex.qatools.ashot.AShot;
import ru.yandex.qatools.ashot.Screenshot;
import ru.yandex.qatools.ashot.coordinates.WebDriverCoordsProvider;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
/**
* @Date: 2024/4/28 14:28
*/
@Slf4j
public class ChromeCapture {
// webdriver驱动解压位置
private static final String DRIVER_URL = "E:\\chromedriver-win64\\chromedriver.exe";
private static WebDriver driver = null;
static {
ChromeOptions options = new ChromeOptions();
//无头,不在操作系统上打开chrome应用
options.addArguments("--headless");
//options.addArguments("--disable-gpu");
options.addArguments("--no-sandbox");
driver = new ChromeDriver(options);
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
driver.manage().window().maximize();
}
public static void main(String[] args) throws InterruptedException {
fullScreenShotPng("",new File("a.PNG"));
quit();
}
/**
* 截PNG长图
* @param url
* @param file
* @throws InterruptedException
*/
public static void fullScreenShotPng(String url,File file) throws InterruptedException {
fullScreenShot(url,300,500L,file,"PNG");
}
/**
* 截长图
* @param url 网页地址
* @param rollingDistance 300 滚动距离
* @param waitTime 500 毫秒
* @param file 保存文件
* @throws InterruptedException
*/
public static void fullScreenShot(String url,int rollingDistance,Long waitTime,File file, String suffix) throws InterruptedException {
System.setProperty("webdriver.chrome.driver",DRIVER_URL);
try {
driver.get(url);
//等待页面加载完成
new WebDriverWait(driver, Duration.ofSeconds(20)).until(drive -> ((JavascriptExecutor) drive)
.executeScript("return document.readyState").equals("complete"));
// 设置小的分辨率
//driver.manage().window().setSize(new Dimension(1920, 1080));
JavascriptExecutor je = (JavascriptExecutor) driver;
// 通过执行脚本解决Selenium截图不全问题
String jsHeight = "return document.body.clientHeight";
int height = Integer.parseInt(je.executeScript(jsHeight)+"");
// 滚动次数
int frequency = height % rollingDistance == 0 ? height / rollingDistance : height / rollingDistance + 1;
for (int i = 0; i < frequency; i++) {
int length = i * rollingDistance;
Thread.sleep(waitTime);
((JavascriptExecutor) driver).executeScript("window.scrollTo(0," + length + ")");
}
//设置浏览窗口大小
int maxWidth = Integer.parseInt(je.executeScript(
"return Math.max(document.body.scrollWidth, document.body.offsetWidth, document.documentElement" +
".clientWidth, document.documentElement.scrollWidth, document.documentElement" +
".offsetWidth);")+"");
int maxHeight = Integer.parseInt(je.executeScript(
"return Math.max(document.body.scrollHeight, document.body.offsetHeight, document.documentElement" +
".clientHeight, document.documentElement.scrollHeight, document.documentElement" +
".offsetHeight);")+"");
Dimension targetSize = new Dimension((int)maxWidth, (int)maxHeight);
driver.manage().window().setSize(targetSize);
// 重新拉到页面顶端
((JavascriptExecutor) driver).executeScript("window.scrollTo(document.body.scrollHeight,0)");
// 截图
Screenshot screenshot = new AShot().coordsProvider(new WebDriverCoordsProvider()).takeScreenshot(driver);
BufferedImage image = screenshot.getImage();
ImageIO.write(image, suffix, file);
} catch (Exception e) {
log.error("快照失败: {}",url, e);
}
}
public static void quit(){
if (driver!=null){
driver.quit();
}
}
}
截图效果: