在 CMS 系統、富文本編輯器內容處理、數據遷移等場景中,常需從 HTML 字符串中提取或修改 `` 標籤的屬性(如 `src`、`width`、`height`、`style` 等)。本文系統梳理基於 PCRE 正則表達式的處理方案,並針對常見陷阱提供最佳實踐。
$pattern = '/<img\s+[^>]*?src\s*=\s*([\'"])(.*?)\\1[^>]*?\/?\s*>/i';
$pattern = '/<img[^>]*?src\s*=\s*([\'"])(.*?)\\1/i';
使用 `preg_match()` 時,`$matches[2]` 即為 URL 值。
$pattern = '/<img[^>]*?width\s*=\s*([\'"]?)(\d+)\\1/i';
支持有引號、無引號兩種寫法,`$matches[2]` 為數值。
<?php
$html = '<p>內容</p> <img src="a.jpg" width="100"> <div>其他</div> <img src=\'b.png\' height=50>';
$pattern = '/<img\s+([^>]*?src\s*=\s*([\'"])(.*?)\\2[^>]*?)\/?\s*>/is';
preg_match_all($pattern, $html, $matches, PREG_SET_ORDER);
foreach ($matches as $m) {
$fullTag = $m[0];
$src = $m[3];
// 進一步解析其他屬性...
echo "標籤: $fullTag\n圖片: $src\n---\n";
}
?>
需求:將 `src="upload/images/xxx.jpg"` 改為 `src="upload/_thumbs/images/xxx.jpg"`,並移除 `width`/`height` 屬性(避免縮略圖變形)。
<?php
$html = '<img src="upload/images/a.jpg" width="200" height="150">
<img src="upload/images/b.png" style="float:left">';
// 方案 A:分步處理(推薦,可讀性強)
// 1. 替換 src 路徑
$html = preg_replace_callback(
'/(<img[^>]*?src\s*=\s*([\'"]))(.*?)\\2/i',
function ($m) {
$prefix = $m[1];
$quote = $m[2];
$url = $m[3];
// 路徑轉換邏輯
$newUrl = preg_replace('/(upload\/)images\//', '$1_thumbs/images/', $url);
return $prefix . $newUrl . $quote;
},
$html
);
// 2. 移除 width/height 屬性
$html = preg_replace('/\s(width|height)\s*=\s*([\'"]?)\d+\\2/i', '', $html);
echo $html;
// 輸出:
// <img src="upload/_thumbs/images/a.jpg">
// <img src="upload/_thumbs/images/b.png" style="float:left">
?>
<?php
$html = preg_replace_callback(
'/(<img[^>]*?)(?:\salt\s*=\s*([\'"])(.*?)\\2)?([^>]*>)/i',
function ($m) {
// 若已有 alt 則保持,否則添加默認值
$alt = $m[3] ?? '圖片說明';
return $m[1] . ' alt="' . htmlspecialchars($alt) . '"' . $m[4];
},
$html
);
?>
$dom = new DOMDocument();
$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
foreach ($dom->getElementsByTagName('img') as $img) {
$src = $img->getAttribute('src');
$img->setAttribute('src', convertToThumb($src));
$img->removeAttribute('width');
$img->removeAttribute('height');
}
$newHtml = $dom->saveHTML();
| 場景 | 推薦方案 | 理由 |
|---|---|---|
| 提取單頁少量圖片信息 | 正則 `preg_match_all` | 代碼簡潔、無依賴、速度快 |
| 批量修改屬性、需輸出合法 HTML | DOMDocument | 自動處理實體編碼、標籤閉合、嵌套結構 |
| 超大 HTML 文檔(>1MB) | 流式解析器 (XMLReader) | 內存佔用恆定、不會載入整個文檔 |
正則表達式在處理 `` 標籤屬性提取與簡單替換時極為高效,但需嚴格控制適用邊界。核心原則:只處理扁平化、結構可預期的 HTML 片段。涉及結構變更、實體編碼、嵌套標籤時,請毫不猶豫選擇 `DOMDocument`。兩者結合,可構建健壯的富文本圖片處理流程。