You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用AShot+Selenium ChromeDriver截取长网页不全问题求助

解决AShot截取超长网页截图不完整的内存优化方案

看起来你遇到的超长网页截图截断问题,很大概率确实是内存限制导致的——AShot在拼接数十个视口截图时,会占用大量堆内存,一旦内存不足就会出现截图不完整甚至OOM错误。结合你的代码,我给你几个针对性的优化方案:

1. 先给Java进程加足内存

最简单的第一步,运行你的Java程序时,通过JVM启动参数增加堆内存分配,避免内存瓶颈:

java -Xmx2G -Xms1G ashot_CompletePage

-Xmx2G表示最大堆内存为2GB,-Xms1G表示初始堆内存为1GB,你可以根据页面长度调整这个数值(比如超长页面可以加到-Xmx4G)。

2. 优化ChromeDriver的启动参数

给Chrome加上几个内存优化和渲染稳定的参数,减少浏览器本身的内存占用,同时避免渲染异常:

ChromeOptions options = new ChromeOptions();
options.addArguments("start-maximized");
options.addArguments("disable-infobars");
options.addArguments("--disable-extensions");
// 新增优化参数
options.addArguments("--disable-gpu"); // 禁用GPU加速,减少内存占用
options.addArguments("--disable-dev-shm-usage"); // 避免/dev/shm内存限制(Windows下也兼容)
options.addArguments("--no-sandbox"); // 关闭沙箱,减少内存开销
options.setPageLoadStrategy(PageLoadStrategy.EAGER); // 页面DOM加载完成就开始操作,不用等所有资源

注意:设置EAGER加载策略后,要确保你的WebDriverWait等待的是页面核心内容加载完成(比如你之前的titleContains("jQuery")就很合适)。

3. 调整AShot的截图策略

修改viewportPasting的参数,减少重叠区域裁剪,同时增加滚动后的等待时间,确保页面完全渲染:

// 第二个参数是裁剪掉的重叠像素,默认可能有冗余,设置为0减少内存消耗
// 同时把等待时间从100ms调整到200ms,确保长页面滚动后内容渲染完成
Screenshot myScreenshot = new AShot()
        .shootingStrategy(ShootingStrategies.viewportPasting(200, 0))
        .takeScreenshot(driver);

如果还是有截断,可以尝试使用viewportPastingWithScroll策略,它会更智能地处理滚动和拼接:

Screenshot myScreenshot = new AShot()
        .shootingStrategy(ShootingStrategies.viewportPastingWithScroll(200, 100))
        .takeScreenshot(driver);

4. 分块截取+手动拼接(内存友好终极方案)

如果上面的方法还是解决不了,那就换成分块截取的思路——每次只截取一个视口的内容,最后手动拼接成完整图片,这样内存压力会小很多:

import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
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 ru.yandex.qatools.ashot.AShot;
import ru.yandex.qatools.ashot.Screenshot;

public class ashot_CompletePage {
    public static void main(String[] args) throws Exception {
        System.setProperty("webdriver.chrome.driver", "C:\\Utility\\BrowserDrivers\\chromedriver.exe");
        ChromeOptions options = new ChromeOptions();
        options.addArguments("start-maximized");
        options.addArguments("disable-infobars");
        options.addArguments("--disable-extensions");
        options.addArguments("--disable-gpu");
        options.addArguments("--disable-dev-shm-usage");
        options.addArguments("--no-sandbox");
        
        WebDriver driver = new ChromeDriver(options);
        driver.get("https://www.smashingmagazine.com/2017/05/long-scrolling/");
        new WebDriverWait(driver, 20).until(ExpectedConditions.titleContains("jQuery"));

        JavascriptExecutor js = (JavascriptExecutor) driver;
        // 获取页面总高度和视口高度
        Long totalHeight = (Long) js.executeScript("return document.body.scrollHeight");
        Long viewportHeight = (Long) js.executeScript("return window.innerHeight");
        Long currentScroll = 0;
        List<BufferedImage> screenshotParts = new ArrayList<>();

        // 分块截取每个视口
        while (currentScroll < totalHeight) {
            // 滚动到当前位置
            js.executeScript("window.scrollTo(0, " + currentScroll + ")");
            // 等待页面渲染稳定
            Thread.sleep(300);
            // 截取当前视口
            Screenshot partShot = new AShot().takeScreenshot(driver);
            screenshotParts.add(partShot.getImage());
            // 滚动到下一个视口(减去50像素避免内容截断)
            currentScroll += viewportHeight - 50;
        }

        // 拼接所有截图块
        BufferedImage fullPageImage = new BufferedImage(
                screenshotParts.get(0).getWidth(),
                totalHeight.intValue(),
                BufferedImage.TYPE_INT_RGB
        );
        Graphics2D g2d = fullPageImage.createGraphics();
        int yPosition = 0;
        for (BufferedImage part : screenshotParts) {
            g2d.drawImage(part, 0, yPosition, null);
            yPosition += part.getHeight();
        }
        g2d.dispose();

        // 保存最终截图
        ImageIO.write(fullPageImage, "PNG", new File("./Screenshots/fullPageScreenshot.png"));
        driver.quit();
    }
}

这个方法的核心是每次只处理一个视口的图片,不会一次性把所有拼接后的大图放在内存里,对超长页面特别友好。

5. 优化图片输出格式

如果输出PNG格式内存占用太高,可以改为JPEG格式并设置压缩质量,进一步减少内存消耗:

// 直接输出JPEG
ImageIO.write(fullPageImage, "JPEG", new File("./Screenshots/fullPageScreenshot.jpg"));

// 或者设置精细的压缩质量(0.8表示80%质量,平衡清晰度和大小)
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import java.io.FileOutputStream;

JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(new FileOutputStream(new File("./Screenshots/fullPageScreenshot.jpg")));
JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(fullPageImage);
param.setQuality(0.8f, true);
encoder.encode(fullPageImage, param);

你可以从第一个方案开始尝试,逐步排查,应该能解决截图不完整的问题。

内容的提问来源于stack exchange,提问作者sankar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:27:26