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

crawler4j 整合 Jsoup 解決無編碼頁面亂碼問題

     編輯:Java 相關知識

問題背景

crawler4j 抓取帶明確編碼的頁面表現優異,搭配 Jsoup 解析 HTML 更是如虎添翼。但遇到 Response Header 缺少 Content-Type charset 的頁面時,crawler4j 預設以 ISO-8859-1 解碼,導致中文內容變成亂碼,Jsoup 再接手時已無力回天。

核心解法:攔截 Page.load() 強制指定編碼

在 crawler4j 原始碼中,Page.load(HttpEntity) 負責將回應實體轉為位元組陣列 contentData。修改此處解碼邏輯,若無編碼則預設用 GBK(或目標站常用編碼),即可從源頭修正亂碼。

修改後的 load() 方法

public void load(HttpEntity entity) throws Exception {
    contentType = null;
    Header type = entity.getContentType();
    if (type != null) contentType = type.getValue();

    contentEncoding = null;
    Header encoding = entity.getContentEncoding();
    if (encoding != null) contentEncoding = encoding.getValue();

    Charset charset = ContentType.getOrDefault(entity).getCharset();
    if (charset != null) {
        contentCharset = charset.displayName();
    } else {
        contentCharset = "gbk"; // ★ 關鍵:無編碼時預設 GBK
    }

    // 原始碼:contentData = EntityUtils.toByteArray(entity);
    // 修正後:先以 GBK 解碼為字串,再獲取位元組,確保中文不亂碼
    contentData = EntityUtils.toString(entity, Charset.forName("gbk")).getBytes();
}

原理說明

  1. EntityUtils.toString(entity, Charset.forName("gbk")):以 GBK 將回應體轉為 Java 字串(內部為 UTF-16)。
  2. .getBytes():將字串轉回預設編碼(通常 UTF-8)的位元組陣列,供後續 Jsoup 解析。
  3. 若目標站為 Big5/UTF-8 等,只需將 "gbk" 替換為對應編碼名稱。

完整整合流程

  1. 下載 crawler4j 源碼(或以 Maven 依賴形式引入並覆寫 Page 類)。
  2. 替換 Page.load() 為上述版本並重新編譯打包。
  3. 爬蟲邏輯維持不變:Jsoup.parse(new String(page.getContentData())) 即可獲得正確 Document。

進階技巧:動態偵測編碼

若目標站編碼不固定,可整合 juniversalchardet 或 ICU4J 在 load() 中自動偵測:

// 伪代码
if (charset == null) {
    byte[] raw = EntityUtils.toByteArray(entity);
    String detected = CharsetDetector.detect(raw); // 需引入偵測庫
    contentData = new String(raw, detected).getBytes();
}

一行修改徹底解決「無編碼頁面亂碼」痛點,讓 crawler4j + Jsoup 組合在中文網頁抓取場景無往不利。

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