前言
抓取的时候有些场景,需要把整个页面截图下载下来。网上不少资源,不过文章水平参差不齐,实现出来的效果有人不尽人意。于是摸索了一番,总结了一个截图生成效果比较好的几个框架。
同时封装成更多方法使用工具类。
实例网站
Html2Image
这个框架放最前面的原因并不是它效果最好,反而效果是文章中最差的,放前面的原因是google百度一搜html生成图片,几乎都是这个框架的资料,但是截图效果很差劲,很多js css都无法正常渲染。
不过支持自定义html源码生成图片,html不复杂可以使用该方案。
maven
<dependency> <groupId>com.github.xuwei-kgroupId> <artifactId>html2imageartifactId> <version>0.1.0version> dependency>
效果
工具类
public class Html2ImageUtil { /** * @param filePath * @param charset * @return * @Description 读取HTML文件,获取字符内容 */ public static String getHtmlContent(String filePath, String charset) { String line = null; StringBuilder sb = new StringBuilder(); BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader(new FileInputStream(new File(filePath)), charset)); while ((line = reader.readLine()) != null) { sb.append(line + "\n"); } } catch (IOException e) { e.printStackTrace(); throw new RuntimeException("读取HTML文件,获取字符内容异常"); } finally { try { reader.close(); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException("关闭流异常"); } } return sb.toString(); } /** * @param htmText HTML文本字符串 * @return 希望生成的Image Location * @Description HTML转Image */ public static String html2Img(String htmText, String saveImageLocation) { HtmlImageGenerator imageGenerator = new HtmlImageGenerator(); try { imageGenerator.loadHtml(htmText); imageGenerator.getBufferedImage(); Thread.sleep(1000); imageGenerator.saveAsImage(saveImageLocation); imageGenerator.saveAsHtmlWithMap("hello-world.html", saveImageLocation); //不需要转换位图的,下面三行可以不要 // BufferedImage sourceImg = ImageIO.read(new File(saveImageLocation)); // sourceImg = transform_Gray24BitMap(sourceImg); // ImageIO.write(sourceImg, "BMP", new File(saveImageLocation)); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException("将HTML文件转换成图片异常"); } return saveImageLocation; } /** * @param image * @return * @Description 转换成24位图的BMP */ public static BufferedImage transform_Gray24BitMap(BufferedImage image) { int h = image.getHeight(); int w = image.getWidth(); // 定义数组,用来存储图片的像素 int[] pixels = new int[w * h]; int gray; PixelGrabber pg = new PixelGrabber(image, 0, 0, w, h, pixels, 0, w); try { pg.grabPixels(); // 读取像素值 } catch (InterruptedException e) { throw new RuntimeException("转换成24位图的BMP时,处理像素值异常"); } // 扫描列 for (int j = 0; j < h; j++) { // 扫描行 for (int i = 0; i < w; i++) { // 由红,绿,蓝值得到灰度值 gray = (int) (((pixels[w * j + i] >> 16) & 0xff) * 0.8); gray += (int) (((pixels[w * j + i] >> 8) & 0xff) * 0.1); gray += (int) (((pixels[w * j + i]) & 0xff) * 0.1); pixels[w * j + i] = (255 << 24) | (gray << 16) | (gray << 8) | gray; } } MemoryImageSource s = new MemoryImageSource(w, h, pixels, 0, w); Image img = Toolkit.getDefaultToolkit().createImage(s); //如果要转换成别的位图,改这个常量即可 BufferedImage buf = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); buf.createGraphics().drawImage(img, 0, 0, null); return buf; } }
DJNativeSwing
该方案能完美截图,底层调用的是Java的实现的浏览器。不好的地方是资源消耗高,同时关闭浏览器的时候,会关闭整个应用,包括tomcat。
maven
<dependency> <groupId>com.hynnetgroupId> <artifactId>DJNativeSwingartifactId> <version>1.0.0version> dependency> <dependency> <groupId>com.hynnetgroupId> <artifactId>DJNativeSwing-SWTartifactId> <version>1.0.0version> dependency> <dependency> <groupId>org.eclipse.swt.org.eclipse.swt.win32.win32.x86_64.4.3.swtgroupId> <artifactId>org.eclipse.swt.win32.win32.x86_64artifactId> <version>4.3version> dependency>
效果
工具类
public class PrintScreen4DJNativeSwingUtils extends JPanel { private static final long serialVersionUID = 1L; // 行分隔符 final static public String LS = System.getProperty("line.separator", "/n"); // 文件分割符 final static public String FS = System.getProperty("file.separator", "//"); // 当网页超出目标大小时 截取 final static public int maxWidth = 2000; final static public int maxHeight = 2000; /** * @param file * 预生成的图片全路径 * @param url * 网页地址 * @param width * 打开网页宽度 ,0 = 全屏 * @param height * 打开网页高度 ,0 = 全屏 * @return boolean * @author xufei * @version 4.0, 2018年12月11日 */ public PrintScreen4DJNativeSwingUtils(final String file, final String url, final String WithResult) { super(new BorderLayout()); JPanel webBrowserPanel = new JPanel(new BorderLayout()); final JWebBrowser webBrowser = new JWebBrowser(null); webBrowser.setBarsVisible(false); webBrowser.navigate(url); webBrowserPanel.add(webBrowser, BorderLayout.CENTER); add(webBrowserPanel, BorderLayout.CENTER); JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER, 4, 4)); webBrowser.addWebBrowserListener(new WebBrowserAdapter() { // 监听加载进度 @Override public void loadingProgressChanged(WebBrowserEvent e) { // 当加载完毕时 if (e.getWebBrowser().getLoadingProgress() == 100) { String result = (String) webBrowser .executeJavascriptWithResult(WithResult); int index = result == null ? -1 : 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); imageSize.height = Math.max(originalSize.height, imageSize.height); nativeComponent.setSize(imageSize); BufferedImage image = new BufferedImage(imageSize.width, imageSize.height, BufferedImage.TYPE_INT_RGB); nativeComponent.paintComponent(image); nativeComponent.setSize(originalSize); // 当网页超出目标大小时 if (imageSize.width > maxWidth || imageSize.height > maxHeight) { // 截图部分图形 image = image.getSubimage(0, 0, maxWidth, maxHeight); // 此部分为使用缩略图 /* * int width = image.getWidth(), height = image * .getHeight(); AffineTransform tx = new * AffineTransform(); tx.scale((double) maxWidth / * width, (double) maxHeight / 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(); } } } }); add(panel, BorderLayout.SOUTH); } /** * 以javascript脚本获得网页全屏后大小 * @return */ public static String getScreenWidthHeight() { StringBuffer jsDimension = new StringBuffer(); jsDimension.append("var width = 0;").append(LS); jsDimension.append("var height = 0;").append(LS); jsDimension.append("if(document.documentElement) {").append(LS); jsDimension .append(" width = Math.max(width, document.documentElement.scrollWidth);") .append(LS); jsDimension .append(" height = Math.max(height, document.documentElement.scrollHeight);") .append(LS); jsDimension.append("}").append(LS); jsDimension.append("if(self.innerWidth) {").append(LS); jsDimension.append(" width = Math.max(width, self.innerWidth);") .append(LS); jsDimension.append(" height = Math.max(height, self.innerHeight);") .append(LS); jsDimension.append("}").append(LS); jsDimension.append("if(document.body.scrollWidth) {").append(LS); jsDimension.append( " width = Math.max(width, document.body.scrollWidth);") .append(LS); jsDimension.append( " height = Math.max(height, document.body.scrollHeight);") .append(LS); jsDimension.append("}").append(LS); jsDimension.append("return width + ':' + height;"); return jsDimension.toString(); } /** * * @param file 图片保存路径 * @param url 要截图的URL地址 * @param width 裁剪图片的宽 0代表按照图片的原始大小保存 * @param height 裁剪图片的高 0代表按照图片的原始大小保存 * @return */ public static boolean printUrlScreen2jpg(final String file, final String url, final int width, final int height) { NativeInterface.open(); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { String withResult = "var width = " + width + ";var height = " + height + ";return width +':' + height;"; if (width == 0 || height == 0) withResult = getScreenWidthHeight(); // SWT组件转Swing组件,不初始化父窗体将无法启动webBrowser JFrame frame = new JFrame("网页截图"); // 加载指定页面,最大保存为640x480的截图 frame.getContentPane().add( new PrintScreen4DJNativeSwingUtils(file, url, withResult), BorderLayout.CENTER); frame.setSize(640, 480); // 仅初始化,但不显示 frame.invalidate(); frame.pack(); frame.setVisible(false); } }); NativeInterface.runEventPump(); return true; } }
cssbox
最完美的一个,完美截图,效率比第二中快!依赖少,简直完美。
maven
<dependency> <groupId>net.sf.cssboxgroupId> <artifactId>cssboxartifactId> <version>4.12version> dependency>
效果
工具类
public class CssboxUtil { public static final int WIDTH = 1900; public static final int HEIGHT = 1000; /** * 图片生成到指定路径 * 支持 file ftp http https * * @param url html地址 * @param path 生成文件地址 * @throws IOException * @throws SAXException */ public static void toPath(String url, String path) throws IOException, SAXException { toPath(url, path, WIDTH, HEIGHT); } /** * 图片生成到指定路径 * 支持 file ftp http https * * @param url html地址 * @param path 生成文件地址 * @throws IOException * @throws SAXException */ public static void toPath(String url, String path, int width, int height) throws IOException, SAXException { ImageRenderer render = new ImageRenderer(); FileOutputStream out = new FileOutputStream(new File(path)); render.setWindowSize(new Dimension(width, height), false); render.renderURL(url, out, ImageRenderer.Type.PNG); out.close(); } /** * 图片生成到byte数组 * 支持 file ftp http https * * @param url html地址 * @throws IOException * @throws SAXException */ public static byte[] toByte(String url) throws IOException, SAXException { return toByte(url, WIDTH, HEIGHT); } /** * 图片生成到byte数组 * 支持 file ftp http https * * @param url html地址 * @throws IOException * @throws SAXException */ public static byte[] toByte(String url, int width, int height) throws IOException, SAXException { ImageRenderer render = new ImageRenderer(); ByteArrayOutputStream stream = new ByteArrayOutputStream(); render.setWindowSize(new Dimension(1900, 1000), false); render.renderURL(url, stream, ImageRenderer.Type.PNG); byte[] bytes = stream.toByteArray(); stream.close(); return bytes; } }
本文由 SAn 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为:
2020/05/14 19:32
截图效果还可以