首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 輕量級網頁爬蟲:HttpURLConnection 實現 GET 抓取與異常處理最佳實踐

     編輯:Java 相關知識

HTTP 爬蟲基礎:URL → HttpURLConnection → InputStream

Java 標準庫提供 java.net.HttpURLConnection,無第三方依賴即可完成 HTTP 請求。核心流程:

  1. new URL(urlStr) 解析地址(可能拋 MalformedURLException);
  2. url.openConnection() 獲取連接對象(尚未建立 TCP 連接);
  3. 強轉 HttpURLConnection 設置請求屬性、超時、重定向策略;
  4. connect() / getInputStream() 真正發起請求(可能拋 IOException);
  5. 讀取響應流,處理編碼、壓縮、分塊傳輸;
  6. finally 關閉流、斷開連接 disconnect()。

生產級封裝:SimpleHttpClient

public final class SimpleHttpClient {
    private static final int DEFAULT_TIMEOUT_MS = 10_000;
    private static final String USER_AGENT = "Mozilla/5.0 (compatible; JavaBot/1.0)";

    private SimpleHttpClient() {}

    /** 同步 GET,返回響應體字符串 */
    public static String get(String urlStr) throws IOException {
        return get(urlStr, DEFAULT_TIMEOUT_MS, null);
    }

    /** 完整參數版 */
    public static String get(String urlStr, int timeoutMs, Map headers) throws IOException {
        HttpURLConnection conn = null;
        try {
            URL url = new URL(urlStr);
            conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(timeoutMs);
            conn.setReadTimeout(timeoutMs);
            conn.setInstanceFollowRedirects(true); // 自動跟隨 301/302
            conn.setRequestProperty("User-Agent", USER_AGENT);
            conn.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
            conn.setRequestProperty("Accept-Encoding", "gzip, deflate"); // 支持壓縮
            
            if (headers != null) headers.forEach(conn::setRequestProperty);

            int code = conn.getResponseCode();
            if (code != HttpURLConnection.HTTP_OK) {
                throw new HttpException("HTTP " + code + " " + conn.getResponseMessage());
            }

            // 自動處理 GZIP
            InputStream is = conn.getInputStream();
            String encoding = conn.getContentEncoding();
            if ("gzip".equalsIgnoreCase(encoding)) is = new GZIPInputStream(is);
            
            // 編碼檢測:優先 Content-Type charset,回退 UTF-8
            String charset = extractCharset(conn.getContentType());
            return IOUtils.toString(is, Charset.forName(charset));
            
        } finally {
            if (conn != null) conn.disconnect(); // 釋放連接回池
        }
    }

    private static String extractCharset(String contentType) {
        if (contentType == null) return "UTF-8";
        Matcher m = Pattern.compile("charset=([^\\s;]+)").matcher(contentType);
        return m.find() ? m.group(1).toUpperCase() : "UTF-8";
    }

    /** 簡易異常類 */
    public static class HttpException extends IOException {
        public HttpException(String msg) { super(msg); }
    }
}

依賴:Apache Commons IO(可選,或自寫 IOUtils)



    commons-io
    commons-io
    2.15.1


若不想引入依賴,自寫 toString(InputStream, Charset) 只需 10 行循環讀取代碼。

調用示例

try {
    String html = SimpleHttpClient.get("https://httpbin.org/html");
    System.out.println("頁面長度:" + html.length());
    // 此處可接 JSoup 解析、正則提取等後續處理
} catch (SimpleHttpClient.HttpException e) {
    System.err.println("業務錯誤:" + e.getMessage());
} catch (IOException e) {
    System.err.println("網絡/IO 錯誤:" + e.getMessage());
}

進階:應對反爬與複雜場景

場景HttpURLConnection 局限升級方案
Cookie 會話保持手動管理 CookieManagerOkHttp 自動 CookieJar
連接池複用無連接池,每次新建OkHttp ConnectionPool / HttpClient 5
HTTP/2 支持不支持OkHttp / Jetty Client
異步非阻塞阻塞 IONetty / Vert.x / WebClient
JS 動態渲染無法執行 JSSelenium / Playwright / Puppeteer

總結

HttpURLConnection 是 Java 標準庫的輕量級 HTTP 客戶端,適合簡單同步 GET/POST、無高併發、無複雜會話的場景。生產環境建議遷移至 OkHttp 或 Apache HttpClient 5,獲得連接池、攔截器、HTTP/2、異步等企業級能力。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved