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

PHP 遠端圖片下載器:支援偽造 Referer、Cookie、自動追蹤重導向

     編輯:PHP 綜合知識

功能特點

  • 使用 fsockopen 底層 Socket 實現 HTTP/1.1 下載
  • 支援偽造 Referer 繞過防盜鏈
  • 支援自訂 Cookie 與自動從 Referer 頁面獲取 Cookie
  • 自動處理 3xx 重導向(最多 3 次)
  • 支援超時控制與大小限制

核心函式 DownImageKeep

<?php
/**
 * 下載遠端圖片並儲存
 *
 * @param string $gurl       圖片 URL
 * @param string $rfurl      Referer(防盜鏈繞過)
 * @param string $filename   儲存檔名(相對路徑)
 * @param string $gcookie    自訂 Cookie
 * @param int    $JumpCount  內部重導向計數
 * @param int    $maxtime    最大下載秒數
 * @return bool
 */
function DownImageKeep($gurl, $rfurl, $filename, $gcookie = "", $JumpCount = 0, $maxtime = 30) {
    $urlinfos = GetHostInfo($gurl);
    $ghost = trim($urlinfos['host']);
    if ($ghost == '') return false;
    
    $gquery = $urlinfos['query'];
    
    // 自動從 Referer 獲取 Cookie
    if ($gcookie == "" && !empty($rfurl)) {
        $gcookie = RefurlCookie($rfurl);
    }
    
    // 組裝 HTTP 請求
    $sessionQuery  = "GET $gquery HTTP/1.1\r\n";
    $sessionQuery .= "Host: $ghost\r\n";
    $sessionQuery .= "Referer: $rfurl\r\n";
    $sessionQuery .= "Accept: */*\r\n";
    $sessionQuery .= "User-Agent: Mozilla/4.0 (compatible; MSIE 5.00; Windows 98)\r\n";
    if ($gcookie != "" && !preg_match("/[\r\n]/", $gcookie)) {
        $sessionQuery .= $gcookie . "\r\n";
    }
    $sessionQuery .= "Connection: Keep-Alive\r\n\r\n";
    
    $errno = $errstr = "";
    $m_fp = fsockopen($ghost, 80, $errno, $errstr, 10);
    if (!$m_fp) return false;
    
    fwrite($m_fp, $sessionQuery);
    
    // 解析回應 Header
    $m_httphead = [];
    $httpstas = explode(" ", fgets($m_fp, 256));
    $m_httphead["http-edition"] = trim($httpstas[0]);
    $m_httphead["http-state"]   = trim($httpstas[1]);
    
    $lnum = 0;
    while (!feof($m_fp)) {
        $line = trim(fgets($m_fp, 256));
        if ($line == "" || $lnum > 100) break;
        $lnum++;
        
        if (($pos = strpos($line, ':')) !== false) {
            $hkey   = strtolower(trim(substr($line, 0, $pos)));
            $hvalue = trim(substr($line, $pos + 1));
            if ($hkey) $m_httphead[$hkey] = $hvalue;
        }
    }
    
    // 處理重導向
    if (preg_match("/^3/", $m_httphead["http-state"])) {
        if (isset($m_httphead["location"]) && $JumpCount < 3) {
            return DownImageKeep($m_httphead["location"], $rfurl, $filename, $gcookie, $JumpCount + 1, $maxtime);
        }
        return false;
    }
    
    // 非 2xx 失敗
    if (!preg_match("/^2/", $m_httphead["http-state"])) return false;
    
    $contentLength = isset($m_httphead['content-length']) ? (int)$m_httphead['content-length'] : 0;
    
    // 儲存檔案
    $fp = @fopen($filename, "wb");
    if (!$fp) return false;
    
    $okdata = "";
    $starttime = time();
    $i = 0;
    
    while (!feof($m_fp)) {
        $okdata .= fgetc($m_fp);
        $i++;
        
        // 超時中斷
        if (time() - $starttime > $maxtime) break;
        // 達到 Content-Length 中斷
        if ($contentLength && $i >= $contentLength) break;
    }
    
    fclose($m_fp);
    
    if ($okdata != "") {
        fwrite($fp, $okdata);
        fclose($fp);
        return true;
    } else {
        fclose($fp);
        @unlink($filename);
        return false;
    }
}

/** 從 Referer 頁面獲取 Cookie */
function RefurlCookie($gurl) {
    global $gcookie, $lastRfurl;
    $gurl = trim($gurl);
    if (!empty($gcookie) && $lastRfurl == $gurl) return $gcookie;
    $lastRfurl = $gurl;
    if ($gurl == '') return '';
    
    $urlinfos = GetHostInfo($gurl);
    $ghost = $urlinfos['host'];
    $gquery = $urlinfos['query'];
    
    $sessionQuery  = "GET $gquery HTTP/1.1\r\n";
    $sessionQuery .= "Host: $ghost\r\n";
    $sessionQuery .= "Accept: */*\r\n";
    $sessionQuery .= "User-Agent: Mozilla/4.0 (compatible; MSIE 5.00; Windows 98)\r\n";
    $sessionQuery .= "Connection: Close\r\n\r\n";
    
    $m_fp = fsockopen($ghost, 80, $errno, $errstr, 10);
    if (!$m_fp) return '';
    
    fwrite($m_fp, $sessionQuery);
    $gcookie = "";
    while (!feof($m_fp)) {
        $line = trim(fgets($m_fp, 256));
        if ($line == "") break;
        if (preg_match("/^set-cookie:/i", $line)) {
            $gcookie = $line;
            break;
        }
    }
    fclose($m_fp);
    return $gcookie;
}

/** 解析 URL 取得 host 與 query */
function GetHostInfo($gurl) {
    $gurl = preg_replace("/^https?:\/\//i", "", trim($gurl));
    $garr['host']  = preg_replace("/\/(.*)$/i", "", $gurl);
    $garr['query'] = "/" . preg_replace("/^([^\/]*)\//i", "", $gurl);
    return $garr;
}
?>

使用範例

<?php
// 下載百度 Logo,偽造 Referer 為百度首頁
$result = DownImageKeep(
    "https://www.baidu.com/img/baidu_jgylogo2.gif", // 圖片 URL
    "https://www.baidu.com",                        // Referer
    "baidu_logo.gif",                              // 儲存檔名
    "",                                            // 自訂 Cookie(可留空)
    0,                                             // 重導向計數
    10                                             // 最長 10 秒
);

if ($result) {
    echo "下載成功!";
} else {
    echo "下載失敗";
}
?>

現代替代方案:cURL 版(更簡潔健壯)

<?php
function downloadImageCurl($url, $referer, $savePath, $cookie = '', $timeout = 30) {
    $ch = curl_init();
    curl_setopt_array($ch, [
        CURLOPT_URL            => $url,
        CURLOPT_REFERER        => $referer,
        CURLOPT_USERAGENT      => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
        CURLOPT_COOKIE         => $cookie,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_MAXREDIRS      => 3,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_CONNECTTIMEOUT => 10,
        CURLOPT_TIMEOUT        => $timeout,
        CURLOPT_SSL_VERIFYPEER => false, // 僅測試
    ]);
    
    $data = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    
    if ($httpCode === 200 && $data) {
        return file_put_contents($savePath, $data) !== false;
    }
    return false;
}
?>

法律與道德提醒

下載圖片前請確認:

  1. 符合目標網站 robots.txt 規範
  2. 不違反服務條款(ToS)
  3. 尊重版權與智慧財產權
  4. 高頻請求加入延遲,避免造成對方伺服器負擔
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved