有几种方法可以评估 HTML + CSS + JS 页面上的 JS 代码。为此,我们需要一个类似浏览器(或浏览器本身),因为使用 DOM 操作评估 JS 正是浏览器在呈现页面之前必须做的。
选项 1
使用HtmlUnit - “Java 程序的无 GUI 浏览器”。
首先,我们需要添加依赖项(例如通过 Maven):
<dependency>
<groupId>net.sourceforge.htmlunit</groupId>
<artifactId>htmlunit</artifactId>
<version>2.32</version>
</dependency>
然后,打开页面,等待 JS 完成它的工作并将页面源提供给 iText pdfHTML:
WebClient webClient = new WebClient();
// You might need this configuration if HtmlUnit fails without it
webClient.getOptions().setThrowExceptionOnScriptError(false);
webClient.waitForBackgroundJavaScript(10 * 1000);
HtmlPage page = webClient.getPage(url);
String xml = page.asXml();
ConverterProperties properties = new ConverterProperties().setBaseUri(url);
HtmlConverter.convertToPdf(source, new PdfWriter("result.pdf"), properties);
HtmlUnit 不完全支持 JS,因此在评估 JS 代码时可能会抛出错误。因此,您可能想要抑制它们(我已将此配置和关于它的注释添加到代码示例中)。当然,您的结果可能看起来不正确。但这是纯 Java 解决方案。
选项 2
向我们每天使用的现实世界浏览器寻求帮助
我们每天使用的浏览器(Chrome、Firefox、Safari 等)对 JS 评估有最好的支持。您可以使用浏览器引擎,例如Selenium 网络自动化工具。我们要做的是在浏览器中打开一个页面,等待页面加载,然后使用源代码进行 HTML -> PDF 转换。我的示例适用于 Chrome,但您可以以类似的方式对其他浏览器执行此操作。首先,您需要 download 一个 Chrome 驱动程序并将其解压到您系统的某个位置。
然后添加以下 Maven 依赖项:
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-chrome-driver</artifactId>
<version>3.14.0</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.14.0</version>
</dependency>
现在我们要写一些代码,类似于第一个选项:
System.setProperty("webdriver.chrome.driver", "C:\\path\\to\\chromedriver.exe");
ChromeDriver driver = new ChromeDriver();
driver.get(url);
new WebDriverWait(driver, 20).until(
webDriver -> ((JavascriptExecutor) webDriver).executeScript("return document.readyState").equals("complete"));
String source = driver.getPageSource();
driver.close();
ConverterProperties properties = new ConverterProperties().setBaseUri(url);
HtmlConverter.convertToPdf(source, new PdfWriter("result.pdf"), properties);
这个选项可能会慢一些,并且有更多的先决条件(浏览器、驱动程序),但它保证了防弹 JS 支持。