批量下載網頁圖片是常見需求 (素材收集、鏡像站、數據分析)。本代碼實現:獲取頁面 → 正則提取 <img src="..."> → 逐個下載 → 保存至 download/ 目錄 → 自動按時間命名、保留擴展名。
<?php
header("Content-Type: text/html; charset=utf-8"); // 網頁輸出用 HTML,非圖片
// 1. 獲取頁面內容
function read_url($url) {
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_USERAGENT => 'Mozilla/5.0 (compatible; PHP Image Collector)',
]);
$content = curl_exec($ch);
curl_close($ch);
return $content;
}
// 2. 提取圖片 URL
function extract_image_urls($html) {
// 兼容單雙引號、無引號、屬性順序
preg_match_all('/<img\s+[^>]*src\s*=\s*["\']?([^"\'\s>]+)["\']?/i', $html, $matches);
return array_unique($matches[1]);
}
// 3. 下載並保存圖片 (核心)
function GrabImage($url, $saveDir = 'download/') {
if (empty($url)) return false;
// 確保目錄存在
if (!is_dir($saveDir)) mkdir($saveDir, 0755, true);
// 確定文件名
$parsed = parse_url($url);
$basename = basename($parsed['path']);
$ext = strtolower(pathinfo($basename, PATHINFO_EXTENSION));
if (!in_array($ext, ['jpg','jpeg','png','gif','webp','bmp'])) {
$ext = 'jpg'; // 默認
}
$filename = $saveDir . date('YmdHis') . '_' . random_int(1000,9999) . ".$ext";
// 下載 (cURL 支持大文件、重定向、HTTPS)
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_RANGE => '0-20971520', // 限制 20MB 防止巨大文件
]);
$imgData = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
curl_close($ch);
// 驗證
if ($httpCode !== 200 || empty($imgData)) return false;
if (!preg_match('/^image\//', $contentType)) return false; // 確保是圖片
// 保存
$fp = fopen($filename, 'wb');
fwrite($fp, $imgData);
fclose($fp);
return $filename;
}
// 4. 主流程
$targetUrl = 'https://www.jb51.net'; // 可改為 $_GET['url'] 並驗證
$html = read_url($targetUrl);
$imageUrls = extract_image_urls($html);
echo "共發現 " . count($imageUrls) . " 張圖片<br>";
foreach ($imageUrls as $imgUrl) {
// 處理相對路徑
if (strpos($imgUrl, 'http') !== 0) {
$imgUrl = rtrim($targetUrl, '/') . '/' . ltrim($imgUrl, '/');
}
$saved = GrabImage($imgUrl);
echo $saved ? "✅ $imgUrl → $saved<br>" : "❌ $imgUrl 下載失敗<br>";
flush(); // 實時輸出
}
?>
| 功能 | 原代碼 | 增強版 |
|---|---|---|
| HTTP 客戶端 | fopen/fread (無超時、無重定向、無 HTTPS) | cURL (完整支持) |
| 正則提取 | 簡單,易漏匹配 | 兼容單雙引號、無引號、屬性順序 |
| 相對路徑處理 | 無 | 自動補全為絕對 URL |
| 文件命名 | 僅時間戳 | 時間戳 + 隨機數 + 原擴展名/驗證後擴展名 |
| 內容驗證 | 無 | HTTP 200 + Content-Type image/* + 大小限制 |
| 錯誤處理 | 無 | 逐個捕獲、記錄、繼續 |
| 內存控制 | 讀入變量 | cURL 直接寫文件句柄 (大文件建議 CURLOPT_WRITEFUNCTION) |
curl_multi_* 或 GuzzleHttp\Pool 並發 10-50 個連接。resize_image() 生成多規格縮略圖。robots.txt、X-Robots-Tag、站點聲明,尊重爬蟲協議。從簡單腳本到健壯采集器,關鍵在於:異步 HTTP、結構化解析、持久化狀態、合規邊界。