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

PHP 遠端內容抓取全方位比較:cURL vs file_get_contents vs fsockopen

     編輯:PHP 綜合知識

在 PHP 開發中,抓取遠端資源是常見需求。最常用的三種方式——file_get_contents、fsockopen、cURL——各有優劣。本文從功能支援、效能穩定性、使用複雜度、適用場景等維度深度比較,助你選擇最適合的工具。

核心功能對比表

特性file_get_contentsfsockopencURL
支援協定HTTP/HTTPS/FTP (需 allow_url_fopen)TCP/UDP 底層 SocketHTTP/HTTPS/FTP/FTPS/SMTP/POP3/LDAP 等 20+ 種
HTTP 方法GET/POST (需 stream_context)完全手動組裝GET/POST/PUT/DELETE/HEAD/PATCH 等完整支援
Header 控制有限 (stream_context)完全自訂完整控制 (CURLOPT_HTTPHEADER)
Cookie 管理手動處理手動處理內建 Cookie Jar (CURLOPT_COOKIEJAR/FILE)
SSL/TLS基礎支援需自行實作完整支援驗證、憑證、Cipher 選項
代理支援stream_context手動 CONNECTHTTP/SOCKS4/5 完整支援
超時控制不穩定 (stream_context timeout 常失效)手動 select()精確控制 (連線/執行/名稱解析分離)
斷點續傳不支援手動實作內建 Range 標頭支援
並發請求不支援需多進程cURL Multi 介面原生支援
DNS 快取無無內建 DNS 快取 (效能亮點)
效能單次請求尚可,持久連線差最底層,開銷最小但開發成本高最佳:連線複用、管線化、非同步多工
學習曲線最低最高 (需懂 HTTP 協定細節)中等 (參數多但文件完善)

實測效能數據(抓取 google.com 首頁)

file_get_contents 耗時(秒):
2.31, 2.30, 2.22, 3.31, 2.30  → 平均 ~2.49s

cURL 耗時(秒):
0.69, 0.65, 0.64, 0.82, 0.64  → 平均 ~0.69s

結論:cURL 速度快 3-4 倍,且穩定度高得多。

常見使用模式速查

1. file_get_contents - 簡單 GET 請求

<?php
$url = 'https://api.example.com/data';
$html = file_get_contents($url);
echo $html;
?>

2. file_get_contents - POST 請求

<?php
$data = http_build_query(['foo' => 'bar']);
$opts = [
    'http' => [
        'method' => 'POST',
        'header' => "Content-type: application/x-www-form-urlencoded\r\n" .
                    "Content-Length: " . strlen($data) . "\r\n",
        'content' => $data,
        'timeout' => 10 // 注意:此超時在某些 PHP 版本不生效
    ]
];
$context = stream_context_create($opts);
$result = file_get_contents('https://api.example.com/endpoint', false, $context);
?>

3. fsockopen - 底層 Socket 完整控制

<?php
function httpRequest($url, $method = 'GET', $data = [], $headers = []) {
    $parsed = parse_url($url);
    $host = $parsed['host'];
    $port = $parsed['port'] ?? ($parsed['scheme'] === 'https' ? 443 : 80);
    $path = $parsed['path'] . ($parsed['query'] ? '?' . $parsed['query'] : '');
    
    $fp = fsockopen(($parsed['scheme'] === 'https' ? 'ssl://' : '') . $host, $port, $errno, $errstr, 10);
    if (!$fp) return false;
    
    $request = "$method $path HTTP/1.1\r\n";
    $request .= "Host: $host\r\n";
    $request .= "Connection: Close\r\n";
    foreach ($headers as $k => $v) $request .= "$k: $v\r\n";
    if ($method === 'POST') {
        $body = http_build_query($data);
        $request .= "Content-Type: application/x-www-form-urlencoded\r\n";
        $request .= "Content-Length: " . strlen($body) . "\r\n";
    }
    $request .= "\r\n";
    if ($method === 'POST') $request .= $body;
    
    fwrite($fp, $request);
    $response = '';
    while (!feof($fp)) $response .= fgets($fp, 4096);
    fclose($fp);
    return $response;
}
?>

4. cURL - 企業級標準選擇

<?php
// 通用封裝函數
function curlRequest($url, $options = []) {
    $ch = curl_init();
    $defaults = [
        CURLOPT_URL => $url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => 10,
        CURLOPT_CONNECTTIMEOUT => 5,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_MAXREDIRS => 5,
        CURLOPT_SSL_VERIFYPEER => true, // 生產環境建議開啟
        CURLOPT_USERAGENT => 'Mozilla/5.0 (compatible; PHP Bot)',
    ];
    curl_setopt_array($ch, $defaults + $options);
    $response = curl_exec($ch);
    $error = curl_error($ch);
    $info = curl_getinfo($ch);
    curl_close($ch);
    return ['body' => $response, 'error' => $error, 'info' => $info];
}

// GET 請求
$result = curlRequest('https://api.example.com/users');

// POST JSON 請求
$result = curlRequest('https://api.example.com/users', [
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => json_encode(['name' => 'John']),
    CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Authorization: Bearer xxx']
]);

// 檔案上傳 (PHP 5.5+ 使用 CURLFile)
$result = curlRequest('https://api.example.com/upload', [
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => ['file' => new CURLFile('/path/to/file.jpg', 'image/jpeg', 'photo.jpg')]
]);

// 模擬瀏覽器登入 (Cookie 自動管理)
$cookieJar = tempnam(sys_get_temp_dir(), 'cookie_');
$ch = curl_init();
curl_setopt_array($ch, [
    CURLOPT_URL => 'https://site.com/login',
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => ['username' => 'user', 'password' => 'pass'],
    CURLOPT_COOKIEJAR => $cookieJar,
    CURLOPT_COOKIEFILE => $cookieJar,
    CURLOPT_RETURNTRANSFER => true,
]);
curl_exec($ch); // 登入並儲存 Cookie
// 後續請求自動攜帶 Cookie
curl_setopt($ch, CURLOPT_URL, 'https://site.com/dashboard');
$dashboard = curl_exec($ch);
curl_close($ch);
?>

專家觀點總結

趙永斌:file_get_contents 容易超時,換 cURL 即解決。cURL 效率較高,因為會自動快取 DNS 资訊。

范佳鵬:公司演進歷程:file_get_contents → fsockopen → cURL。cURL 支援 Keep-Alive 持久連線,適合大量採集。

潘少寧 (騰訊):file_get_contents 只能拉資料;cURL 支援 POST/GET/Header;Socket 最底層,UDP/TCP 都能玩。Socket 能做的 cURL 不一定能做,但 file_get_contents/cURL 能做的 Socket 都能做。

選擇建議決策樹

  • 簡單 GET、一次性腳本、無依賴限制 → file_get_contents (確認 allow_url_fopen=On)
  • 需控制 Header、Cookie、POST、超時、SSL、代理、並發、大檔案、穩定性 → cURL (首選)
  • 極度客製化協定、非 HTTP 協定、教學研究 HTTP 細節 → fsockopen / stream_socket_client
  • 現代 PHP (7.1+) 新專案 → 推薦使用 GuzzleHttp (cURL 物件導向封裝,支援 PSR-7/18、Middleware、非同步)

總結:file_get_contents 適合簡單場景,但生產環境特別是採集、API 串接、高併發場景,cURL 是事實標準。投資學習 cURL 參數(CURLOPT_*)回報率極高。

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