2016-11-07 70 views
1

使用Socket我可以向服務器發送http請求並獲取html響應。我的目標是讓每個圖像可能是png, jpeg, gif,或任何其他圖像類型。來自http響應的Java過濾器圖像

但是,通過查看來自不同網站的回覆,我注意到一些圖片不使用html的<img>標籤,而是可能在CSS中。 如何提取<img>圖像和css圖像(例如background-image)? 使用正則表達式從<img>獲取這些圖像url是否好?

請不要將我引用到像Apache HttpClient這樣的http類。 我的問題不在於http協議。

+2

請提供基本代碼來澄清您的問題 –

回答

1

正如其他答案已經提到的那樣,理想情況下,您將使用理解如何解析,渲染和遞歸HTTP資源(即.html/css/js/png/gif/jpg /等)的工具。

話雖這麼說,如果你感覺特別受虐狂(我懷疑你),你可以這樣做自己......

這不是一個完美的解決方案,但如果我打算用攻擊這個鈍的工具,我會使用正則表達式(我不會進入正則表達式的細節,它已經是widely documented on the interwebs)。我的過程將是:

  1. HTTP GET我的基頁。
  2. 刪除所有與匹配的字符串定義「資源」(使用正則表達式)。
  3. 有選擇地爲這些資源遞送更多的字符串。

你已經提到你可以執行HTTP請求/響應(使用Sockets),所以我不會在這裏介紹。

瞧!

/** 
* Regular expression to match file types - .js/.css/.png/.jpg/.gif 
*/ 
public static final Pattern resources = Pattern.compile("([^\"'\n({}]+\\.(js|css|png|jpg|gif))", 
     Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); 

/** 
* Pulls out "resources" from the provided text. 
*/ 
public static Set<String> findResources(URL url, String text) { 
    Matcher matcher = resources.matcher(text); 
    Set<String> resources = new HashSet<>(); 
    while (matcher.find()) { 
     String resource = matcher.group(1); 
     String urlStr = url.toString(); 
     int endIndex = urlStr.lastIndexOf("/") + 1; 
     String parentPath = endIndex > 0 ? urlStr.substring(0, endIndex) : urlStr; 
     String fqResource = resource.startsWith("//") ? url.getProtocol() + ":" + resource : 
       resource.startsWith("http") ? resource 
         : resource.startsWith("/") ? getBaseUrl(url) + resource : parentPath + resource; 
     if (fqResource.contains("?")) { 
      fqResource = fqResource.substring(0, fqResource.indexOf("?")); 
     } 
     resources.add(fqResource); 
    } 
    return resources; 
} 

正則表達式:查找在css/js/png/gif/jpg

的方法結束阱形成的字符串:檢索從給定文本(又名「http響應」)中的所有字符串匹配,試圖建立一個完全限定的URL,並返回一組數據。

我已經上傳了full example here(帶有示例輸出)。玩的開心!

-2

您可以使用JSoup a HTML & XML解析器。 下面是一個例子,如何做到這一點,

String responseData = ""; // HTML data 
Document doc = Jsoup.parse(responseData); 
Elements images = doc.select("img"); 
// Elements pngImages = doc.select("img[src$=.png]"); 
// To parse specific image format in this case png 
for(Element image : images){ 
    // Do what ever you wanted to do 
} 

Here is related official documentation

+1

這不會提取CSS使用/加載的圖像。我也會使用JSoup而不是正則表達式:它更可靠。 –

4

要獲取所有圖像,包括由css和js加載的圖像,您需要的不僅僅是html代碼。 您需要瞭解的代碼 html和css和js。 您需要一個完整的瀏覽器。

幸運的是,Java自帶瀏覽器。 JavaFXWebEngine。 給它一個url或html,它會加載一切。 作爲WebKit,它知道最新的圖像加載技術,例如CSS border-image

我們只需要一種方法來獲取它的圖像。 它不提供media list,但由於它是純Java的,我們可以劫持Java的URL處理器攔截其請求:

import java.io.IOException; import java.net.URL; import java.net.URLConnection; import javafx.application.Application; import javafx.application.Platform; import javafx.concurrent.Worker; import javafx.scene.Scene; import javafx.scene.web.WebView; import javafx.stage.Stage; 

public class NetworkMonitor extends Application { 

    private final String url = "http://www.google.com/"; 

    public static void main(String[] args) { 
     // Override default http/https handler. Must do once only. 
     URL.setURLStreamHandlerFactory(protocol -> 
     protocol.equals("http") ? new HttpHandler() : 
     protocol.equals("https") ? new HttpsHandler() : null); 
     // Launch as JavaFX app. Required for WebView/WebEngine. 
     launch(args); 
    } 

    @Override public void start(Stage primaryStage) throws Exception { 
     // Create webview and listen for ondone 
     WebView v = new WebView(); 
     v.getEngine().getLoadWorker().stateProperty().addListener((prop, old, now) -> { 
     if (now == Worker.State.SUCCEEDED || now == Worker.State.FAILED) 
      Platform.exit(); }); 
     // Showing GUI is easiest way to make sure ondone will be fired. 
     primaryStage.setScene(new Scene(v)); 
     primaryStage.show(); 
     // Load the target url. 
     v.getEngine().load(url); 
    } 

    // Your IDE should warn you about the sun package. 
    private static class HttpHandler extends sun.net.www.protocol.http.Handler { 
     @Override protected URLConnection openConnection(URL url) throws IOException { 
     System.out.println(url); // Capture url! 
     return super.openConnection(url); 
     } 
    } 

    // If there is no warning, you need to switch to a better IDE! 
    private static class HttpsHandler extends sun.net.www.protocol.https.Handler { 
     @Override protected URLConnection openConnection(URL url) throws IOException { 
     System.out.println(url); // Capture url! 
     return super.openConnection(url); 
     } 
    } 
} 

既然你只問如何獲得URL,這是代碼做什麼。 該代碼可以根據您的需求進行擴展。

例如,兩個用於URLConnection的decorator對象應該允許您攔截getInputStream調用並查詢其標頭(以確定MIME類型)並分叉流(以保存圖像的副本)。

如果此答案有用,請不要忘記投票!