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

PHP GD 庫批量下載網頁所有圖片:正則提取 URL + 串流儲存完整實作

     編輯:PHP 綜合知識

需求:輸入網頁 URL,自動解析所有 <img> 標籤的 src,處理相對/絕對路徑,去重下載至本地目錄。

核心流程

  1. 取得網頁 HTML 內容(支援代理、超時)
  2. 正則提取所有 src 屬性值
  3. 相對路徑轉絕對路徑(依 base_url 或網域)
  4. 去重(array_unique)
  5. 逐張下載:
    • getimagesize() 偵測 MIME/類型
    • 依類型選對應 GD 函式(imagecreatefromjpeg 等)
    • imagejpeg/png/gif/... 儲存,可指定品質

完整類別實作

<?php
class ImageDownloader {
    private $saveDir;
    private $baseUrl;
    private $domain;

    public function __construct($pageUrl, $saveDir = './images/') {
        $this->saveDir = rtrim($saveDir, '/') . '/';
        if (!is_dir($this->saveDir)) mkdir($this->saveDir, 0755, true);

        $parsed = parse_url($pageUrl);
        $this->domain = $parsed['host'] ?? '';
        $this->baseUrl = substr($pageUrl, 0, strrpos($pageUrl, '/') + 1);
    }

    public function downloadAll() {
        $ctx = stream_context_create(['http'=>['timeout'=>10,'request_fulluri'=>true]]);
        $html = @file_get_contents($this->baseUrl, false, $ctx);
        if (!$html) return ['error'=>'無法取得網頁內容'];

        preg_match_all('/<img[^>]+src=["\']([^"\']+)["\']/i', $html, $m);
        $urls = array_unique($m[1] ?? []);

        $results = [];
        foreach ($urls as $url) {
            $absUrl = $this->toAbsolute($url);
            $results[] = $this->downloadOne($absUrl);
        }
        return $results;
    }

    private function toAbsolute($url) {
        if (stripos($url, 'http') === 0) return $url;
        if ($url[0] === '/') return "https://{$this->domain}{$url}";
        return $this->baseUrl . $url;
    }

    private function downloadOne($url) {
        $info = @getimagesize($url);
        if (!$info) return ['url'=>$url, 'status'=>'invalid_image'];

        $mime = $info['mime'];
        $extMap = [
            'image/jpeg' => ['func'=>'imagecreatefromjpeg', 'save'=>'imagejpeg', 'ext'=>'jpg', 'quality'=>90],
            'image/png'  => ['func'=>'imagecreatefrompng',  'save'=>'imagepng',  'ext'=>'png'],
            'image/gif'  => ['func'=>'imagecreatefromgif',  'save'=>'imagegif',  'ext'=>'gif'],
            'image/webp' => ['func'=>'imagecreatefromwebp', 'save'=>'imagewebp', 'ext'=>'webp'],
        ];
        $cfg = $extMap[$mime] ?? $extMap['image/jpeg'];

        $img = @$cfg['func']($url);
        if (!$img) return ['url'=>$url, 'status'=>'gd_load_failed'];

        $filename = basename(parse_url($url, PHP_URL_PATH));
        $filename = pathinfo($filename, PATHINFO_FILENAME) . '.' . $cfg['ext'];
        $filepath = $this->saveDir . $filename;

        $saveFunc = $cfg['save'];
        $quality = $cfg['quality'] ?? null;
        $ok = $quality ? $saveFunc($img, $filepath, $quality) : $saveFunc($img, $filepath);
        imagedestroy($img);

        return ['url'=>$url, 'path'=>$filepath, 'status'=>$ok ? 'success' : 'save_failed'];
    }
}

// 使用範例
$downloader = new ImageDownloader('https://example.com/article', './downloads/');
$results = $downloader->downloadAll();
print_r($results);

關鍵技術點

環節技術說明
HTML 取得stream_context_create統一控制 timeout、proxy、User-Agent
正則提取/<img[^>]+src=["\']([^"\']+)["\']/i支援單/雙引號、屬性順序不固定
相對路徑轉換parse_url + 判斷處理 /path、path、https://... 三種
類型偵測getimagesize()回傳 mime、寬高,比單看副檔名可靠
GD 載入/儲存imagecreatefrom* / image*統一轉檔、可調品質、支援主流格式

避坑指南

  • 防盜鏈:部分站檢查 Referer,Context 加 'header'=>"Referer: {$pageUrl}\r\n"
  • 大圖記憶體:GD 載入解碼後佔記憶體 = 寬×高×4 bytes,超大圖(>4000px)易 OOM,建議先 getimagesize 判斷尺寸,過大跳過或用 Imagick 串流處理。
  • 並發下載:單執行緒慢,可用 curl_multi、Guzzle Promise 或 Swoole 協程並發。
  • 版權合規:僅供學習/授權場景,勿濫用爬取受保護圖片。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved