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

PHP 反防盜鏈采集核心技術:基於 Socket 的 HTTP 原始請求實現

     編輯:PHP 相關知識

背景與痛點

許多網站啟用「防盜鏈」機制,透過檢查 HTTP Request Header 中的 Referer 欄位,僅允許自家域名或白名單域名請求圖片/頁面內容。常見的 file_get_contents()、fopen()、cURL (預設) 往往發送空 Referer 或 PHP 機器特徵 Referer,導致被擋回 403/404 或跳轉頁面。

本文提供一個 底層 Socket 實現的 HTTP/1.0 客戶端,可完全自訂 Header (Referer, User-Agent, Accept, Cookie 等),繞過大多數基於 Header 的防盜鏈檢查。

核心函數:retrieveURLContentBySocket()

<?php
/**
 * 使用原始 Socket 發送 HTTP GET 請求,支援自訂 Host、Port、Timeout、完整 Header 控制
 * 
 * @param string $url     目標 URL (若提供 $host 則視為 URI Path)
 * @param string $host    指定 Host Header (可偽裝 Referer 來源域名)
 * @param int    $port    連接埠 (預設 80)
 * @param int    $timeout 連線/讀取超時秒數
 * @return string|false   回應 Body 內容,失敗回傳 false
 */
function retrieveURLContentBySocket($url, $host = "", $port = 80, $timeout = 30) {
    // 1. 解析 URL 與 Host
    if ($host === "") {
        if (($pos = strpos($url, '://')) === false) return false;
        $host = substr($url, $pos + 3);
        $host = substr($host, 0, strpos($host, '/'));
        $uri = substr($url, strpos($url, '/', $pos + 3));
        if ($uri === false || $uri === '') $uri = '/';
    } else {
        $uri = $url; // 此模式下 $url 應為 URI Path
    }

    // 2. 建構 HTTP/1.0 請求報文 (關鍵:手動控制 Header)
    $request = "GET $uri HTTP/1.0\r\n"
             . "Host: $host\r\n"
             . "Accept: */*\r\n"
             . "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36\r\n"
             . "Referer: https://$host/\r\n"  // 核心:偽裝來自目標站點首頁
             . "Connection: Close\r\n"      // HTTP/1.0 預設短連線,避免 Keep-Alive 卡住
             . "\r\n";

    // 3. 建立 Socket 連線
    $errno = 0; $errstr = '';
    $socket = @fsockopen($host, $port, $errno, $errstr, $timeout);
    if (!$socket) {
        error_log("Socket 連線失敗 [$errno]: $errstr (Host: $host:$port)");
        return false;
    }

    // 4. 設定串流超時 (讀取/寫入)
    stream_set_timeout($socket, $timeout);

    // 5. 發送請求
    if (@fwrite($socket, $request) === false) {
        fclose($socket);
        return false;
    }

    // 6. 讀取完整回應
    $response = '';
    while (!feof($socket)) {
        $chunk = fread($socket, 8192);
        if ($chunk === false || $chunk === '') break;
        $response .= $chunk;
        
        // 讀取超時檢查
        $info = stream_get_meta_data($socket);
        if ($info['timed_out']) {
            error_log("Socket 讀取超時: $host$uri");
            break;
        }
    }
    fclose($socket);

    // 7. 分離 Header 與 Body
    $headerEnd = strpos($response, "\r\n\r\n");
    if ($headerEnd === false) {
        return $response; // 非標準回應,全回傳
    }
    
    // 可選:解析狀態碼、Content-Type、Set-Cookie 等
    // $header = substr($response, 0, $headerEnd);
    // if (strpos($header, 'HTTP/1.') !== 0) return false;
    // if (strpos($header, ' 200 ') === false) return false; // 非 200 視為失敗
    
    return substr($response, $headerEnd + 4);
}

// ===== 進階用法範例 =====
// 采集受防盜鏈保護的圖片
$imageUrl = '/images/protected/photo.jpg';
$targetHost = 'example.com';
$binaryContent = retrieveURLContentBySocket($imageUrl, $targetHost, 80, 15);
if ($binaryContent !== false) {
    file_put_contents('photo.jpg', $binaryContent);
    echo "圖片采集成功 (" . strlen($binaryContent) . " bytes)";
} else {
    echo "采集失敗";
}

// 采集 HTTPS 頁面 (需搭配 SSL Context 或改用 cURL)
?>

關鍵技術細節解析

1. HTTP/1.0 vs HTTP/1.1

  • 範例使用 HTTP/1.0 + Connection: Close,簡化連線管理,避免 Chunked Transfer Encoding 解析麻煩。
  • 若需支援 HTTPS、Keep-Alive、Chunked、壓縮 等,強烈建議改用 cURL (見下方對比)。

2. Header 偽裝策略 (繞過防盜鏈核心)

Header偽裝目的建議值
Referer核心防盜鏈判斷依據https://target-domain.com/ 或具體列表頁 URL
User-Agent識別爬蟲/機器人最新 Chrome/Edge/Firefox 完整 UA 字串
Accept內容協商text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language地區化內容zh-TW,zh;q=0.9,en-US;q=0.8,en;q=0.7
Cookie會話/登入狀態從瀏覽器開發工具複製完整 Cookie 字串
X-Forwarded-ForIP 白名單繞過 (部分站點)隨機內網 IP 或目標國家代理 IP

3. Socket vs cURL 選型指南

🔧 原始 Socket (fsockopen)

  • 優點:完全控制 TCP 層、無依賴、教學價值高、可實作非標準協定。
  • 缺點:需手寫 HTTP 協定解析 (Header/Body 分離、Chunked、Gzip、HTTPS/SSL、重導向、Cookie 罐)。
  • 適用:特殊協定、嵌入式環境無 cURL、教學示範、極簡 HTTP/1.0 GET。

🚀 cURL (推薦生產環境)

  • 優點:完整支援 HTTPS/HTTP2、自動重導向、Cookie 管理、多執行緒 (curl_multi)、代理、認證、憑證驗證、效能極佳。
  • 缺點:需安裝擴充套件、較重量級。
  • 適用:所有生產級采集任務。

cURL 版反防盜鏈最佳實踐 (生產級)

function fetchWithAntiHotlink($url, $referer = '', $opts = []) {
    $ch = curl_init();
    
    $defaultOpts = [
        CURLOPT_URL => $url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_FOLLOWLOCATION => true,      // 自動追蹤 301/302
        CURLOPT_MAXREDIRS => 5,
        CURLOPT_CONNECTTIMEOUT => 10,
        CURLOPT_TIMEOUT => 30,
        CURLOPT_SSL_VERIFYPEER => false,     // 采集通常關閉驗證
        CURLOPT_SSL_VERIFYHOST => false,
        CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
        CURLOPT_REFERER => $referer ?: $url, // 自動帶入目標域名
        CURLOPT_ENCODING => 'gzip,deflate',  // 自動解壓
        CURLOPT_COOKIEJAR => '',             // 啟用記憶體 Cookie 罐
        CURLOPT_COOKIEFILE => '',
        CURLOPT_HTTPHEADER => [
            'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
            'Accept-Language: zh-TW,zh;q=0.9,en-US;q=0.8,en;q=0.7',
            'Cache-Control: no-cache',
            'Pragma: no-cache',
        ],
    ];
    
    curl_setopt_array($ch, array_merge($defaultOpts, $opts));
    $content = curl_exec($ch);
    $errno = curl_errno($ch);
    $info = curl_getinfo($ch);
    curl_close($ch);
    
    if ($errno) return ['error' => curl_strerror($errno), 'info' => $info];
    if ($info['http_code'] >= 400) return ['error' => "HTTP {$info['http_code']}", 'info' => $info];
    
    return ['content' => $content, 'info' => $info];
}

// 使用
$result = fetchWithAntiHotlink('https://target.com/page.html', 'https://target.com/list.html');
if (isset($result['content'])) {
    // 成功
}

法律與道德邊界 (必讀)

⚖️ 合規采集檢查清單

  1. 檢查 robots.txt:User-agent: * Disallow: /path/ 禁止路徑不可抓取。
  2. 遵守 Terms of Service:網站條款若明文禁止爬蟲/采集,法律風險極高。
  3. 頻率限制:單 IP 每秒 < 1-2 請求,隨機延遲 sleep(rand(1, 5))。
  4. 資料用途:僅供個人研究/搜尋引擎索引,嚴禁商業轉售、競品監控違反反壟斷法。
  5. 個資保護:GDPR、個資法嚴禁未經同意蒐集個人資料 (姓名、電話、Email、IP 等)。

結語

Socket 底層實現展示了 HTTP 協定本質,是理解「繞過防盜鏈」原理的最佳教材。但實務上,請直接使用 cURL 並配合完整 Header 偽裝、代理 IP 池、Headless Chrome 渲染 組合拳,才能穩定應對現代 WAF (Web Application Firewall)、行為分析、JS 挑戰 等多層防護。技術無罪,用途決定合法性,請謹慎使用。

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