Java实现HTML页面截图功能
概述
业务开发中,经常会有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页面截图功能相关推荐
- html2canvas实现页面截图功能
一, 首先必不可少的引入:html2canvas.js 二, HTML 与 JS 代码 <div id="targetDom" class="main"& ...
- 关于selenium+java,实现部分截图功能,-针对单个元素的截图
//生成截图的方法 public class ElementPicture {public static File captureElement(File screenshot, WebElement ...
- JavaFX:截图功能
JavaFX:截图功能 b站up主Aimls的课程:JavaFX开发桌面截图功能 码农教程:基于Javafx的截图功能实现 脚本之家:Java模拟QQ桌面截图功能实现方法 鼠标事件 JavaFX:鼠标 ...
- java实现截图功能
java实现截图功能 java实现截图/录屏 public static void main(String[] args) throws InterruptedException {//截取整个屏幕 ...
- html制作qq注册页面代码截图,javascript在网页中实现粘贴qq截图功能
这篇文章主要介绍了在网页中实现读取剪贴板粘贴截图功能,即可以把剪贴板的截图Ctrl+V粘贴到网页的一个输入框中,例如QQ截图.旺旺截图或者其它截图软件.具体代码如下. 利用 clipboardData ...
- Web开发之用canvas2image.js将canvas保存为图片(实现页面截图下载功能)
关于实现页面截图常用的几个js插件库 canvas2image.js html2canvas.js convertImgToBase64.js 废话不多说,直接上demo代码 index.html: ...
- H5页面长按截图+保存页面截图到本地功能
利用的是html2canvas插件实现该该功能 长按3秒后触发截图功能,并自动下载所截图片 一次刷新只能触发一次功能 <!DOCTYPE html> <html> <he ...
- 服务端实现对页面截图 - PhantomJs
版权声明 : 本文为博主原创文章,如需转载,请注明出处(https://blog.csdn.net/F1004145107/article/details/97786555) 目录 / 1 / 前言 ...
- java网页保存pdf_JavaScript+Java实现HTML页面转为PDF文件保存的方法
JavaScript+Java实现HTML页面转为PDF文件保存的方法 发布于 2017-02-27 09:58:50 | 160 次阅读 | 评论: 0 | 来源: 网友投递 JavaScript客 ...
- java 网页保存为pdf文件怎么打开方式_js相关:JavaScript+Java实现HTML页面转为PDF文件保存的方法...
js相关:JavaScript+Java实现HTML页面转为PDF文件保存的方法 发布于 2020-8-12| 复制链接 借助iText这个Java库,我们可以将HTML文件保存为图片文件进而转换成P ...
最新文章
- python list 的乘法
- 红帽Linux故障定位技术详解与实例(1)
- ktv歌手歌曲后台功能 1216
- 5 kvm虚拟磁盘扩容
- R - 变化plot字形,嵌入字体以pdf
- spring-boot报错循环注入报错:has been injected into other beans
- java 的初始化顺序
- Android中应用锁的实现之账号盗取
- ios系统gps测试软件,GPS工具箱苹果版
- VAE背后的哲学思想及数学原理
- Amazon 的IoT之路
- Java中的IO整理
- JavaScript之正则表达式验证邮箱,手机号码,身份证,网址,QQ,邮政编码,中文
- ubuntu16.04下运行Drcom客户端
- 调试页面或样式一定要关闭拦截广告的插件
- 图片不超过200kb怎么调整?一分钟学会图片压缩到指定大小
- 人工神经网络算法的应用,神经网络算法应用案例
- 英特尔的指令集体系结构_新指令集将上线:Intel 新版指令集手册确认 Alder Lake 架构的存在...
- 碳云智能CEO王俊:大数据基础上人人都将活到120岁 | 2017 IT领袖峰会
- 图的遍历 DFS遍历(深学思维)