playwright的简介
Playwright是一款跨浏览器自动化测试工具,由Microsoft推出。它支持Chrome、Firefox和Safari等主流浏览器。可以轻松地编写自动化测试用例,可以模拟用户在浏览器中的操作,如点击、输入、滚动、截图等功能。
在公司刚好开发一个截图功能,playwright就有了用武之地。
代码如下,实现截长图,并且转换为pdf格式文件。
本地使用没什么问题,但在线上环境使用,要注意这个组件需要一些浏览器依赖,如果是docker等部署,安装可能会遇到问题。
在转换为pdf格式文件用到了itextpdf组件,saveAsPdf方法主要是将长图转为pdf,如果不需要可以去掉相关代码。
package com.xxx.xxx.util;
import cn.hutool.core.io.FileUtil;
import com.itextpdf.text.Document;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfWriter;
import com.microsoft.playwright.Browser;
import com.microsoft.playwright.ElementHandle;
import com.microsoft.playwright.Page;
import com.microsoft.playwright.Playwright;
import com.microsoft.playwright.options.BoundingBox;
import java.io.File;
import java.io.FileOutputStream;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
public class ScreenshotUtil {
/**
* 通过url截长图
* @param webUrl
*/
public static String getScreenshotByUrl(String webUrl,String id,String pdfPath) throws Exception {
String pdfUrl = "";
String imagePath = "outputPng" + id + ".png";
try (Playwright playwright = Playwright.create()) {
Browser browser = playwright.chromium().launch();
Page page = browser.newPage();
page.navigate(webUrl);
page.waitForLoadState();
// 获取要截图的元素 前端的class元素自己调整
ElementHandle element = page.querySelector(".hello");
// 获取元素的位置和大小
BoundingBox boundingBox = element.boundingBox();
int viewportWidth = page.viewportSize().width;
int viewportHeight = page.viewportSize().height;
// 计算需要滚动的距离
int scrollHeight = (int) Math.ceil((double) boundingBox.height / viewportHeight) * viewportHeight;
int scrollWidth = (int) Math.ceil((double) boundingBox.width / viewportWidth) * viewportWidth;
// 设置视口大小,确保能够完整显示元素
page.setViewportSize(scrollWidth, scrollHeight);
// 滚动页面使元素处于可见区域
int currentScrollHeight = 0;
while (currentScrollHeight < scrollHeight) {
String script = String.format("window.scrollBy(0, %s)", viewportHeight);
page.evaluate(script, scrollHeight - currentScrollHeight);
currentScrollHeight += viewportHeight;
page.waitForTimeout(200); // 等待滚动完成,可以根据具体情况调整等待时间
}
// 截图并保存为文件
byte[] screenshotData = page.screenshot(new Page.ScreenshotOptions().setPath(Paths.get(imagePath)));
browser.close();
//截图转为生成pdf文件
pdfUrl = saveAsPdf(screenshotData,pdfPath);
String fullImagePath = System.getProperty("user.dir")+"/"+imagePath;
if(FileUtil.isFile(fullImagePath)){
FileUtil.del(fullImagePath);
}
}
return pdfUrl;
}
/**
* 长截图字节数组数据转为pdf文件
* @param screenshotData
* @param outputFilePath
* @throws Exception
*/
public static String saveAsPdf(byte[] screenshotData, String outputFilePath) throws Exception {
String pdfUrl = "";
// 创建Document对象
Document document = new Document();
// 创建PdfWriter对象
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(outputFilePath));
// 打开文档
document.open();
// 分页处理长图
int pageWidth = 595; // 页面宽度,单位为磅,A4纸宽度为595磅
int pageHeight = 842; // 页面高度,单位为磅,A4纸高度为842磅
// 设置页面边距
document.setMargins(0, 0, 0, 0);
// 获取截图的宽高
Image fullImage = Image.getInstance(screenshotData);
// 调整图片大小适应页面
fullImage.scaleToFit(PageSize.A4.getWidth(), PageSize.A4.getHeight());
int imageWidth = (int) fullImage.getWidth();
int imageHeight = (int) fullImage.getHeight();
// 计算需要分页的数量
int pageCount = (int) Math.ceil((double) imageHeight / pageHeight);
// 分页转换为多页PDF
for (int pageNumber = 0; pageNumber < pageCount; pageNumber++) {
// 创建新页
document.newPage();
// 计算当前页的高度
int currentPageHeight = Math.min(imageHeight - pageNumber * pageHeight, pageHeight);
// 计算裁剪区域
Rectangle cropRegion = new Rectangle(0, pageNumber * pageHeight, imageWidth, currentPageHeight);
// 裁剪图片
Image croppedImage = Image.getInstance(fullImage);
croppedImage.setAbsolutePosition(-cropRegion.getLeft(), -(cropRegion.getBottom()));
croppedImage.scaleToFit(cropRegion.getWidth(), cropRegion.getHeight());
// 添加Image对象到Document
document.add(croppedImage);
}
// 关闭文档
document.close();
return pdfUrl;
}
}