簡介
simple_html_dom 是 PHP 知名的 HTML 解析庫,提供類 jQuery 的選擇器語法,支援斷裂/不標準 HTML 容錯解析,適合爬蟲、內容擷取、頁面清洗。
安裝與載入
# Composer 安裝 (推薦)
composer require sunra/php-simple-html-dom-parser
# 或下載單檔版 simple_html_dom.php 放入專案
require_once 'simple_html_dom.php';
核心物件建立
<?php
use Sunra\PhpSimple\HtmlDomParser;
// 從 URL 載入
$dom = HtmlDomParser::file_get_html('https://example.com');
// 從字串載入
$html = '<div id="box"><p>Hello</p></div>';
$dom = HtmlDomParser::str_get_html($html);
// 手動建立並載入
$dom = new simple_html_dom();
$dom->load($html);
選擇器 find() 完整語法
| 語法 | 說明 | 範例 |
| 標籤名 | 選取所有指定標籤 | $dom->find('div') |
.class | 選取 class | $dom->find('.item') |
#id | 選取 id | $dom->find('#main') |
[attr] | 擁有屬性 | $dom->find('img[alt]') |
[attr=value] | 屬性等於值 | $dom->find('a[href="/login"]') |
[attr^=value] | 屬性開頭 | $dom->find('a[href^="https"]') |
[attr$=value] | 屬性結尾 | $dom->find('img[src$=".png"]') |
[attr*=value] | 屬性包含 | $dom->find('div[class*="box"]') |
| 後代組合 | 空格分隔 | $dom->find('ul li a') |
| 子元素 | > | $dom->find('ul > li') |
| 相鄰兄弟 | + | $dom->find('h2 + p') |
| 多選擇器 | , 分隔 | $dom->find('h1, h2, h3') |
| 第 N 個 | 第 2 參數 | $dom->find('div', 0) (第一個), -1 (最後) |
元素屬性與內容存取
<?php
$element = $dom->find('#content', 0);
// 標籤名
echo $element->tag; // 'div'
// 完整外層 HTML(含自身標籤)
echo $element->outertext; // '<div id="content">...</div>'
// 內部 HTML(不含自身標籤)
echo $element->innertext; // '...內容...'
// 純文字(去除所有標籤)
echo $element->plaintext; // '純文字內容'
// 取得/設定屬性
echo $element->href; // 取得 href
echo $element->id; // 取得 id
$element->class = 'new-class'; // 設定 class
$element->setAttribute('data-id', '123');
// 移除屬性
$element->removeAttribute('style');
DOM 遍歷方法
| 方法 | 說明 |
children([$index]) | 子元素陣列,或指定索引 |
parent() | 父元素 |
first_child() | 第一個子元素 |
last_child() | 最後一個子元素 |
next_sibling() | 下一個兄弟元素 |
prev_sibling() | 上一個兄弟元素 |
<?php
// 遍歷所有子元素
foreach ($element->children() as $child) {
echo $child->tag . ': ' . $child->plaintext . "\n";
}
// 精確定位:#div1 → 第2個子元素 → 第2個子元素 → 第3個子元素
echo $dom->find('#div1', 0)->children(1)->children(1)->children(2)->id;
實戰範例:文章列表擷取
<?php
$dom = HtmlDomParser::file_get_html('https://blog.example.com/list');
$articles = [];
foreach ($dom->find('article.post') as $post) {
$item = [
'title' => $post->find('h2.title a', 0)->plaintext,
'link' => $post->find('h2.title a', 0)->href,
'summary' => $post->find('.excerpt', 0)->plaintext,
'date' => $post->find('time', 0)->datetime,
'author' => $post->find('.author-name', 0)->plaintext,
'tags' => [],
];
foreach ($post->find('.tags a') as $tag) {
$item['tags'][] = $tag->plaintext;
}
$articles[] = $item;
}
print_r($articles);
修改 HTML 並輸出
<?php
$html = '<div id="hello">Hello</div><div id="world">World</div>';
$dom = HtmlDomParser::str_get_html($html);
// 修改第 2 個 div 的 class
$dom->find('div', 1)->class = 'bar';
// 修改 #hello 的內部內容
$dom->find('#hello', 0)->innertext = 'foo';
// 輸出完整 HTML
echo $dom->save();
// 或 echo $dom; // __toString()
// 輸出:
// <div id="hello">foo</div><div id="world" class="bar">World</div>
記憶體管理
<?php
// 大型文件解析後釋放記憶體
$dom = HtmlDomParser::file_get_html('large_page.html');
// ... 處理 ...
$dom->clear(); // 避免循環引用導致記憶體洩漏
unset($dom);
常見問題與替代方案
| 問題 | 解決/替代 |
| 大文件記憶體耗盡 | 使用 XMLReader (SAX 流式解析) 或 Masterminds/HTML5 |
| 惡劣 HTML 解析錯誤 | 預處理 tidy、Masterminds/HTML5 (HTML5 標準解析器) |
| 效能不足 | wa72/htmlpagedom、symfony/dom-crawler + css-selector |
| 需 XPath 支援 | DOMDocument + DOMXPath (內建) |
內建 DOMDocument 替代方案(無需外部依賴)
<?php
$dom = new DOMDocument();
libxml_use_internal_errors(true); // 抑制錯誤警告
$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
libxml_clear_errors();
$xpath = new DOMXPath($dom);
$nodes = $xpath->query('//div[@class="item"]//a');
foreach ($nodes as $node) {
echo $node->textContent . ' -> ' . $node->getAttribute('href') . "\n";
}
- 上一篇文章: PHP PKI 加密技術(OpenSSL)完整實作指南
- 下一篇文章: PHP cURL 介接 API 完整指南:從基礎到進階實戰
Copyright ©
程式碼之家 All Rights Reserved