前端開發中常需要從現有網站提取 CSS 背景圖片。手動下載效率低且易出錯,本文提供一個功能完整的 PHP 命令列工具,支援遠端 CSS 解析、相對/絕對路徑處理、圖片去重與批量下載。
<?php
/**
* CSS 背景圖片批量下載器
* @author 開發者
* @usage php cssImages.php [類型] [CSS路徑] [儲存目錄]
* 類型: 0=遠端, 1=本地
* 範例: php cssImages.php 0 https://example.com/style.css \images\
*/
set_time_limit(0);
error_reporting(E_ERROR);
// 參數檢查
if ($argc < 4) {
print_r("
+-------------------------------------------------+
Usage: php {$argv[0]} css路徑類型(0遠端/1本地) css文件路徑 圖片保存目錄
Example:
php {$argv[0]} 0 https://www.xxx.com/index.css \\images\\
+-------------------------------------------------+
");
exit();
}
$type = $argv[1];
$cssPath = $argv[2];
$saveDir = $argv[3];
// 全域變數
$host = '';
$savePath = '';
// 遠端 CSS 處理
if ($type == 0) {
$host = getParse($cssPath, 'host');
$savePath = getSavePath($saveDir);
$images = getCssImagesArray($cssPath);
$imageUrls = getImagesLinks($images, $cssPath);
imagesDowner($imageUrls);
}
// 本地 CSS 處理(預留擴展)
if ($type == 1) {
// 本地檔案處理邏輯
echo "本地模式暫未實現\n";
}
/**
* 解析 CSS 檔案,提取所有 url() 內的圖片路徑
*/
function getCssImagesArray($cssPath) {
$cssContent = file_get_contents($cssPath);
$images = array();
// 匹配 url(路徑) 模式,支援單雙引號或無引號
preg_match_all("|url\((['\"]?)(.+?)\\1\)|i", $cssContent, $matches);
return $matches[2]; // 返回捕獲組 2(實際路徑)
}
/**
* 解析 CSS 路徑,獲取非檔名部分的目錄路徑
*/
function getNocssPath($path) {
global $host;
$tempPath = explode('/', $path);
$tempLinkImages = '';
// 重構目錄路徑(排除協定、主機、檔名)
for ($i = 1; $i < (count($tempPath) - 1); $i++) {
$tempLinkImages .= $tempPath[$i] . '/';
}
return $host . $tempLinkImages;
}
/**
* 根據 CSS 路徑解析圖片完整 URL
*/
function getImagesLinks($imagesArray, $cssLink) {
global $host;
$urlImages = array();
foreach ($imagesArray as $key => $value) {
$value = trim($value);
if (pathCheck($value)) {
// 絕對路徑(以 / 開頭)
$fullUrl = $host . $value;
if (!in_array($fullUrl, $urlImages)) {
$urlImages[$key] = $fullUrl;
}
} else {
// 相對路徑
$basePath = getNocssPath(getParse($cssLink, 'path'));
$fullUrl = $basePath . $value;
if (!in_array($fullUrl, $urlImages)) {
$urlImages[$key] = $fullUrl;
}
}
}
return $urlImages;
}
/**
* 批量下載圖片
*/
function imagesDowner($urlImages) {
foreach ($urlImages as $key => $value) {
// 清理 URL
$cleanUrl = str_replace('//', '/', $value);
$cleanUrl = str_replace('"', '', $cleanUrl);
$cleanUrl = str_replace("'", '', $cleanUrl);
$cleanUrl = 'https://' . ltrim($cleanUrl, 'https://');
$filename = basename($cleanUrl);
if (grabImage($cleanUrl, $filename)) {
print_r($filename . " 文件下載成功\n");
} else {
print_r($filename . " 下載失敗\n");
}
}
}
/**
* 判斷是否為絕對路徑
*/
function pathCheck($imageUrl) {
return preg_match('|^/|', $imageUrl) ? true : false;
}
/**
* 下載單張圖片
*/
function grabImage($url, $filename) {
global $savePath;
if (empty($url)) return false;
// 驗證副檔名
$ext = strrchr($url, '.');
$allowedExt = array('.gif', '.jpg', '.jpeg', '.bmp', '.png', '.webp', '.svg');
if (!in_array(strtolower($ext), $allowedExt)) {
return false;
}
if (empty($filename)) return false;
// 使用 readfile 獲取遠端內容
ob_start();
if (readfile($url)) {
$imgData = ob_get_contents();
ob_end_clean();
$size = strlen($imgData);
} else {
ob_end_clean();
return false;
}
// 寫入本地檔案
$filePath = $savePath . $filename;
if (($fp = fopen($filePath, 'w')) && fwrite($fp, $imgData)) {
fclose($fp);
return true;
}
return false;
}
/**
* 獲取本地儲存絕對路徑
*/
function getSavePath($savePath) {
$fullPath = dirname(__FILE__) . $savePath;
// 自動建立目錄
if (!is_dir($fullPath)) {
mkdir($fullPath, 0755, true);
}
return $fullPath;
}
/**
* 解析 URL 組件
*/
function getParse($url, $type) {
$parsed = parse_url($url);
$value = isset($parsed[$type]) ? $parsed[$type] : '';
// host 自動補全結尾斜線
if ($type === 'host' && $value) {
$value = rtrim($value, '/') . '/';
}
return $value;
}
?>
| 參數 | 說明 | 範例 |
|---|---|---|
| 類型 | 0=遠端 CSS, 1=本地 CSS | 0 |
| CSS 路徑 | 遠端完整 URL 或本地檔案路徑 | https://example.com/css/style.css |
| 儲存目錄 | 相對於腳本目錄的儲存路徑 | \images\ |
# Windows
php.exe cssImages.php 0 https://www.example.com/css/main.css \images\
# Linux/Mac
php cssImages.php 0 https://www.example.com/css/main.css /images/
原版 |url\((.+)\)|i 存在貪婪匹配問題,改進版使用 |url\((['\"]?)(.+?)\\1\)|i:
url(image.png)、url('image.png')、url("image.png").+? 避免跨多個 url() 捕獲\\1 確保引號成對/ 開頭 → 直接拼接主機名in_array 檢查避免重複下載readfile() + 輸出緩衝區獲取二進位內容curl_multi 或 pthreads 實現多執行緒下載robots.txt 與服務條款本工具提供了從 CSS 提取並下載背景圖片的完整解決方案,核心邏輯涵蓋 CSS 解析、路徑解析、去重、下載等關鍵環節。程式碼結構清晰,易於擴展與維護,可作為前端資源遷移、設計素材收集等場景的實用工具。