simple html dom 不支持 composer 安装,因其未发布到 packagist 且无 composer.json;第三方镜像已停更、不兼容 php 8+,易报 mb_convert_encoding 或 undefined index 错误;推荐改用 symfony/dom-crawler + symfony/css-selector。

直接用 symfony/dom-crawler + symfony/css-selector,别碰 simple_html_dom —— 后者不支持 Composer、PHP 8+ 下大概率崩,且没有维护。
为什么不能用 simple_html_dom?
它没上 Packagist,没 composer.json,强行 composer require sunra/php-simple-html-dom-parser 会报 Could not find package;就算绕过装上了,运行时极可能触发:
Fatal error: Uncaught Error: Call to undefined function mb_convert_encoding()-
Undefined index: href类错误(因内部用正则硬解析,非真实 DOM 树) - PHP 8.2+ 下因严格类型检查直接中断
它的原始项目托管在 SourceForge,最后一次更新是 2016 年,所有镜像 fork 都已停更。
正确安装:两个包必须一起装
dom-crawler 本身不带 CSS 选择器支持,只提供基础 DOM 导航;要写 $crawler->filter('a[href]') 这类代码,css-selector 是硬依赖:
composer require symfony/dom-crawler symfony/css-selector
不装 symfony/css-selector 会导致 filter() 方法抛出 InvalidArgumentException,错误信息类似:The "css-selector" component is required to use the filter() method。
注意:不需要手动 require_once 或配置 autoload —— Composer 自动处理。
解析 HTML 片段时容易漏掉的关键参数
如果你传入的是纯 HTML 片段(比如 <div class="item">xxx</div>),DOMDocument 默认会自动补全成完整文档结构(加 ),导致节点层级错位。解决方法是显式传入 libxml 选项:
$crawler = new \Symfony\Component\DomCrawler\Crawler(); $crawler->addHtmlContent($html, 'text/html', LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
这两个 flag 的作用:
-
LIBXML_HTML_NOIMPLIED:禁用自动添加 -
LIBXML_HTML_NODEFDTD:跳过 DTD 声明插入(避免解析失败)
漏掉它们,$crawler->filter('.item') 可能返回空,而你查半天发现实际节点被套进了自动生成的 里。
filter() 和 filterXPath() 性能与可读性怎么选?
两者底层都走 DOMXPath,性能差异可忽略,但使用场景明确:
- 日常开发优先用
filter('div.post h2.title')—— 可读性强,CSS 语法直觉匹配前端经验 - 需要跨命名空间、处理 XML 或复杂逻辑(如“第 3 个子元素中包含文本‘error’的
<p></p>”)才用filterXPath()
注意:filterXPath() 不依赖 css-selector 包,但 XPath 表达式必须严格符合规范,比如 //div[@class="title"] 中的引号必须是英文双引号,单引号会静默失败。
真正容易被忽略的是:当你从远程 URL 加载 HTML(比如用 Guzzle 获取响应体),必须确保响应内容是 UTF-8 编码;否则中文字符会变成乱码或节点提取为空 —— DOMDocument 对编码极其敏感,它不自动检测 meta charset。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











