你如何在 PHP 中解析和处理 HTML/XML?

新手上路,请多包涵

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

原文由 RobertPitt 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 813
2 个回答

本机 XML 扩展

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

DOM

DOM 扩展允许您使用 PHP 5 通过 DOM API 对 XML 文档进行操作。它是 W3C 文档对象模型核心级别 3 的一个实现,一个平台和语言中立的接口,允许程序和脚本动态访问和更新文件的内容、结构和风格。

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

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

StackOverflow 上已经 广泛 介绍了如何使用 DOM 扩展,因此如果您选择使用它,可以确定您遇到的大部分问题都可以通过搜索/浏览 Stack Overflow 来解决。

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

XML阅读器

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

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

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

XML 解析器

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

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

简单的XML

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

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

提供了一个 基本用法示例 ,PHP 手册中还有许多其他示例


第 3 方库(基于 libxml)

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

FluentDom

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

HtmlPageDom

Wa72\HtmlPageDom 是一个 PHP 库,用于使用 DOM 轻松操作 HTML 文档。它需要 Symfony2 组件中的 DomCrawler 来遍历 DOM 树,并通过添加操作 HTML 文档的 DOM 树的方法来扩展它。

查询

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

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

层域

Laminas\Dom 组件(以前称为 Zend_DOM)提供了处理 DOM 文档和结构的工具。目前,我们提供 Laminas\Dom\Query ,它为使用 XPath 和 CSS 选择器查询 DOM 文档提供了一个统一的接口。

这个包被认为是功能完整的,现在处于仅安全维护模式。

fDOM文档

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

军刀/ xml

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

流体XML

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


第 3 方(不是基于 libxml 的)

在 DOM/libxml 上构建的好处是您可以获得开箱即用的良好性能,因为您是基于本机扩展的。然而,并不是所有的 3rd 方库都走这条路。下面列出了其中一些

PHP 简单的 HTML DOM 解析器

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

我一般不推荐这个解析器。代码库很糟糕,解析器本身相当慢并且需要内存。并非所有 jQuery 选择器(例如 子选择器)都是可能的。任何基于 libxml 的库都应该很容易胜过这一点。

PHP HTML 解析器

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

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


HTML 5

您可以使用上面的代码来解析 HTML5,但由于 HTML5 允许的标记 ,可能会有一些怪癖。所以对于 HTML5 你可能要考虑使用专用的解析器。请注意,这些是用 PHP 编写的,因此与使用低级语言的编译扩展相比,性能较慢且内存使用量增加。

HTML5Dom文档

HTML5DOMDocument 扩展了本机 DOMDocument 库。它修复了一些错误并添加了一些新功能。

  • 保留 html 实体(DOMDocument 不保留)
  • 保留 void 标签(DOMDocument 不保留)
  • 允许插入 HTML 代码,将正确的部分移动到适当的位置(head 元素插入到 head 中,body 元素插入到 body 中)
  • Allows querying the DOM with CSS selectors (currently available: * , tagname , tagname#id , #id , tagname.classname , .classname , tagname.classname.classname2 , .classname.classname2 , tagname[attribute-selector] , [attribute-selector] , div, p , div p , div > p , div + pp ~ ul )5-94d07
  • 添加对 element->classList 的支持。
  • 添加对 element->innerHTML 的支持。
  • 添加对 element->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 克苏鲁之道


图书

如果你想花点钱,看看

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

原文由 Gordon 发布,翻译遵循 CC BY-SA 4.0 许可协议

试试 简单的 HTML DOM 解析器

  • 用 PHP 5+ 编写的 HTML DOM 解析器,可让您以非常简单的方式操作 HTML!
  • 需要 PHP 5+。
  • 支持无效的 HTML。
  • 使用选择器在 HTML 页面上查找标签,就像 jQuery 一样。
  • 在一行中从 HTML 中提取内容。
  • 下载

注意:顾名思义,它对简单的任务很有用。它使用正则表达式而不是 HTML 解析器,因此对于更复杂的任务来说会慢得多。它的大部分代码库是在 2008 年编写的,此后只做了很小的改进。它不遵循现代 PHP 编码标准,并且很难融入现代 PSR 兼容项目。

例子:

获取HTML元素的方法:

 // Create DOM from URL or file
$html = file_get_html('http://www.example.com/');

// Find all images
foreach($html->find('img') as $element)
       echo $element->src . '<br>';

// Find all links
foreach($html->find('a') as $element)
       echo $element->href . '<br>';

如何修改 HTML 元素:

 // Create DOM from string
$html = str_get_html('<div id="hello">Hello</div><div id="world">World</div>');

$html->find('div', 1)->class = 'bar';

$html->find('div[id=hello]', 0)->innertext = 'foo';

echo $html;

从 HTML 中提取内容:

 // Dump contents (without tags) from HTML
echo file_get_html('http://www.google.com/')->plaintext;

抓取 Slashdot:

 // Create DOM from URL
$html = file_get_html('http://slashdot.org/');

// Find all article blocks
foreach($html->find('div.article') as $article) {
    $item['title']     = $article->find('div.title', 0)->plaintext;
    $item['intro']    = $article->find('div.intro', 0)->plaintext;
    $item['details'] = $article->find('div.details', 0)->plaintext;
    $articles[] = $item;
}

print_r($articles);

原文由 Naveed 发布,翻译遵循 CC BY-SA 4.0 许可协议

推荐问题