爬蟲、內容遷移、編輯器圖片上傳等場景常需從 HTML 中提取 <img> 的 src 屬性。本文系統整理正則寫法演進、零寬斷言限制、相對路徑轉絕對、無副檔名圖片處理等實戰技巧。
| 需求 | 正則 | 說明 |
|---|---|---|
| 最簡單 | /src=["']([^"']+)["']/i | 匹配所有 src,含 JS/CSS/iframe,誤判率高 |
| 限定 img 標籤 | /<img[^>]+src=["']([^"']+)["']/i | 較精確,但屬性順序不固定可能漏匹 |
| 容忍屬性順序 | /<img\b[^>]*\bsrc=["']([^"']+)["']/i | 推薦通用寫法,\b 確保單字邊界 |
| 提取 src 並保留標籤上下文 | /<img(\s[^>]*)?src=["']([^"']+)["']/i | 捕獲組 2 為網址,組 1 為其他屬性 |
function extractImageUrls(string $html): array {
$pattern = '/<img\b[^>]*\bsrc=["\']([^"\']+)["\']/i';
preg_match_all($pattern, $html, $matches);
return $matches[1] ?? []; // 捕獲組 1 為網址
}
$html = '<img src="photo.jpg" alt="test"> <img data-src="lazy.png" src="real.png">';
print_r(extractImageUrls($html));
// Array ( [0] => photo.jpg [1] => real.png )
function toAbsoluteUrls(array $urls, string $baseUrl): array {
$base = rtrim($baseUrl, '/') . '/';
return array_map(function($url) use ($base) {
if (preg_match('/^https?:\/\//i', $url)) return $url; // 已是絕對
if (str_starts_with($url, '//')) return 'https:' . $url; // 協議相對
if (str_starts_with($url, '/')) {
$parsed = parse_url($base);
return $parsed['scheme'] . '://' . $parsed['host'] . $url; // 根相對
}
return $base . $url; // 同目錄相對
}, $urls);
}
正則不可依賴副檔名過濾。直接提取 src 值,後續用 getimagesize() 或 HTTP HEAD 檢查 Content-Type: image/... 驗證。
PHP PCRE 要求 lookbehind 固定長度,故 (?<=img.+?src=") 會報錯。解決:改用捕獲組 (src=["']([^"']+)["']) 取組 2,或用 \K 重設匹配起點:/<img\b[^>]*\bsrc=["']\K[^"']+/i。
$pattern = '/<img\b[^>]*\bsrc=(["\']?)([^"\'>\s]+)\1/i';
// \1 反向引用確保首尾引號一致,組 2 為網址
class ImageExtractor {
public static function extract(string $html, string $baseUrl = ''): array {
$urls = [];
preg_match_all('/<img\b[^>]*\bsrc=(["\']?)([^"\'>\s]+)\1/i', $html, $m);
$urls = $m[2] ?? [];
if ($baseUrl) $urls = self::toAbsolute($urls, $baseUrl);
return array_values(array_unique($urls));
}
private static function toAbsolute(array $urls, string $base): array { ... }
}
核心正則 /<img\b[^>]*\bsrc=(["\']?)([^"\'>\s]+)\1/i 兼容引號、屬性順序、無引號情況。提取後務必轉絕對路徑並驗證 Content-Type。避免用零寬斷言、副檔名過濾等脆弱寫法。大規模爬蟲建議改用 DOMDocument 或 symfony/dom-crawler 解析器,健壯度遠超正則。