如何以Java實現網頁截圖技術

來源:互聯網
上載者:User

今天看到某網友關於“如何以Java實現網頁技術”的諮詢帖,由於出現該諮詢的地點非常不適合較長回複,故以博文形式回答。

 

事實上,如果您想以Java實現網頁,也就是“輸入一段網址,幾秒鐘過後就能截取一張網頁縮圖”的效果。那麼,您至少有3種方式可以選擇。

 

1、最直接的方式——使用Robot

 

方法詳解:該方法利用Robat提供的強大案頭操作能力,硬性呼叫瀏覽器開啟指定網頁,並將網頁資訊儲存到本地。

 

優勢:簡單易用,不需要任何第三方外掛程式。

 

缺點:不能同時處理大量資料,技術含量過低,屬於應急型技巧。

 

實現方法:使用如下代碼即可。

 

public static void main(String[] args) throws MalformedURLException,<br />IOException, URISyntaxException, AWTException {<br />//此方法僅適用於JdK1.6及以上版本<br />Desktop.getDesktop().browse(<br />new URL("http://google.com/intl/en/").toURI());<br />Robot robot = new Robot();<br />robot.delay(10000);<br />Dimension d = new Dimension(Toolkit.getDefaultToolkit().getScreenSize());<br />int width = (int) d.getWidth();<br />int height = (int) d.getHeight();<br />//最大化瀏覽器<br />robot.keyRelease(KeyEvent.VK_F11);<br />robot.delay(2000);<br />Image image = robot.createScreenCapture(new Rectangle(0, 0, width,<br />height));<br />BufferedImage bi = new BufferedImage(width, height,<br />BufferedImage.TYPE_INT_RGB);<br />Graphics g = bi.createGraphics();<br />g.drawImage(image, 0, 0, width, height, null);<br />//儲存圖片<br />ImageIO.write(bi, "jpg", new File("google.jpg"));<br />}<br />

 

2、最常規的方式——利用JNI,調用第三方C/C++組件

 

方法詳解:目前來講,Java領域對於網頁組件的開發明顯不足(商機?),當您需要完成此種操作時,算得上碰到了Java的軟肋。但是,眾所周知Java也擁有強大的JNI能力,可以輕易將C/C++開發的同類組件引為己用。

優勢:實現簡單,只需要封裝對應的DLL檔案,就可以讓Java實現同類功能。

 

劣勢:同其他JNI實現一樣,在跨平台時存在隱患,而且您的程式將不再屬於純Java應用。

 

實現方法:可參見此用例,具體封裝何種C/C++組件請自行選擇。

 

PS:樣本來源於ACA HTML to Image Converter項目(http://www.acasystems.com/en/web-thumb-activex/faq-convert-html-to-image-in-java.htm
),這是一個收費的HTML轉Image第三方組件,但封裝方式在Java中大同小異。

 

引用JNI封裝:

 

import sun.awt.*;<br />import java.awt.*;<br />import javax.swing.*;<br />import java.awt.event.*;<br />import java.awt.*;<br />import java.awt.peer.*;<br />public class Snap<br />{<br /> static<br /> {<br /> System.loadLibrary("Snap");<br /> }<br /> public static void main( String[] argv )<br /> {<br /> Snap t_xSnap = new Snap();<br /> t_xSnap.Start("http://www.google.com", "snapshot-google.png");<br /> }<br /> public native void Start(String pi_strURL, String pi_strImageName);<br />}<br />

 

CPP部分的實現:

 

#include <windows.h><br />#include <atlbase.h><br />#include "snap.h"<br />#pragma comment(lib,"atl.lib")<br />#import "./../../acawebthumb.dll" no_namespace<br />JNIEXPORT void JNICALL Java_Snap_Start(JNIEnv *pEnv, jobject, jstring pi_strUrl, jstring pi_strFileName)<br />{<br /> CoInitialize(0);<br /> _bstr_t t_strUrl = pEnv->GetStringUTFChars(pi_strUrl, 0);<br /> _bstr_t t_strFileName = pEnv->GetStringUTFChars(pi_strFileName, 0);<br /> IThumbMakerPtr HTML_Converter = NULL;<br /> HRESULT hr = HTML_Converter.CreateInstance(L"ACAWebThumb.ThumbMaker");<br /> if (SUCCEEDED(hr))<br /> {<br /> HTML_Converter->SetURL(t_strUrl);<br /> if ( 0 == HTML_Converter->StartSnap() )<br /> HTML_Converter->SaveImage(t_strFileName);<br /> }<br /> if (HTML_Converter)<br /> HTML_Converter.Release();<br /> CoUninitialize();<br />}<br />

 

以該元件圖表像化yahoo介面的:

 


3、最紮實的方法——自行解析HTML標記,並將其映像化

 

方法詳解:眾所周知,HTML之所以在瀏覽器中以具體的網頁格式出現,並非伺服器端傳了一整個應用到用戶端,而是源自於瀏覽器對於用戶端自行解析的結果。因此,只要我們將對應的解析一一實現,那麼將網頁圖形化,就將不是什麼難事。


優勢:純Java實現,一勞永逸,一旦開發完成則永遠通用,而且有一定的商用價值。

 

劣勢:開發費時,且需要針對不同文法做精確分析,才能保證輸出的基本正確。尤其在涉及到JavaScript解析時,難度將尤其增大。

 

實現方法:目前尚無具體案例可供參考。但是,由於Java有jdic之類的瀏覽器項目存在(https://jdic.dev.java.net/
),而Java圖形介面又屬繪製產生。從理論上說,我們可以將所有具備Graphics的元件圖表形化儲存。

 

而如果自行解析,那麼您需要建立HTML解析器(或使用第三方的,萬幸Java在這方面的組件很多),瞭解Java2D機制,瞭解何時該使用drawString繪製文字,何時又該使用drawImage插入圖片等等。

 


補充:

 

這是一個利用內建瀏覽器的樣本,使用了DJNativeSwing組件。

 

樣本工程(Eclipse工程,含lib):http://greenvm.googlecode.com/files/Screenshot.7z

 

 

import java.awt.BorderLayout;<br />import java.awt.Dimension;<br />import java.awt.FlowLayout;<br />import java.awt.image.BufferedImage;<br />import java.io.File;<br />import java.io.IOException;<br />import javax.imageio.ImageIO;<br />import javax.swing.JFrame;<br />import javax.swing.JPanel;<br />import javax.swing.SwingUtilities;<br />import chrriis.dj.nativeswing.swtimpl.NativeComponent;<br />import chrriis.dj.nativeswing.swtimpl.NativeInterface;<br />import chrriis.dj.nativeswing.swtimpl.components.JWebBrowser;<br />import chrriis.dj.nativeswing.swtimpl.components.WebBrowserAdapter;<br />import chrriis.dj.nativeswing.swtimpl.components.WebBrowserEvent;<br />public class Main extends JPanel {<br />/**<br /> *<br /> */<br />private static final long serialVersionUID = 1L;<br />// 行分隔字元<br />final static public String LS = System.getProperty("line.separator", "/n");<br />// 檔案分割符<br />final static public String FS = System.getProperty("file.separator", "//");<br />//以javascript指令碼獲得網頁全屏後大小<br />final static StringBuffer jsDimension;</p><p>static {<br />jsDimension = new StringBuffer();<br />jsDimension.append("var width = 0;").append(LS);<br />jsDimension.append("var height = 0;").append(LS);<br />jsDimension.append("if(document.documentElement) {").append(LS);<br />jsDimension.append(<br />" width = Math.max(width, document.documentElement.scrollWidth);")<br />.append(LS);<br />jsDimension.append(<br />" height = Math.max(height, document.documentElement.scrollHeight);")<br />.append(LS);<br />jsDimension.append("}").append(LS);<br />jsDimension.append("if(self.innerWidth) {").append(LS);<br />jsDimension.append(" width = Math.max(width, self.innerWidth);")<br />.append(LS);<br />jsDimension.append(" height = Math.max(height, self.innerHeight);")<br />.append(LS);<br />jsDimension.append("}").append(LS);<br />jsDimension.append("if(document.body.scrollWidth) {").append(LS);<br />jsDimension.append(<br />" width = Math.max(width, document.body.scrollWidth);")<br />.append(LS);<br />jsDimension.append(<br />" height = Math.max(height, document.body.scrollHeight);")<br />.append(LS);<br />jsDimension.append("}").append(LS);<br />jsDimension.append("return width + ':' + height;");<br />}<br /> //DJNativeSwing組件請於http://djproject.sourceforge.net/main/index.html下載<br />public Main(final String url, final int maxWidth, final int maxHeight) {<br />super(new BorderLayout());<br />JPanel webBrowserPanel = new JPanel(new BorderLayout());<br />final String fileName = System.currentTimeMillis() + ".jpg";<br />final JWebBrowser webBrowser = new JWebBrowser(null);<br />webBrowser.setBarsVisible(false);<br />webBrowser.navigate(url);<br />webBrowserPanel.add(webBrowser, BorderLayout.CENTER);<br />add(webBrowserPanel, BorderLayout.CENTER);<br />JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER, 4, 4));<br />webBrowser.addWebBrowserListener(new WebBrowserAdapter() {<br />// 監聽載入進度<br />public void loadingProgressChanged(WebBrowserEvent e) {<br />// 當載入完畢時<br />if (e.getWebBrowser().getLoadingProgress() == 100) {<br />String result = (String) webBrowser<br />.executeJavascriptWithResult(jsDimension.toString());<br />int index = result == null ? -1 : result.indexOf(":");<br />NativeComponent nativeComponent = webBrowser<br />.getNativeComponent();<br />Dimension originalSize = nativeComponent.getSize();<br />Dimension imageSize = new Dimension(Integer.parseInt(result<br />.substring(0, index)), Integer.parseInt(result<br />.substring(index + 1)));<br />imageSize.width = Math.max(originalSize.width,<br />imageSize.width + 50);<br />imageSize.height = Math.max(originalSize.height,<br />imageSize.height + 50);<br />nativeComponent.setSize(imageSize);<br />BufferedImage image = new BufferedImage(imageSize.width,<br />imageSize.height, BufferedImage.TYPE_INT_RGB);<br />nativeComponent.paintComponent(image);<br />nativeComponent.setSize(originalSize);<br />// 當網頁超出目標大小時<br />if (imageSize.width > maxWidth<br />|| imageSize.height > maxHeight) {<br />//部分圖形<br />image = image.getSubimage(0, 0, maxWidth, maxHeight);<br />/*此部分為使用縮圖<br />int width = image.getWidth(), height = image<br />.getHeight();<br /> AffineTransform tx = new AffineTransform();<br />tx.scale((double) maxWidth / width, (double) maxHeight<br />/ height);<br />AffineTransformOp op = new AffineTransformOp(tx,<br />AffineTransformOp.TYPE_NEAREST_NEIGHBOR);<br />//縮小<br />image = op.filter(image, null);*/<br />}<br />try {<br />// 輸出映像<br />ImageIO.write(image, "jpg", new File(fileName));<br />} catch (IOException ex) {<br />ex.printStackTrace();<br />}<br />// 退出操作<br />System.exit(0);<br />}<br />}<br />}<br />);<br />add(panel, BorderLayout.SOUTH);<br />}<br />public static void main(String[] args) {<br />NativeInterface.open();<br />SwingUtilities.invokeLater(new Runnable() {<br />public void run() {<br />// SWT組件轉Swing組件,不初始化父表單將無法啟動webBrowser<br />JFrame frame = new JFrame("以DJ組件儲存指定網頁");<br />// 載入指定頁面,最大儲存為640x480的<br />frame.getContentPane().add(<br />new Main("http://blog.csdn.net/cping1982", 640, 480),<br />BorderLayout.CENTER);<br />frame.setSize(800, 600);<br />// 僅初始化,但不顯示<br />frame.invalidate();<br />frame.pack();<br />frame.setVisible(false);<br />}<br />});<br />NativeInterface.runEventPump();<br />}<br />}<br />

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.