PHPHtmlParser是一款简单灵活的HTML解析器,允许您使用任何CSS选择器来选取标签,类似于jQuery的方式。其目标是为那些需要快速简便地抓取HTML(无论是否合法)的工具提供帮助!
安装 通过Composer安装最新版本。
$ composer require paquettg/php-html-parser
本包可在Packagist上找到,并推荐通过Composer加载。我们支持PHP 7.2、7.3和7.4。
基本用法 在测试目录中,您可以找到关于如何使用DOM解析器及其各部分(很可能您永远不会直接触碰)的许多示例。这些测试使用PHPUnit编写,非常简短,每个只有几行,是开始学习的好地方。即便如此,我仍会展示一些如何使用该包的基本例子。以下是一个非常简单的使用示例:
// 假设您已通过Composer安装:
require "vendor/autoload.php";
use PHPHtmlParser\Dom;
$dom = new Dom;
$dom->loadStr('嘿,兄弟,点击这里
:)
');
$a = $dom->find('a')[0];
echo $a->text; // 输出 "点击这里"
这段代码将输出“点击这里”。简单吧?从DOM获取相同结果的方式有很多种,比如$dom->getElementsByTagName(‘a’)[0]或$dom->find(‘a’, 0),更多用法可参考测试案例或源码本身。
支持PHP Html Parser的资金赞助 获取受支持的Monolog,并通过Tidelift订阅资助该项目。
Tidelift为您的应用所依赖的开源依赖项提供了商业级别的支持与维护。节省时间,降低风险,改善代码健康状况,同时支持您实际使用的依赖项的维护者。
加载文件 您也可以无缝地将文件加载到DOM中而不是字符串,这更方便,也是我认为大多数开发者加载HTML的方式。以下示例源自我们的测试,使用了其中的”big.html”文件。
// 假设您已通过Composer安装:
require "vendor/autoload.php";
use PHPHtmlParser\Dom;
$dom = new Dom;
$dom->loadFromFile('tests/data/big.html');
$contents = $dom->find('.content-border');
echo count($contents); // 输出 10
foreach ($contents as $content) {
// 获取类属性
$class = $content->getAttribute('class');
// 对HTML进行处理
$html = $content->innerHtml;
// 或进一步细化查找
$child = $content->firstChild();
$sibling = $child->nextSibling();
}
此例从”big.html”(一个真实的在线页面)加载HTML,获取所有.content-border类以进行处理,并展示了可以对节点执行的一些操作,但并非节点可用方法的完整列表。
加载URL 加载URL的方式与从文件加载HTML非常相似。
// 假设您已通过Composer安装:
require "vendor/autoload.php";
use PHPHtmlParser\Dom;
$dom = new Dom;
$dom->loadFromUrl('http://google.com');
$html = $dom->outerHtml;
// 或者
$dom->loadFromUrl('http://google.com');
$html = $dom->outerHtml; // 结果与第一个示例相同
默认情况下,loadFromUrl使用\Psr\Http\Client\ClientInterface的一个实现来执行HTTP请求,并使用一个默认的\Psr\Http\Message\RequestInterface实现来构造请求体。您可以轻松实现自己的客户端或请求版本,以便在使用loadFromUrl时使用自定义的HTTP连接。
// 假设您已通过Composer安装:
require "vendor/autoload.php";
use PHPHtmlParser\Dom;
use App\Services\MyClient;
$dom = new Dom;
$dom->loadFromUrl('http://google.com', null, new MyClient());
$html = $dom->outerHtml;
只要客户端对象正确实现了接口,它就会使用那个对象来获取URL的内容。
加载字符串 直接加载字符串也非常简单。
// 假设您已通过Composer安装:
require "vendor/autoload.php";
use PHPHtmlParser\Dom;
$dom = new Dom;
$dom->loadStr('字符串');
$html = $dom->outerHtml;
配置选项 您还可以设置影响解析引擎行为的解析选项。可以通过Dom对象的setOptions方法设置全局选项数组,或者将选项作为load方法的额外(可选)参数添加来设定实例特定的选项。
// 假设您已通过Composer安装:
require "vendor/autoload.php";
use PHPHtmlParser\Dom;
use PHPHtmlParser\Options;
$dom = new Dom;
$dom->setOptions(
// 这被设置为全局选项级别。
(new Options())
->setStrict(true)
);
$dom->loadFromUrl('http://google.com',
(new Options())->setWhitespaceTextNode(false) // 只在此加载中适用。
);
$dom->loadFromUrl('http://gmail.com'); // 将不会设置whitespaceTextNode为false。
目前,我们支持12个配置选项。
严格模式 默认关闭,当发现HTML不严格合规(所有标签都必须有闭合标签,没有无值属性等)时抛出StrictException。
空白文本节点 默认开启,告诉解析器保存即使是空内容(仅空白字符)的文本节点。设置为假则忽略文档中的所有仅空白文本节点。
强制编码 默认为空,用于指定读取内容和返回内容时使用的字符集。若设为null,则尝试从给定字符串的内容中推断编码。
其余选项还包括清理输入阶段控制(cleanupInput)、移除脚本和样式标签、保留换行符、去除双倍空格、移除Smarty脚本以及HTML特殊字符解码等功能,它们各自都有详细的描述和默认值,使用户能根据需求定制解析过程。
静态外观(Static Facade) 您还可以为 Dom 对象安装一个静态外观。
PHPHtmlParser\StaticDom::mount();
Dom::loadFromFile('tests/big.html');
$objects = Dom::find('.content-border');
上述 PHP 代码块与第一个示例执行相同的操作,但使用了静态外观,该外观支持在 Dom 对象中找到的所有公共方法。
修改 DOM 您可以随时修改通过任何加载方法创建的 DOM。要更改节点的属性,只需调用 setAttribute 方法。
use PHPHtmlParser\Dom;
$dom = new Dom;
$dom->loadStr('Hey bro, click here
:)
');
$a = $dom->find('a')[0];
$a->setAttribute('class', 'foo');
echo $a->getAttribute('class'); // "foo"
您还可以直接获取 PHPHtmlParser\Dom\Tag 类并按需操作它。
use PHPHtmlParser\Dom;
$dom = new Dom;
$dom->loadStr('Hey bro, click here
:)
');
/** @var Dom\Node\AbstractNode $a */
$a = $dom->find('a')[0];
$tag = $a->getTag();
$tag->setAttribute('class', 'foo');
echo $a->getAttribute('class'); // "foo"
也可以从树中删除节点。只需对任何节点调用 delete 方法即可将其从树中移除。重要的是要注意,在从 DOM 中删除节点后应将其取消设置,否则它仍会占用内存。
use PHPHtmlParser\Dom;
$dom = new Dom;
$dom->loadStr('Hey bro, click here
:)
');
/** @var Dom\Node\AbstractNode $a */
$a = $dom->find('a')[0];
$a->delete();
unset($a);
echo $dom; // 'Hey bro,
:)
';
您可以轻松地修改 TextNode 对象的文本。请注意,如果您设置了编码,新文本将使用现有编码进行编码。
use PHPHtmlParser\Dom;
$dom = new Dom;
$dom->loadStr('Hey bro, click here
:)
');
/** @var Dom\Node\InnerNode $a */
$a = $dom->find('a')[0];
$a->firstChild()->setText('biz baz');
echo $dom; // 'Hey bro, biz baz
:)
'