fsockopen 底層 Socket 實現 HTTP/1.1 下載Referer 繞過防盜鏈Cookie 與自動從 Referer 頁面獲取 CookieDownImageKeep<?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 "下載失敗";
}
?>
<?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;
}
?>
下載圖片前請確認:
robots.txt 規範