在 CMS、部落格、商品列表中,常需自動抓取內文第一張圖作為縮圖。本文整理四種正則寫法,並提供預設圖片 fallback 機制。
$content = $article['content'];
// 階段 1:匹配所有
標籤(自閉合或雙標籤)
$imgTagPattern = '~
]+>~i';
preg_match_all($imgTagPattern, $content, $matches);
$allImages = $matches[0];
if (!empty($allImages)) {
// 階段 2:從第一個 img 標籤提取 src
$srcPattern = '/src=["\']([^"\']+\.(?:jpg|jpeg|gif|png|webp))["\']/i';
preg_match($srcPattern, $allImages[0], $srcMatch);
$firstImg = $srcMatch[1] ?? null;
}
echo $firstImg ? "
" : "無圖片";
$pattern = '/
]+src=["\']([^"\']+\.(?:jpg|jpeg|gif|png|webp))["\'][^>]*>/i';
preg_match($pattern, $content, $match);
$firstImg = $match[1] ?? 'images/nopic.jpg'; // 預設圖
echo $firstImg;
$pattern = '/
]*src\s*=\s*["\']?([^"\'>\s]+\.(?:jpg|jpeg|gif|png|webp))["\']?/i';
preg_match($pattern, $content, $match);
$firstImg = $match[1] ?? 'images/nopic.jpg';
libxml_use_internal_errors(true);
$dom = new DOMDocument();
$dom->loadHTML('' . $content); // 修正編碼
libxml_clear_errors();
$images = $dom->getElementsByTagName('img');
$firstImg = 'images/nopic.jpg';
foreach ($images as $img) {
$src = $img->getAttribute('src');
if ($src && preg_match('/\.(jpg|jpeg|gif|png|webp)$/i', $src)) {
$firstImg = $src;
break;
}
}
echo $firstImg;
| 方法 | 優點 | 缺點 | 建議場景 |
|---|---|---|---|
| 正則兩階段 | 邏輯清晰 | 效能較差,兩次掃描 | 教學、簡單專案 |
| 單一正則 | 速度快 | 正則複雜,難維護 | 高流量、格式固定 |
| DOMDocument | 標準、容錯高、支援巢狀/屬性順序不固定 | 記憶體較大、稍慢 | 內容來源不可控、企業級專案 |
function getFirstImage(string $html, string $default = 'images/nopic.jpg'): string {
// 優先用 DOMDocument
if (extension_loaded('dom')) {
libxml_use_internal_errors(true);
$dom = new DOMDocument();
$dom->loadHTML('' . $html);
foreach ($dom->getElementsByTagName('img') as $img) {
$src = $img->getAttribute('src');
if ($src && preg_match('/\.(jpg|jpeg|gif|png|webp)$/i', $src)) {
return $src;
}
}
}
// Fallback 正則
if (preg_match('/
]*src\s*=\s*["\']?([^"\'>\s]+\.(?:jpg|jpeg|gif|png|webp))["\']?/i', $html, $m)) {
return $m[1];
}
return $default;
}
根據專案規模與內容來源選擇適合方案,並務必加上預設圖片,避免版面崩壞。