Java+Selenium如何实现将HTML页面转换成图片?

新手上路,请多包涵

Java+Selenium如何实现将HTML页面转换成图片?

  1. 对于页面总高度比较小的页面,可以直接给Dimension设置一个比较大的高度,一次性截取;但是对于页面总高度比较大的页面,即使给Dimension设置一个非常大的高度,也无法截取完整的页面.
  2. 因为上述原因,我使用window.scrollBy(0,X)来滑动页面,想每次截高度X的内容,然后向下移动X,然后重新截图.但从结果来看,并不符合预期.截取的图片存在部分内容缺失.

我创建了一个最简单的页面,从下图可以看出,234~240丢失了,我想可能是scrollBy的原因,但是我不知道该怎么解决这个问题.

<!DOCTYPE html>
<html lang="en">

<body>
  1<br>
  2<br>
  3<br>
  4<br>
  5<br>
  .....
  800<br>
</body>
</html>

image.png
image.png

public class HtmlToImage_Selenium {

  public static void main(String[] args) {

    // 路径
    String chromePath = "D:\\htmlToImg\\Selenium\\chromedriver-win64\\chromedriver.exe";
    String mergePath = "D:\\htmlToImg\\Selenium\\output\\merge.png";
    String tempPath = "D:\\htmlToImg\\Selenium\\output\\screenshot_";

    // 设置 ChromeDriver 路径
    System.setProperty("webdriver.chrome.driver", chromePath);

    // 设置 Chrome 选项
    ChromeOptions options = new ChromeOptions();
    // 无头模式
    options.addArguments("--headless");
    // 窗口大小
    options.addArguments("--window-size=2160,1440");

    // 创建 ChromeDriver
    WebDriver driver = new ChromeDriver(options);

    try {
      // 加载 HTML 文件
      driver.get("file:///D:/htmlToImg/Test.html");

      // 使用显式等待,确保页面加载完成
      WebDriverWait wait = new WebDriverWait(driver, 15);
      wait.until(ExpectedConditions.visibilityOfElementLocated(By.tagName("body")));

      // 获取页面总高度
      JavascriptExecutor js = (JavascriptExecutor) driver;
      long pageHeight = (long) js.executeScript("return document.body.scrollHeight;");
      System.out.println("页面高度为" + pageHeight);

      // 每次截取的高度
      int captureHeight = 5000;
      int numberOfScreenshots = (int) Math.ceil((double) pageHeight / captureHeight);

      // 截取的图片的总高度
      int totalHeight = 0;
      List<File> files = new ArrayList<>();

      for (int i = 0; i < numberOfScreenshots; i++) {
        // 设置窗口大小
        Dimension dimension = new Dimension(2160, captureHeight);
        driver.manage().window().setSize(dimension);
        // 截取屏幕并保存为临时图片
        File screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
        files.add(screenshot);
        BufferedImage img = ImageIO.read(screenshot);
        // 计算合并后的图片的总高度
        totalHeight += img.getHeight();
        System.out.println("第" + (i + 1) + "张图完成");
        FileHandler.copy(screenshot, new File(tempPath + (i + 1) + ".png"));
        // 使用JS滚动页面
        js.executeScript("window.scrollBy(0, " + captureHeight + ");");
        // 等待
        Thread.sleep(500);
      }

      System.out.println(totalHeight);

      int width = 0;
      for (File file : files) {
        BufferedImage img = ImageIO.read(file);
        width = Math.max(img.getWidth(), width);
      }

      BufferedImage combinedImage = new BufferedImage(width, totalHeight,
          BufferedImage.TYPE_INT_ARGB);
      Graphics2D g = combinedImage.createGraphics();

      int nowYIndex = 0;
      for (File file : files) {
        BufferedImage img = ImageIO.read(file);
        g.drawImage(img, 0, nowYIndex, null);
        nowYIndex += img.getHeight();
      }

      // 释放图形上下文
      g.dispose();

      // 保存合并后的大图
      ImageIO.write(combinedImage, "PNG", new File(mergePath));
      System.out.println("合并成功");

    } catch (IOException | InterruptedException e) {
      e.printStackTrace();
    } finally {
      // 关闭 WebDriver
      driver.quit();
    }
  }
}

版本限定:JDK8+selenium-java(3.141.59)
我希望能通过JDK8+selenium生成给定的HTML静态页面的截图

阅读 1k
1 个回答

看你思路是想多次截图拼接为一个完整图片。你可以每次滑动少一点,比如第二次截取的图片中有四分之一和上一张图片重合,存在重合部分就可以用算法把多张图片拼接成一张长图了。

推荐问题
宣传栏