wa72 / htmlpagedom
基于jQuery的DOM操作扩展,用于Symfony的Crawler
Requires
- php: ^8.0
- ext-dom: *
- ext-libxml: *
- symfony/css-selector: ^6.0 || ^7.0
- symfony/dom-crawler: ^6.0 || ^7.0
- symfony/polyfill-mbstring: ~1.0
Requires (Dev)
- clean/phpdoc-md: ^0.19.3
- mikey179/vfsstream: ^1.6.10
- phpunit/phpunit: ^9
- scrutinizer/ocular: ^1.9
- wa72/html-pretty-min: ~0.1
Suggests
- wa72/html-pretty-min: Minify or indent HTML documents
This package is auto-updated.
Last update: 2024-09-07 12:30:51 UTC
README
Wa72\HtmlPageDom
是一个PHP库,用于通过DOM轻松操作HTML文档。它需要 Symfony组件的DomCrawler 来遍历DOM树,并通过添加操作HTML文档DOM树的方法来扩展它。
当你不仅需要从HTML文件中提取信息(DomCrawler所做的),还需要修改HTML页面时,它非常有用。它可以作为一个模板引擎:加载HTML模板文件,在页面标题、div#content
或 ul#menu
等元素上设置新的HTML内容,并打印出修改后的页面。
Wa72\HtmlPageDom
由两个主要类组成
-
HtmlPageCrawler
通过添加如setInnerHtml($htmltext)
、before()
、append()
、wrap()
、addClass()
或css()
等受jQuery启发的、HTML特定的DOM 操作 函数来扩展Symfony\Components\DomCrawler
。它就像PHP中的jQuery:简单地使用CSS选择器选择HTML页面的元素,并更改它们的属性和内容。 -
HtmlPage
代表一个完整的HTML文档,并提供如getTitle()
、setTitle($title)
、setMeta('description', $description)
、getBody()
等便利函数。内部,它使用HtmlPageCrawler
类来过滤和操作DOM元素。自1.2版本以来,它还提供了压缩(minify()
)和美化打印(indent()
)HTML页面的方法。
要求与兼容性
版本3.x
- PHP 8.x
- Symfony\Components\DomCrawler 6.x | 7.x
- Symfony\Components\CssSelector 6.x | 7.x
版本2.x
- PHP ^7.4 | 8.x
- Symfony\Components\DomCrawler ^4.4 | 5.x
- Symfony\Components\CssSelector ^4.4 | 5.x
2.x和3.0.x版本之间的API没有区别。唯一的区别是与不同版本的Symfony的兼容性。
安装
-
使用 composer:
composer require wa72/htmlpagedom
-
使用其他 PSR-4 兼容的自动加载器:将此项目克隆到包含库的位置,并将自动加载器指向在此项目的 "src" 目录中查找 "\Wa72\HtmlPageDom" 命名空间
使用方法
HtmlPageCrawler
是DOMNodes的包装器。可以使用 new
或静态函数 HtmlPageCrawler::create()
创建 HtmlPageCrawler
对象,该函数接受一个HTML字符串或一个DOMNode(或一个DOMNode数组、一个DOMNodeList,甚至是另一个 Crawler
对象)作为参数。
之后,可以通过调用 filter()
(相当于jQuery中的find())从添加的DOM树中选择节点,并使用以下jQuery-like操作函数更改选定的元素
addClass()
、hasClass()
、removeClass()
、toggleClass()
after()
、before()
append()
、appendTo()
makeClone()
(相当于jQuery中的clone()
)css()
(别名getStyle()
/setStyle()
)html()
(获取内部HTML内容)和setInnerHtml($html)
attr()
(别名getAttribute()
/setAttribute()
)、removeAttr()
insertAfter()
、insertBefore()
makeEmpty()
(与 jQuery 中的empty()
等价)prepend()
,prependTo()
remove()
replaceAll()
,replaceWith()
text()
,getCombinedText()
(获取爬虫中所有节点的文本内容)以及setText($text)
wrap()
,unwrap()
,wrapInner()
,unwrapInner()
,wrapAll()
要获取修改后的 DOM 作为 HTML 代码,请使用 html()
(返回爬虫对象中第一个节点的 innerHTML)或 saveHTML()
(返回列表中所有元素的组合“外部”HTML 代码)。
请参阅生成的 HtmlPageCrawler API 文档中的完整方法文档。
示例
use \Wa72\HtmlPageDom\HtmlPageCrawler; // create an object from a fragment of HTML code as you would do with jQuery's $() function $c = HtmlPageCrawler::create('<div id="content"><h1>Title</h1></div>'); // the above is the same as calling: $c = new HtmlPageCrawler('<div id="content"><h1>Title</h1></div>'); // filter for h1 elements and wrap them with an HTML structure $c->filter('h1')->wrap('<div class="innercontent">'); // return the modified HTML echo $c->saveHTML(); // or simply: echo $c; // implicit __toString() calls saveHTML() // will output: <div id="content"><div class="innercontent"><h1>Title</h1></div></div>
高级示例:从 HTML 表格中删除第三列
use \Wa72\HtmlPageDom\HtmlPageCrawler; $html = <<<END <table> <tr> <td>abc</td> <td>adsf</td> <td>to be removed</td> </tr> <tr> <td>abc</td> <td>adsf</td> <td>to be removed</td> </tr> <tr> <td>abc</td> <td>adsf</td> <td>to be removed</td> </tr> </table> END; $c = HtmlPageCrawler::create($html); $tr = $c->filter('table > tr > td') ->reduce( function ($c, $j) { if (($j+1) % 3 == 0) { return true; } return false; } ); $tr->remove(); echo $c->saveHTML();
HtmlPage
类的使用示例
use \Wa72\HtmlPageDom\HtmlPage; // create a new HtmlPage object with an empty HTML skeleton $page = new HtmlPage(); // or create a HtmlPage object from an existing page $page = new HtmlPage(file_get_contents('http://www.heise.de')); // get or set page title echo $page->getTitle(); $page->setTitle('New page title'); echo $page->getTitle(); // add HTML content $page->filter('body')->setInnerHtml('<div id="#content"><h1>This is the headline</h1><p class="text">This is a paragraph</p></div>'); // select elements by css selector $h1 = $page->filter('#content h1'); $p = $page->filter('p.text'); // change attributes and content of an element $h1->addClass('headline')->css('margin-top', '10px')->setInnerHtml('This is the <em>new</em> headline'); $p->removeClass('text')->append('<br>There is more than one line in this paragraph'); // add a new paragraph to div#content $page->filter('#content')->append('<p>This is a new paragraph.</p>'); // add a class and some attribute to all paragraphs $page->filter('p')->addClass('newclass')->setAttribute('data-foo', 'bar'); // get HTML content of an element echo $page->filter('#content')->saveHTML(); // output the whole HTML page echo $page->save(); // or simply: echo $page; // output formatted HTML code echo $page->indent()->save(); // output compressed (minified) HTML code echo $page->minify()->save();
请参阅生成的 HtmlPage API 文档
限制
-
HtmlPageDom 建立在 PHP 的 DOM 函数之上,并使用 DOMDocument 类的 loadHTML() 和 saveHTML() 方法。这就是为什么它的输出总是 HTML,而不是 XHTML。
-
PHP 使用的 HTML 解析器是为 HTML4 构建的。它会在 HtmlPageDom 忽略的 HTML5 特定元素上抛出错误,因此 HtmlPageDom 在一些限制下可用于 HTML5。
-
HtmlPageDom 未经测试,除 UTF-8 之外的其他字符编码。
历史
当我发现使用 jQuery 修改 HTML 文档非常容易时,我在寻找一个提供类似功能的 PHP 库。
搜索 Google 时,我发现了 SimpleHtmlDom 和后来的 Ganon,但两者都证明非常慢。尽管如此,我还是在我的项目中使用了这两个库。
当 Symfony2 出现并带有它的 DomCrawler 和 CssSelector 组件时,我想:遍历 DOM 树和通过 CSS 选择器选择元素的函数已经存在了,只有操作函数缺失。让我们来实现它们!因此,HtmlPageDom 项目应运而生。
结果证明,建立在 PHP 的 DOM 函数之上是一个好选择:与 SimpleHtmlDom 和 Ganon 相比,HtmlPageDom 非常快。在我的一个项目中,我有一个 PHP 脚本,它接受一个包含数百个文章元素的巨大 HTML 页面,并将它们提取到单独的 HTML 文件中(稍后通过 AJAX 需求加载回原始 HTML 页面)。使用 SimpleHtmlDom,该脚本需要 3 分钟(是的,分钟!)才能运行(并且我需要将 PHP 的内存限制提高到超过 500MB)。使用 Ganon 作为 HTML 解析和操作引擎,它甚至需要更长的时间,大约 5 分钟。切换到 HtmlPageDom 后,执行相同处理任务的相同脚本只需要大约一秒钟(所有都是在同一台服务器上)。HtmlPageDom 真的很快。
© 2012-2023 Christoph Singer。许可协议为 MIT 许可。