Java 原生 `HttpURLConnection` 無需第三方依賴即可完成 HTTP 通信。本文以知乎模擬登錄為例,演示如何通過瀏覽器開發者工具分析請求、提取關鍵 Header、構建通用請求工具類、處理 GET/POST、Cookie 管理,並封裝可復用的異步回調框架。
經測試,訪問知乎首頁僅需 `Cookie` 包含有效登錄憑證即可,其他 Header (User-Agent、Accept 等) 非必需但建議補全防反爬。
public class HttpUtils {
private HttpURLConnection conn;
private OnVisitingListener listener;
public interface OnVisitingListener {
void onSuccess(HttpURLConnection conn);
void onSetDetails(HttpURLConnection conn, HttpUtils httpUtils); // 設置 Header/Body
void onFail(IOException e);
}
public HttpUtils setOnVisitingListener(OnVisitingListener l) { this.listener = l; return this; }
public void startConnection(String url, String method) {
try {
URL u = new URL(url);
conn = (HttpURLConnection) u.openConnection();
conn.setRequestMethod(method);
conn.setConnectTimeout(5000);
conn.setReadTimeout(5000);
listener.onSetDetails(conn, this); // 回調設置細節
conn.connect();
if (conn.getResponseCode() == 200) listener.onSuccess(conn);
else throw new IOException("HTTP " + conn.getResponseCode());
} catch (IOException e) { listener.onFail(e); }
}
// 批量設置 Header
public void setRequestProperties(Map headers) {
for (Map.Entry e : headers.entrySet())
conn.setRequestProperty(e.getKey(), e.getValue());
}
// 設置 Request Body (POST)
public void setRequestBody(String body) throws IOException {
try (PrintWriter w = new PrintWriter(conn.getOutputStream())) {
w.write(body); w.flush();
}
}
public static HttpUtils newInstance() { return new HttpUtils(); }
}
public class StreamUtils {
// 讀取流為字符串
public static String readFromStream(InputStream in) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buf = new byte[1024]; int len;
while ((len = in.read(buf)) != -1) out.write(buf, 0, len);
return out.toString(StandardCharsets.UTF_8);
}
// 按行讀取文件/流,回調處理
public interface OnGetStringListener { void onGetString(String line); void onGeted(); }
public static void getString(Object src, OnGetStringListener l) throws IOException {
BufferedReader br = createBufferedReader(src, null);
String line;
while ((line = br.readLine()) != null) l.onGetString(line);
l.onGeted(); br.close();
}
// 創建 BufferedReader (支持 File/String/InputStream/Reader)
static BufferedReader createBufferedReader(Object src, String charset) throws IOException { /* ... */ }
}
public class ZhihuCrawler {
public static void main(String[] args) {
HttpUtils.newInstance().setOnVisitingListener(new HttpUtils.OnVisitingListener() {
@Override public void onSuccess(HttpURLConnection conn) {
try { System.out.println(StreamUtils.readFromStream(conn.getInputStream())); }
catch (IOException e) { e.printStackTrace(); }
}
@Override public void onSetDetails(HttpURLConnection conn, HttpUtils httpUtils) {
Map headers = new HashMap<>();
// 從文件讀取預先保存的 Header (含 Cookie)
StreamUtils.getString("requestheader.txt", new StreamUtils.OnGetStringListener() {
@Override public void onGetString(String line) {
String[] kv = line.split(":", 2);
if (kv.length == 2) headers.put(kv[0].trim(), kv[1].trim());
}
@Override public void onGeted() { httpUtils.setRequestProperties(headers); }
});
}
@Override public void onFail(IOException e) { e.printStackTrace(); }
}).startConnection("https://www.zhihu.com/", "GET");
}
}
requestheader.txt 示例:
Cookie: _xsrf=...; z_c0=...; d_c0=...; q_c1=...
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Referer: https://www.zhihu.com/
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
httpUtils.setOnVisitingListener(new HttpUtils.OnVisitingListener() {
@Override public void onSetDetails(HttpURLConnection conn, HttpUtils httpUtils) {
Map headers = new HashMap<>();
headers.put("Content-Type", "application/x-www-form-urlencoded");
headers.put("Cookie", "..."); // 如有預登錄 Cookie
httpUtils.setRequestProperties(headers);
// 構建表單體: phone_num=xxx&password=yyy&captcha=...
httpUtils.setRequestBody("phone_num=13800000000&password=123456");
}
// onSuccess/onFail 同 GET
}).startConnection("https://www.zhihu.com/login/phone_num", "POST");
| 挑戰 | 應對策略 |
|---|---|
| User-Agent 檢測 | 設置真實瀏覽器 UA,定期輪換 |
| Cookie 失效/掃碼登錄 | 維護 Cookie 池,研究登錄流程 (二維碼/短信/滑塊),或使用 Selenium/Playwright 自動化瀏覽器獲取 Cookie |
| IP 限流/封禁 | 代理 IP 池 (付費/免費),請求間隔隨機化 (1-5s) |
| JS 渲染/動態加載 | HttpURLConnection 無法執行 JS,需 Headless Chrome (Puppeteer/Java 綁定) 或分析 AJAX 接口直接調用 |
| 驗證碼/行為分析 | 打碼平台、模擬人類軌跡、降低頻率 |
| HTTPS 證書驗證 | 生產環境勿關閉驗證;自簽證書需導入信任庫 |
Java 爬蟲核心在於:請求分析 → Header/Body 精準構建 → 異步非阻塞 IO → 反爬對抗 → 數據清洗入庫。本文提供的 `HttpUtils` + `StreamUtils` 雙工具類,採用回調模式解耦邏輯,適合快速驗證與輕量項目。生產環境請拥抱成熟 HTTP 客戶端庫,專注於業務解析與反爬策略迭代。