概述

业务开发中,经常会有HTML页面截图,或打印另存为PDF文件的需求。本文即是HTML页面截图需求的技术调研过程的成文。不想看长篇大论的同学,可以直接看Selenium部分,本人最后也是采取此方案。

html2canvas

直接上代码:

const canvas = function () {html2canvas($("#chart"), {onrendered: function (canvas) {// 将id为“class11”部分的代码转换为canvas$("#class11").html(canvas);const type = 'png';// 将图片转换为png类型的流const imgData = canvas.toDataURL('png');const saveFile = function (data, filename) {const save_link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');save_link.href = data;save_link.download = filename;const event = document.createEvent('MouseEvents');event.initMouseEvent('click', true, false, window, 0, 0, 0,0, 0, false, false, false, false, 0, null);save_link.dispatchEvent(event);};const filename = 'html2canvasSavePic' + (new Date()).getTime() + '.' + type;// 下载文件saveFile(imgData, filename);}});
};

优缺点

html2canvas可以将HTML代码块进行截取,并生成快照形式的canvas,然后利用html5的下载功能。
优点:前台技术,实现比较容易。
缺点:如果是使用H5,则只能在IE9+的版本上使用。需引用jQuery.js和html2canvas.js。

PhantomJS

PhantomJS下载地址
直接上代码:

/*** 图片保存目录*/
private static final String TEMP_PATH = "E:\\tmp\\img";private static final String BLANK = " ";/*** 可执行文件路径*/
private static final String BIN_PATH = "D:\\phantomjs-2.1.1-windows\\bin\\phantomjs.exe";/*** js路径*/
private static final String JS_PATH = "D:\\phantomjs-2.1.1-windows\\examples\\rasterize.js";public static void main(String[] args) throws IOException, InterruptedException, SAXException {String url = "http://www.samr.gov.cn/ggjgs/sjdt/gzdt/202001/t20200115_310511.html";
//  String url = "http://www.cqn.com.cn/cj/content/2018-06/12/content_5907410.htm";printUrlScreen2jpg(url);
}public static void printUrlScreen2jpg(String url) throws IOException, InterruptedException {// 图片路径String imagePath = TEMP_PATH + "/" + System.currentTimeMillis() + ".png";// Java中使用Runtime和Process类运行外部程序Process process = Runtime.getRuntime().exec(cmd(imagePath, url));Thread.sleep(1000);InputStream inputStream = process.getInputStream();BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));while (reader.readLine() != null) {close(process, reader);}
}/*** 执行cmd命令*/
private static String cmd(String imagePath, String url) {return BIN_PATH + BLANK + JS_PATH + BLANK + url + BLANK + imagePath;
}/*** 关闭命令*/
private static void close(Process process, BufferedReader bufferedReader) throws IOException {if (bufferedReader != null) {bufferedReader.close();}if (process != null) {process.destroy();}
}

优缺点

优点:效率高,截图清晰,最重要的是能够截完整的页面,而不是当前可见页面。
缺点:对于运行环境有小小的要求,需要有PhantomJS可执行环境;很容易解决,算不上缺点。
但是,对于部分网站,如上面代码片段里面的http://www.samr.gov.cn/ggjgs/sjdt/gzdt/202001/t20200115_310511.html,截图失败:

很明显,被拦截。
解决思路:添加User-Agent信息,考虑在rasterize.js脚本追加,但是看不到相关的代码片段。有待进一步调研。

DjNativeSwing

原生Java实现,几乎不会被网站屏蔽,至少我没碰到过。
Maven引入依赖,第三个是64位操作系统需要添加:

<dependency><groupId>com.hynnet</groupId><artifactId>DJNativeSwing</artifactId><version>1.0.0</version>
</dependency>
<dependency><groupId>com.hynnet</groupId><artifactId>DJNativeSwing-SWT</artifactId><version>1.0.0</version>
</dependency>
<dependency><groupId>org.eclipse.swt.org.eclipse.swt.win32.win32.x86_64.4.3.swt</groupId><artifactId>org.eclipse.swt.win32.win32.x86_64</artifactId><version>4.3</version>
</dependency>

直接上代码:

public class PicSnapshotUtils extends JPanel {/*** 行分隔符*/private final static String LS = System.getProperty("line.separator", "/n");/*** 当网页超出目标大小时 截取*/private static final int MAX_WIDTH = 2000;private static final int MAX_HEIGHT = 1400;public static void main(String[] args) throws IOException, InterruptedException, SAXException {String url = "http://www.samr.gov.cn/ggjgs/sjdt/gzdt/202001/t20200115_310511.html";printUrlScreen2jpg("1122.jpg", url, 1400, 900);}/*** @param file 预生成的图片全路径* @param url  网页地址*/public PicSnapshotUtils(final String file, final String url, final String withResult) {super(new BorderLayout());JPanel webBrowserPanel = new JPanel(new BorderLayout());final JWebBrowser webBrowser = new JWebBrowser((NSOption) null);webBrowser.setBarsVisible(false);webBrowser.navigate(url);webBrowserPanel.add(webBrowser, BorderLayout.CENTER);add(webBrowserPanel, BorderLayout.CENTER);JPanel panel = new JPanel(new FlowLayout());webBrowser.addWebBrowserListener(new WebBrowserAdapter() {// 监听加载进度@Overridepublic void loadingProgressChanged(WebBrowserEvent e) {// 当加载完毕时if (e.getWebBrowser().getLoadingProgress() == 100) {String result = (String) webBrowser.executeJavascriptWithResult(withResult);if (StrUtil.isEmpty(result)) {return;}int index = result.indexOf(":");NativeComponent nativeComponent = webBrowser.getNativeComponent();Dimension originalSize = nativeComponent.getSize();Dimension imageSize = new Dimension(Integer.parseInt(result.substring(0, index)),Integer.parseInt(result.substring(index + 1)));imageSize.width = Math.max(originalSize.width, imageSize.width + 50);imageSize.height = Math.max(originalSize.height, imageSize.height + 50);nativeComponent.setSize(imageSize);BufferedImage image = new BufferedImage(imageSize.width, imageSize.height, BufferedImage.TYPE_INT_RGB);nativeComponent.paintComponent(image);nativeComponent.setSize(originalSize);// 当网页超出目标大小时if (imageSize.width > MAX_WIDTH || imageSize.height > MAX_HEIGHT) {// 截图部分图形//                        image = image.getSubimage(0, 0, MAX_WIDTH, MAX_HEIGHT);// 此部分为使用缩略图int width = image.getWidth(), height = image.getHeight();AffineTransform tx = new AffineTransform();tx.scale((double) MAX_WIDTH / width, (double) MAX_HEIGHT / height);AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);image = op.filter(image, null);}try {// 输出图像ImageIO.write(image, "jpg", new File(file));} catch (IOException ex) {ex.printStackTrace();}// 退出操作System.exit(0);}}});add(panel, BorderLayout.SOUTH);}/*** 以javascript脚本获得网页全屏后大小*/private static String getScreenWidthHeight() {return "var width = 0;" + LS +"var height = 0;" + LS +"if(document.documentElement) {" + LS +"  width = Math.max(width, document.documentElement.scrollWidth);" + LS +"  height = Math.max(height, document.documentElement.scrollHeight);" + LS +"}" + LS +"if(self.innerWidth) {" + LS +"  width = Math.max(width, self.innerWidth);" + LS +"  height = Math.max(height, self.innerHeight);" + LS +"}" + LS +"if(document.body.scrollWidth) {" + LS +"  width = Math.max(width, document.body.scrollWidth);" + LS +"  height = Math.max(height, document.body.scrollHeight);" + LS +"}" + LS +"return width + ':' + height;";}private static void printUrlScreen2jpg(final String file, final String url, final int width, final int height) {NativeInterface.open();SwingUtilities.invokeLater(() -> {String withResult = "var width = " + width + ";var height = " + height + ";return width +':' + height;";if (width == 0 || height == 0) {withResult = getScreenWidthHeight();}JFrame frame = new JFrame("网页截图");frame.getContentPane().add(new PicSnapshotUtils(file, url, withResult), BorderLayout.CENTER);// TODO:加载指定页面,最大保存为640x480的截图frame.setSize(640, 480);// 仅初始化,但不显示frame.invalidate();frame.pack();frame.setVisible(false);});NativeInterface.runEventPump();}}

优缺点

优点:大概率不会被拦截
缺点:不能截完整的页面,只能截可见(不滑动滚轮)的当前页面。Linux系统兼容性暂未测试。

另外,程序运行时,会输出报错日志,虽然截图是成功的:

Exception "java.lang.ClassNotFoundException: com/intellij/codeInsight/editorActions/FoldingData"while constructing DataFlavor for: application/x-java-jvm-local-objectref; class=com.intellij.codeInsight.editorActions.FoldingData
Exception "java.lang.ClassNotFoundException: com/intellij/codeInsight/editorActions/FoldingData"while constructing DataFlavor for: application/x-java-jvm-local-objectref; class=com.intellij.codeInsight.editorActions.FoldingData
Exception "java.lang.ClassNotFoundException: com/intellij/codeInsight/editorActions/ReferenceData"while constructing DataFlavor for: application/x-java-jvm-local-objectref; class=com.intellij.codeInsight.editorActions.ReferenceData
Exception "java.lang.ClassNotFoundException: com/intellij/codeInsight/editorActions/ReferenceData"while constructing DataFlavor for: application/x-java-jvm-local-objectref; class=com.intellij.codeInsight.editorActions.ReferenceData

Selenium

核心,另起一篇:Java+Selenium实现网页截图

html2image

引用依赖:

<dependency><groupId>com.github.xuwei-k</groupId><artifactId>html2image</artifactId><version>0.1.0</version>
</dependency>

优缺点

html2image是可以识别html标签并将html转换成图片的java项目。
优点:后台转换,故对浏览器的版本基本没有要求。
缺点:对样式的识别不是很好,转换出来的图片比较简单,基本没有可以兼容的样式。

Cssbox

依赖:

<dependency><groupId>net.sf.cssbox</groupId><artifactId>cssbox</artifactId><version>5.0.0</version>
</dependency>

直接给代码:

public static void cssBox() throws IOException, InterruptedException, SAXException {ImageRenderer render = new ImageRenderer();render.setWindowSize(new Dimension(800, 1000), false);FileOutputStream out = new FileOutputStream("cssbox.png");Thread.sleep(10000);render.renderURL("http://www.samr.gov.cn/ggjgs/sjdt/gzdt/202001/t20200115_310511.html", out, ImageRenderer.Type.PNG);
}

优缺点

优点:无
缺点:不支持引用的外部js、css;其次,自定义设置的宽度有时候不起作用,代码内部有一个默认的宽度是2400。控制台很多报错:

10:34:46.475 [main] ERROR org.fit.cssbox.layout.ContentImage - Unable to get image from: http://www.samr.gov.cn/images/ico39.png

Robot

和Selenium比较类似。未做过多调研。

Cobra

maven搜索到一个看起来比较像能实现网页截图的依赖,并不是放在maven中央仓库的,如果可以下载jar包也行。依赖jar包下载地址为:Tidalwave,实际上已经打不开,404。另一方面,该jar包久未更新,故而未继续调研下去。

xhtmlrenderer

有依赖启动问题。

结论

Selenium牛逼。
一开始网上找到的Java版本Selenium代码也有截图不全的问题,和Python Selenium API还不是一一对应,考虑Java调用Python脚本。未免不是一种思路,但是太麻烦。

参考

Java实现网页截屏功能-PhantomJS
DjNativeSwing网页截图
使用Python+Selenium网页截图,解决截图不全问题
HTML转为图片-xhtmlrenderer
HTML转为图片-Cobra
HTML转为图片-Robot
Cssbox实现HTML转图片

Java实现HTML页面截图功能相关推荐

  1. html2canvas实现页面截图功能

    一, 首先必不可少的引入:html2canvas.js 二, HTML 与 JS 代码 <div id="targetDom" class="main"& ...

  2. 关于selenium+java,实现部分截图功能,-针对单个元素的截图

    //生成截图的方法 public class ElementPicture {public static File captureElement(File screenshot, WebElement ...

  3. JavaFX:截图功能

    JavaFX:截图功能 b站up主Aimls的课程:JavaFX开发桌面截图功能 码农教程:基于Javafx的截图功能实现 脚本之家:Java模拟QQ桌面截图功能实现方法 鼠标事件 JavaFX:鼠标 ...

  4. java实现截图功能

    java实现截图功能 java实现截图/录屏 public static void main(String[] args) throws InterruptedException {//截取整个屏幕 ...

  5. html制作qq注册页面代码截图,javascript在网页中实现粘贴qq截图功能

    这篇文章主要介绍了在网页中实现读取剪贴板粘贴截图功能,即可以把剪贴板的截图Ctrl+V粘贴到网页的一个输入框中,例如QQ截图.旺旺截图或者其它截图软件.具体代码如下. 利用 clipboardData ...

  6. Web开发之用canvas2image.js将canvas保存为图片(实现页面截图下载功能)

    关于实现页面截图常用的几个js插件库 canvas2image.js html2canvas.js convertImgToBase64.js 废话不多说,直接上demo代码 index.html: ...

  7. H5页面长按截图+保存页面截图到本地功能

    利用的是html2canvas插件实现该该功能 长按3秒后触发截图功能,并自动下载所截图片 一次刷新只能触发一次功能 <!DOCTYPE html> <html> <he ...

  8. 服务端实现对页面截图 - PhantomJs

    版权声明 : 本文为博主原创文章,如需转载,请注明出处(https://blog.csdn.net/F1004145107/article/details/97786555) 目录 / 1 / 前言 ...

  9. java网页保存pdf_JavaScript+Java实现HTML页面转为PDF文件保存的方法

    JavaScript+Java实现HTML页面转为PDF文件保存的方法 发布于 2017-02-27 09:58:50 | 160 次阅读 | 评论: 0 | 来源: 网友投递 JavaScript客 ...

  10. java 网页保存为pdf文件怎么打开方式_js相关:JavaScript+Java实现HTML页面转为PDF文件保存的方法...

    js相关:JavaScript+Java实现HTML页面转为PDF文件保存的方法 发布于 2020-8-12| 复制链接 借助iText这个Java库,我们可以将HTML文件保存为图片文件进而转换成P ...

最新文章

  1. python list 的乘法
  2. 红帽Linux故障定位技术详解与实例(1)
  3. ktv歌手歌曲后台功能 1216
  4. 5 kvm虚拟磁盘扩容
  5. R - 变化plot字形,嵌入字体以pdf
  6. spring-boot报错循环注入报错:has been injected into other beans
  7. java 的初始化顺序
  8. Android中应用锁的实现之账号盗取
  9. ios系统gps测试软件,GPS工具箱苹果版
  10. VAE背后的哲学思想及数学原理
  11. Amazon 的IoT之路
  12. Java中的IO整理
  13. JavaScript之正则表达式验证邮箱,手机号码,身份证,网址,QQ,邮政编码,中文
  14. ubuntu16.04下运行Drcom客户端
  15. 调试页面或样式一定要关闭拦截广告的插件
  16. 图片不超过200kb怎么调整?一分钟学会图片压缩到指定大小
  17. 人工神经网络算法的应用,神经网络算法应用案例
  18. 英特尔的指令集体系结构_新指令集将上线:Intel 新版指令集手册确认 Alder Lake 架构的存在...
  19. 碳云智能CEO王俊:大数据基础上人人都将活到120岁 | 2017 IT领袖峰会
  20. 图的遍历 DFS遍历(深学思维)

热门文章

  1. java TIF 转 JPG
  2. 云服务器网站logo,云服务器 logo
  3. Eureka高可用注册中心通过defaultZone深入理解zone和serviceUrl
  4. u盘为什么显示在工具栏而不显示在计算机里,为什么U盘后插入后不显示?
  5. Microsoft Visual Studio 建表格
  6. 寻找故障检测相关论文的期刊
  7. 自定义dns服务器是什么,dns服务器有什么用(电脑设置DNS的方法)
  8. 坤坤音效键盘(Python实现)
  9. vue移动端复杂表格表头,固定表头与固定第一列
  10. 2.5.2 文法的二义性