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

PHP 批量下載圖片實作:從基礎爬蟲到生產級下載器

     編輯:PHP 相關知識

批量下載遠端圖片是常見需求。本文從簡單的 file_get_contents 迴圈進階到支援斷點續傳、併發控制、錯誤重試的生產級下載器。

基礎版:簡單迴圈下載

<?php
$imageUrls = [
    'https://example.com/img1.jpg',
    'https://example.com/img2.png',
    // ...
];

set_time_limit(0); // 移除執行時間限制
$imageUrls = array_unique($imageUrls); // 去重

foreach ($imageUrls as $url) {
    $filename = basename($url);
    $content = @file_get_contents($url);
    if ($content !== false) {
        file_put_contents($filename, $content);
        echo "下載成功: $filename\n";
    } else {
        echo "下載失敗: $url\n";
    }
}
?>

進階版:cURL + 錯誤處理 + 進度顯示

<?php
function downloadImage(string $url, string $saveDir = '.', int $timeout = 30): array {
    $filename = basename(parse_url($url, PHP_URL_PATH));
    if (empty($filename) || $filename === '/') {
        $filename = 'image_' . time() . '.jpg';
    }
    $filepath = rtrim($saveDir, '/') . '/' . $filename;

    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_MAXREDIRS => 5,
        CURLOPT_CONNECTTIMEOUT => 10,
        CURLOPT_TIMEOUT => $timeout,
        CURLOPT_SSL_VERIFYPEER => true,
        CURLOPT_USERAGENT => 'Mozilla/5.0 PHP Downloader',
        CURLOPT_WRITEFUNCTION => function($ch, $data) use ($filepath) {
            static $fp = null;
            if ($fp === null) {
                $fp = fopen($filepath, 'wb');
            }
            return fwrite($fp, $data);
        },
    ]);

    $success = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
    curl_close($ch);

    if ($success && $httpCode === 200 && str_starts_with($contentType, 'image/')) {
        return ['success' => true, 'file' => $filepath];
    }
    @unlink($filepath); // 失敗刪除殘檔
    return ['success' => false, 'error' => "HTTP $httpCode: $contentType"];
}

// 批量下載主程式
$urls = array_unique([/* 圖片 URL 陣列 */]);
$results = ['success' => 0, 'failed' => 0];

foreach ($urls as $i => $url) {
    $result = downloadImage($url, 'downloads');
    if ($result['success']) {
        $results['success']++;
        echo "[$i] ✓ {$result['file']}\n";
    } else {
        $results['failed']++;
        echo "[$i] ✗ $url - {$result['error']}\n";
    }
    usleep(100000); // 禮貌延遲 0.1 秒
}

echo "完成: 成功 {$results['success']}, 失敗 {$results['failed']}\n";
?>

生產級增強功能

功能實作方案
斷點續傳CURLOPT_RESUME_FROM + Range Header
併發下載curl_multi_* 或 parallel 擴展 / Swoole
重試機制指數退避:1s, 2s, 4s, 8s... 最大 3 次
去重複檔MD5/SHA256 檢查已下載檔案
頻率限制Token Bucket / Leaky Bucket 演算法
進度條CURLOPT_PROGRESSFUNCTION + CLI 進度顯示

CSS 圖片提取實戰

<?php
function extractImagesFromCss(string $cssContent): array {
    // 匹配 url(...) 格式,支援單雙引號、無引號
    preg_match_all('/url\(\s*[\'"]?([^\'")]+)[\'"]?\s*\)/i', $cssContent, $matches);
    return array_unique($matches[1]);
}

$css = file_get_contents('https://example.com/style.css');
$imageUrls = extractImagesFromCss($css);
// 轉換相對路徑為絕對 URL
$baseUrl = 'https://example.com/';
$imageUrls = array_map(fn($u) => $u[0] === '/' ? $baseUrl . ltrim($u, '/') : $baseUrl . $u, $imageUrls);
?>

法律與道德提醒

  • 遵守 robots.txt 與網站服務條款
  • 設定合理的 User-Agent 標識爬蟲身分
  • 控制請求頻率(建議 ≥ 1 秒/請求)
  • 僅下載公開授權或合法授權的圖片資源
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved