一段生產可用的 cURL 封裝,涵蓋最常見的爬蟲/對接場景:
$header[] = 'Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, text/html, */*';
$header[] = 'Accept-Language: zh-cn';
$header[] = "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:25.0) Gecko/20100101 Firefox/25.0";
$ch = curl_init();
// 基礎設置
curl_setopt($ch, CURLOPT_URL, $url); // 目標 URL
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // 返回字符串而非直接輸出
curl_setopt($ch, CURLOPT_HEADER, 1); // 包含響應 Header
// HTTPS 支持(跳過證書驗證,生產環境建議配置 CA 憑證)
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
// 重定向處理
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // 自動跟隨 Location
curl_setopt($ch, CURLOPT_MAXREDIRS, 10); // 最大重定向次數防死循環
// 偽裝瀏覽器
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_USERAGENT, $header[2]); // 顯式設置 UA
curl_setopt($ch, CURLOPT_REFERER, $url); // 可選:設置 Referer
// 執行與清理
$html = curl_exec($ch);
if (curl_errno($ch)) {
error_log("cURL Error: " . curl_error($ch));
}
curl_close($ch);
// $html 現包含 Header + Body,可用以下方式分離:
// list($responseHeaders, $responseBody) = explode("\r\n\r\n", $html, 2);
| 選項 | 作用 | 建議值 |
|---|---|---|
| CURLOPT_RETURNTRANSFER | 將響應作為字符串返回 | 1 (必須) |
| CURLOPT_FOLLOWLOCATION | 自動處理 3xx 重定向 | 1 |
| CURLOPT_MAXREDIRS | 限制重定向層數 | 10-20 |
| CURLOPT_SSL_VERIFYPEER | 驗證 SSL 證書 | 生產環境 TRUE + CAINFO |
| CURLOPT_SSL_VERIFYHOST | 驗證域名與證書匹配 | 生產環境 2 |
| CURLOPT_TIMEOUT | 最大執行秒數 | 10-30 |
| CURLOPT_CONNECTTIMEOUT | 連接等待秒數 | 5-10 |
| CURLOPT_COOKIEJAR/FILE | Cookie 持久化 | 文件路徑 |
| CURLOPT_POSTFIELDS | POST 數據 | 數組或 urlencode 字符串 |
$data = json_encode(['key' => 'value']);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Content-Length: ' . strlen($data)
]);
$info = curl_getinfo($ch); echo "HTTP 狀態碼: " . $info['http_code'] . "\n"; echo "總耗時: " . $info['total_time'] . "s\n"; echo "DNS 解析: " . $info['namelookup_time'] . "s\n";
$mh = curl_multi_init();
// ... 添加多個 handle ...
$active = null;
do {
$mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
while ($active && $mrc == CURLM_OK) {
if (curl_multi_select($mh) != -1) {
do { $mrc = curl_multi_exec($mh, $active); } while ($mrc == CURLM_CALL_MULTI_PERFORM);
}
}
CURLOPT_CAINFO 指向 cacert.pemCURLOPT_TIMEOUT 防止腳本卡死curl_error() 和 curl_getinfo() 做完善錯誤處理與監控curl_multi 或 Swoole/Workerman 異步方案COOKIEJAR 和 COOKIEFILE