如何解析HTML/XML并从中提取信息?


当前回答

本机XML扩展

我更喜欢使用一种原生XML扩展,因为它们与PHP捆绑在一起,通常比所有第三方库都快,并为我提供了对标记所需的所有控制。

DOM

DOM扩展允许您使用PHP5通过DOMAPI对XML文档进行操作。它是W3C文档对象模型核心级别3的实现,这是一个平台和语言中立的界面,允许程序和脚本动态访问和更新文档的内容、结构和样式。

DOM能够解析和修改真实世界(已损坏)的HTML,并且可以执行XPath查询。它基于libxml。

使用DOM需要一些时间来提高效率,但这段时间是值得的。由于DOM是一种语言无关的接口,您可以找到多种语言的实现,因此如果您需要更改编程语言,那么您很可能已经知道如何使用该语言的DOM API。

StackOverflow上已经详细介绍了如何使用DOM扩展,因此如果您选择使用它,您可以确保通过搜索/浏览StackOverload来解决您遇到的大多数问题。

其他答案中提供了基本用法示例和一般概念概述。

解析器

XMLReader扩展是一个XML拉式解析器。读取器充当文档流上前进的光标,并在途中的每个节点处停止。

XMLReader与DOM一样,基于libxml。我不知道如何触发HTML解析器模块,因此使用XMLReader解析损坏的HTML可能比使用DOM更不可靠,在DOM中可以明确告诉它使用libxml的HTML解析器模块。

另一个答案中提供了一个基本用法示例。

解析器

此扩展允许您创建XML解析器,然后为不同的XML事件定义处理程序。每个XML解析器也有一些可以调整的参数。

XML解析器库也基于libxml,并实现SAX风格的XML推送解析器。对于内存管理,它可能比DOM或SimpleXML更好,但比XMLReader实现的pull解析器更难使用。

简单XML

SimpleXML扩展提供了一个非常简单且易于使用的工具集,用于将XML转换为可以使用普通属性选择器和数组迭代器处理的对象。

当您知道HTML是有效的XHTML时,SimpleXML是一个选项。如果您需要解析损坏的HTML,甚至不要考虑SimpleXml,因为它会窒息。

有一个基本的用法示例,PHP手册中还有很多其他示例。


第三方库(基于libxml)

如果您更喜欢使用第三方库,我建议使用实际上在下面使用DOM/libxml的库,而不是字符串解析。

流利通

FluentDOM为PHP中的DOMDocument提供了一个类似jQuery的fluent XML接口。选择器使用XPath或CSS(使用CSS到XPath转换器)编写。当前版本扩展了DOM实现标准接口,并添加了DOM Living standard的功能。FluentDOM可以加载JSON、CSV、JsonML、RabbitFish等格式。可以通过Composer安装。

HTML页面域

Wa72\HtmlPageDom是一个易于操作HTML的PHP库使用DOM的文档。它需要Symfony2的DomCrawler用于遍历的组件DOM树,并通过添加用于操作HTML文档的DOM树。

php查询

phpQuery是一个基于jQueryJavaScript库的服务器端、可链接的CSS3选择器驱动的文档对象模型(DOM)API。该库使用PHP5编写,并提供了额外的命令行界面(CLI)。

这被描述为“废弃软件和bug:使用风险自负”,但似乎维护得很少。

薄层dom

Laminas\Dom组件(以前称为Zend_Dom)提供了处理Dom文档和结构的工具。目前,我们提供Laminas\Dom\Query,它为使用XPath和CSS选择器查询Dom文档提供了统一的接口。此软件包被视为功能完整,现在处于仅安全维护模式。

fDOM文件

fDOMDocument扩展了标准DOM,在所有错误情况下都使用异常,而不是PHP警告或通知。为了方便和简化DOM的使用,他们还添加了各种自定义方法和快捷方式。

sa刀/xml

sabre/xml是一个库,它包装并扩展XMLReader和XMLWriter类,以创建一个简单的“xml到对象/数组”映射系统和设计模式。编写和读取XML是一次性的,因此速度很快,对大型XML文件的内存要求很低。

流体XML

FluidXML是一个PHP库,用于使用简洁流畅的API操作XML。它利用XPath和流畅的编程模式,使其变得有趣和有效。


第三方(非基于libxml)

基于DOM/libxml构建的好处是,由于您基于本机扩展,因此可以立即获得良好的性能。然而,并不是所有的第三方libs都走这条路。其中一些列在下面

PHP简单HTML DOM解析器

用PHP5+编写的HTML DOM解析器可以让您以非常简单的方式操作HTML!需要PHP 5+。支持无效的HTML。使用类似jQuery的选择器在HTML页面上查找标记。从HTML中提取单行内容。

我通常不建议使用此解析器。代码库很糟糕,解析器本身也很慢,内存不足。并非所有jQuery选择器(如子选择器)都是可能的。任何基于libxml的库都应该很容易地胜过这一点。

PHP Html解析器

PHPHtmlParser是一个简单、灵活的html解析器,它允许您使用任何css选择器(如jQuery)选择标记。目标是帮助开发需要快速、简单的方式来抓取html的工具,无论它是否有效!这个项目最初由sunra/php简单的html dom解析器支持,但支持似乎已经停止,所以这个项目是我对他以前工作的改编。

同样,我不建议使用此解析器。由于CPU使用率高,速度相当慢。也没有清除创建的DOM对象的内存的功能。这些问题尤其适用于嵌套循环。文档本身不准确,拼写错误,自2016年4月14日以来,没有对修复进行回复。


HTML 5

您可以使用上面的方法来解析HTML5,但由于HTML5允许的标记,可能会有一些奇怪之处。因此,对于HTML5,您可能需要考虑使用专用解析器。请注意,这些都是用PHP编写的,因此与使用较低级别语言编译的扩展相比,性能更慢,内存使用量更大。

HTML5DomDocument

HTML5DOMDocument扩展了本机DOMDocument库。它修复了一些错误并添加了一些新功能。保留html实体(DOMDocument不保留)保留空标记(DOMDocument不保留)允许插入HTML代码,将正确的部分移动到正确的位置(头部元素插入头部,身体元素插入身体)允许使用CSS选择器查询DOM(当前可用:*、标记名、标记名#id、#id、tagname.classname、.classname,tagname.cclassname2、.classname2、标记名[attribute selector]、[attributeselector],div、p、div p、div>p、div+p和p~ul)添加对元素->classList的支持。添加对元素->innerHTML的支持。添加对元素->outerHTML的支持。

HTML5

HTML5是完全用PHP编写的符合标准的HTML5解析器和编写器。它是稳定的,在许多制作网站中使用,下载量超过500万。HTML5提供以下功能。

HTML5序列化程序支持PHP命名空间作曲家支持基于事件(类似SAX)的解析器DOM树生成器与QueryPath的互操作性在PHP 5.3.0或更高版本上运行


正则表达式

最后也是最不推荐的,您可以使用正则表达式从HTML中提取数据。通常不鼓励在HTML上使用正则表达式。

你在网上找到的大多数与标记匹配的代码片段都很脆弱。在大多数情况下,它们只适用于一段非常特殊的HTML。微小的标记更改,如在某处添加空白,或在标记中添加或更改属性,可能会导致RegEx在未正确编写时失败。在HTML上使用RegEx之前,您应该知道自己在做什么。

HTML解析器已经知道HTML的语法规则。必须为您编写的每个新RegEx教授正则表达式。RegEx在某些情况下是可以的,但它确实取决于您的用例。

您可以编写更可靠的解析器,但使用正则表达式编写完整可靠的自定义解析器是浪费时间的,因为前面提到的库已经存在,并且在这方面做得更好。

另请参见解析Html Cthulhu方法


如果你想花钱,看看

PHP架构师使用PHP进行Web抓取的指南

我不属于PHP架构师或作者。

其他回答

我们以前已经为我们的需求创建了不少爬虫。最后,通常是简单的正则表达式做得最好。虽然上面列出的库对于创建它们的原因来说是很好的,但如果您知道自己在寻找什么,正则表达式是一种更安全的方法,因为您还可以处理无效的HTML/XTML结构,如果通过大多数解析器加载,则会失败。

这听起来像是W3C XPath技术的一个很好的任务描述。很容易表达诸如“返回嵌套在<foo><bar><baz>元素中的img标记中的所有href属性”之类的查询。我不是一个PHP爱好者,无法告诉您XPath可能以什么形式可用。如果可以调用外部程序来处理HTML文件,则应该能够使用命令行版本的XPath。有关快速介绍,请参见http://en.wikipedia.org/wiki/XPath.

简单HTML DOM是一个很棒的开源解析器:

simplehtmldom.sourceforge

它以面向对象的方式处理DOM元素,新的迭代包含了大量不兼容代码。还有一些很棒的函数,如JavaScript中的“find”函数,它将返回该标记名元素的所有实例。

我已经在许多工具中使用了这个,在许多不同类型的网页上测试了它,我认为它非常有用。

只需使用DOMDocument->loadHTML()就可以了。libxml的HTML解析算法非常好,速度也很快,与流行的观点相反,它不会对格式错误的HTML产生影响。

我创建了一个名为HTML5DOMDocument的库,可以在https://github.com/ivopetkov/html5-dom-document-php

它还支持查询选择器,我认为这在您的情况下非常有用。下面是一些示例代码:

$dom = new IvoPetkov\HTML5DOMDocument();
$dom->loadHTML('<!DOCTYPE html><html><body><h1>Hello</h1><div class="content">This is some text</div></body></html>');
echo $dom->querySelector('h1')->innerHTML;