Java 通過URL獲取頁面快照十種方式解讀

需求:通過URL超鏈接獲取超鏈接的頁面快照

查詢翻閱各種資料 ,找到了十種方式, 但是這十種方式都有各自的獨特性,以下是我對其測試結果

方法一:java本身的API

不需要引用任何的jar包,不支持寫在style裏面的css和外置的css文件,只能寫在標籤上,還有也不支持js只能是html文件的url地址。

首先對一本地靜態頁面測試

原圖結果圖(結果圖有裁剪)對比:

對應案例:

package cn.cosmos.page;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.File;
import java.net.URL;

/**
 * Created with CosmosRay
 *
 * @author CosmosRay
 * @date 2019/5/21
 * Function:
 */
public class JavaApi {
    public static void generateOutput() throws Exception {
        String url = new File("E:/test/index.html").toURI().toString();
        JEditorPane ed = new JEditorPane(new URL(url));
        ed.setSize(1000,1300);
        Thread.sleep(5000);
        //create a new image
        BufferedImage image = new BufferedImage(ed.getWidth(), ed.getHeight(),
                BufferedImage.TYPE_INT_ARGB);
        SwingUtilities.paintComponent(image.createGraphics(),
                ed,
                new JPanel(),
                0, 0, image.getWidth(), image.getHeight());
        //save the image to file
        ImageIO.write((RenderedImage)image, "png", new File("E:/test/javacore.png"));
    }
    public static void main(String[] args) {
        try {
            generateOutput();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

方法二:Cobra

Cobra 是一個純 Java 的HTML 解析和生成器,支持 HTML 4 、JavaScript、CSS 2。

效果圖:

源碼:

方法三:DjNativeSwing

只有這個支持js,css,但是網頁超過一定高度,就會截取一半;如果是接口調用的話,因爲是線程,所以這個只能運行一次就自動關閉了;使用main方法運行就沒有問題--多線程問題

效果圖:

 所需Maven文件

<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>

源碼: 

package cn.cosmos.page;

import chrriis.dj.nativeswing.swtimpl.NativeComponent;
import chrriis.dj.nativeswing.swtimpl.NativeInterface;
import chrriis.dj.nativeswing.swtimpl.components.JWebBrowser;
import chrriis.dj.nativeswing.swtimpl.components.WebBrowserAdapter;
import chrriis.dj.nativeswing.swtimpl.components.WebBrowserEvent;
import sun.misc.BASE64Encoder;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;

/**
 * Created with CosmosRay
 *
 * @author CosmosRay
 * @date 2019/5/22
 * Function:
 */
public class JFrame extends JPanel {
    // 行分隔符
    final static public String LS = System.getProperty("line.separator", "\n");
    // 文件分割符
    final static public String FS = System.getProperty("file.separator", "\\");
    // 以javascript腳本獲得網頁全屏後大小
    private static final long serialVersionUID = 1L;
    private static final StringBuffer jsDimension;

    static {
        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;");
    }

    public JFrame(final String url, final int maxWidth, final int maxHeight) {
        super(new BorderLayout());
        JPanel webBrowserPanel = new JPanel(new BorderLayout());
        final String fileName = System.currentTimeMillis() + ".jpg";
        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) {
                                                     /*睡眠3秒鐘,等待頁面請求完畢再截取圖片信息
                                                      * 如果不延時,則圖片等可能沒有時間下載顯示
                                                      * 具體的秒數需要根據網速等調整
                                                      * */
                                                     try {
                                                         Thread.sleep(3000);
                                                     } catch (InterruptedException e1) {
                                                         e1.printStackTrace();
                                                     }
                                                     String result = (String) webBrowser.executeJavascriptWithResult(jsDimension.toString());
                                                     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 + 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);

                                                     try {
                                                         /*將圖片轉爲base64二進制字節 */
                                                         //io流
                                                         ByteArrayOutputStream baos = new ByteArrayOutputStream();
                                                         //寫入流中
                                                         ImageIO.write(image, "jpg", baos);
                                                         //轉換成字節
                                                         byte[] bytes = baos.toByteArray();
                                                         BASE64Encoder encoder = new BASE64Encoder();
                                                         //轉換成base64串
                                                         String png_base64 = encoder.encodeBuffer(bytes).trim();
                                                         //刪除 \r\n
                                                         png_base64 = png_base64.replaceAll("\n", "").replaceAll("\r", "");
                                                         //data:image/png;base64,
                                                         System.out.println(png_base64);
                                                     } catch (IOException e1) {
                                                         e1.printStackTrace();
                                                     }

                                                     try {
                                                         // 輸出圖像
                                                         System.out.println(fileName);
                                                         ImageIO.write(image, "jpg", new File(fileName));
                                                     } catch (IOException ex) {
                                                         ex.printStackTrace();
                                                     }
                                                     // 退出操作
                                                     System.exit(0);
                                                 }
                                             }
                                         }
        );
        add(panel, BorderLayout.SOUTH);
    }

    public static void main(String[] args) {
        NativeInterface.open();
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                // SWT組件轉Swing組件,不初始化父窗體將無法啓動webBrowser
                javax.swing.JFrame frame = new javax.swing.JFrame("以DJ組件保存指定網頁截圖");
                // 加載google,最大保存爲640x480的截圖
                //實際項目中傳入URL參數,根據不同參數截取不同網頁快照,保存地址也可以在構造器中多設置一個參數,保存到指定目錄
                frame.getContentPane().add(new JFrame("http://www.baidu.com", 640, 480), BorderLayout.CENTER);
                frame.setSize(1400, 900);

                // 僅初始化,但不顯示
                frame.invalidate();
                frame.pack();
                frame.setVisible(false);
            }
        });
        NativeInterface.runEventPump();
    }
}

方法四:Robot

運行成功後 ,只截取顯示器當前顯示內容 爲jpg格式類型的圖片,不會截取我們需要的網頁頁面

效果圖:

源碼:

package cn.cosmos.page;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;

/**
 * Created with CosmosRay
 *
 * @author CosmosRay
 * @date 2019/5/22
 * Function:
 */
public class Robot {
    public static void main(String[] args) throws AWTException, IOException, URISyntaxException {
        // 此方法僅適用於JdK1.6及以上版本
        Desktop.getDesktop().browse(
                new URL("http://www.baidu.com").toURI());
        java.awt.Robot robot = new java.awt.Robot();
        robot.delay(10000);
        Dimension d = new Dimension(Toolkit.getDefaultToolkit().getScreenSize());
        int width = (int) d.getWidth();
        int height = (int) d.getHeight();
        // 最大化瀏覽器
        robot.keyRelease(KeyEvent.VK_F11);
        robot.delay(2000);
        Image image = robot.createScreenCapture(new Rectangle(0, 0, width,
                height));
        BufferedImage bi = new BufferedImage(width, height,
                BufferedImage.TYPE_INT_RGB);
        Graphics g = bi.createGraphics();
        g.drawImage(image, 0, 0, width, height, null);
        // 保存圖片
        ImageIO.write(bi, "jpg", new File("d:/google"+System.currentTimeMillis()+".jpg"));
    }
}

 

方法五:xhtmlrenderer

不支持css,js

 

方法六:Html2Image

可以支持css,但是js不支持,重寫HtmlImageGenerator方法

方法七:Cssbox

這個方法,不支持引用的外部js、css;其次,自定義設置的寬度有時候不起作用,代碼內部有一個默認的寬度是2400,暫時沒找到解決方法。

方法八:HtmlImageGenerator

對樣式識別不好,顏色有差異

方法九:JFrame

截取整個屏幕窗體

方法十:phantomJs

需要在項目的服務器端引用exe文件進行截圖,併發性能有待考證。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章