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

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

答案

本机 XML 扩展

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

DOM

DOM 扩展使您可以使用 PHP 5 通过 DOM API 通过 XML 文档进行操作。它是 W3C 的 Document Object Model Core Level 3 的实现,它是一种平台和语言无关的接口,允许程序和脚本动态访问和更新。文件的内容,结构和样式。

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

使用 DOM 需要花一些时间,但是 IMO 值得花时间。由于 DOM 是与语言无关的接口,因此您会找到许多语言的实现,因此,如果需要更改编程语言,那么您很可能已经知道如何使用该语言的 DOM API。

Grabbing A 元素的 href 属性中可以找到一个基本的用法示例,而在 php 的 DOMDocument 中可以找到基本的概念概述

如何使用 DOM 扩展已在 StackOverflow 上进行了广泛介绍 ,因此,如果您选择使用它,则可以确保可以通过搜索 / 浏览 Stack Overflow 来解决大多数遇到的问题。

XMLReader

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

像 DOM 一样,XMLReader 也基于 libxml。我不知道如何触发 HTML 解析器模块,因此使用 XMLReader 解析损坏的 HTML 的机会可能不如使用 DOM 健壮,在 DOM 中您可以明确地告诉它使用 libxml 的 HTML 解析器模块。

使用 php 从 h1 标签获取所有值时,可以找到一个基本的用法示例

XML 解析器

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

XML 解析器库也基于 libxml,并实现了SAX样式的 XML 推送解析器。与 DOM 或 SimpleXML 相比,内存管理可能是更好的选择,但与 XMLReader 实现的请求解析器相比,使用起来更加困难。

SimpleXml

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

当您知道 HTML 是有效的 XHTML 时,可以选择 SimpleXML。如果您需要解析损坏的 HTML,甚至不用考虑 SimpleXml,因为它会阻塞。

一个基本的用法示例可以在到 CRUD 节点和 xml 文件的节点值的简单程序中找到,并且在 PHP 手册中还有很多其他示例


第三方库(基于 libxml)

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

FluentDom- 回购

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

HtmlPageDom

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

phpQuery (多年未更新)

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

另请参阅: https : //github.com/electrolinux/phpquery

Zend_Dom

Zend_Dom 提供了用于处理 DOM 文档和结构的工具。当前,我们提供 Zend_Dom_Query,它提供了一个统一的接口,用于同时使用 XPath 和 CSS 选择器查询 DOM 文档。

查询路径

QueryPath 是一个用于处理 XML 和 HTML 的 PHP 库。它不仅可以与本地文件一起使用,还可以与 Web 服务和数据库资源一起使用。它实现了许多 jQuery 接口(包括 CSS 样式的选择器),但为服务器端使用做了很大的调整。可以通过 Composer 安装。

fDOMDocument

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

军刀 / XML

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

FluidXML

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


第三方(不是基于 libxml 的)

建立在 DOM / libxml 上的好处是,由于您基于本机扩展,因此可以立即获得良好的性能。但是,并非所有第 3 方库都遵循这条路线。下面列出其中一些

PHP 简单 HTML DOM 解析器

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

我通常不建议使用此解析器。代码库太可怕了,解析器本身也很慢并且占用大量内存。并非所有的 jQuery 选择器(例如子选择器 )都是可行的。任何基于 libxml 的库都应轻而易举地胜过它。

PHP HTML 解析器

PHPHtmlParser 是一个简单,灵活的 html 解析器,它使您可以使用任何 CSS 选择器(如 jQuery)来选择标签。目标是协助开发工具,这些工具需要快速,简便的方式来废弃 html,无论它是否有效!该项目最初由 sunra / php-simple-html-dom-parser 支持,但该支持似乎已停止,因此该项目是我对他先前工作的改编。

同样,我不建议使用此解析器。 CPU 使用率很高时,速度相当慢。也没有清除创建的 DOM 对象的内存的功能。这些问题在嵌套循环中尤为严重。文档本身不准确且拼写错误,自 16 年 4 月 14 日以来未对修复程序做出任何回应。

加农

  • 通用标记器和 HTML / XML / RSS DOM 解析器
    • 能够操纵元素及其属性
    • 支持无效的 HTML 和 UTF8
  • 可以对元素执行类似 CSS3 的高级查询(例如 jQuery - 支持名称空间)
  • HTML 美化工具(例如 HTML Tidy)
    • 缩小 CSS 和 Javascript
    • 排序属性,更改字符大小写,正确缩进等
  • 可扩展的
    • 使用基于当前字符 / 令牌的回调解析文档
    • 将操作分成较小的功能,以便于覆盖
  • 快速简便

没用过。无法判断是否有好处。


HTML 5

您可以使用以上内容来解析 HTML5,但是由于 HTML5 允许的标记, 因此可能会有一些怪癖 。因此,对于 HTML5,您需要考虑使用专用的解析器,例如

html5lib

基于 WHATWG HTML5 规范的 HTML 解析器的 Python 和 PHP 实现,以实现与主要桌面 Web 浏览器的最大兼容性。

HTML5 完成后,我们可能会看到更多专用的解析器。 W3 上还有一个博客文章,标题为How-To,用于 html 5 解析 ,值得一试。


网页服务

如果您不想编程 PHP,也可以使用 Web 服务。通常,我发现这些工具的实用性很少,但这只是我和我的用例。

ScraperWiki

ScraperWiki 的外部界面允许您以想要在 Web 或您自己的应用程序中使用的形式提取数据。您还可以提取有关任何刮板状态的信息。


常用表达

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

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

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

可以编写更可靠的解析器 ,但是当上述库已经存在并且在此方面做得更好时,编写具有正则表达式的完整且可靠的自定义解析器会浪费时间。

另请参阅解析 Cthulhu 方式的 HTML


图书

如果你想花一些钱,看看

我不隶属于 PHP Architect 或作者。

尝试简单 HTML DOM 解析器

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


例子:

如何获取 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);

只需使用DOMDocument-> loadHTML()即可完成。 libxml 的 HTML 解析算法非常好且快速,并且与流行的看法相反,它不会阻止格式错误的 HTML。

为什么不应该以及何时使用正则表达式?

首先,一个常见的误称:Regexps 不是用于解析 HTML。但是,正则表达式可以提取数据。提取是他们的目的。与适当的 SGML 工具包或基准 XML 解析器相比,正则表达式 HTML 提取的主要缺点是其语法工作和可靠性不同。

考虑制作一个可靠的 HTML 提取正则表达式:

<a\s+class="?playbutton\d?[^>]+id="(\d+)".+?    <a\s+class="[\w\s]*title
[\w\s]*"[^>]+href="(http://[^">]+)"[^>]*>([^<>]+)</a>.+?

比简单的 phpQuery 或 QueryPath 可读性更差:

$div->find(".stationcool a")->attr("title");

但是,在特定的用例中它们可以提供帮助。

  • 许多 DOM 遍历前端不会显示 HTML 注释<!-- ,但是注释有时是提取时更有用的锚点。特别是伪 HTML 变体<$var>或 SGML 残基易于与正则表达式配合。
  • 通常,正则表达式可以节省后期处理。但是,HTML 实体通常需要手动维护。
  • 最后,对于诸如提取 < img src = url 之类的极其简单的任务 ,它们实际上是一种可能的工具。相对于 SGML / XML 解析器的速度优势主要体现在这些非常基本的提取过程中。

有时甚至建议使用正则表达式/<!--CONTENT-->(.+?)<!--END-->/预提取 HTML 片段,然后使用更简单的 HTML 解析器前端处理其余部分。

注意:实际上,我有这个应用程序 ,在这里我可以选择使用 XML 解析和正则表达式。就在上周,PyQuery 解析中断,而正则表达式仍然有效。是的,很奇怪,我自己也无法解释。但是,它发生了。
因此,请勿仅仅因为它与 regex = evil meme 不匹配而否决现实世界中的考虑因素。 但是,我们也不要对此投票太多。这只是该主题的旁注。

phpQueryQueryPath在复制流畅的 jQuery API 方面极为相似。这就是为什么它们是在 PHP 中正确解析 HTML 的两种最简单方法。

QueryPath 的示例

基本上,您首先要根据 HTML 字符串创建可查询的 DOM 树:

$qp = qp("<html><body><h1>title</h1>..."); // or give filename or URL

结果对象包含 HTML 文档的完整树形表示。可以使用 DOM 方法遍历它。但是常见的方法是像在 jQuery 中一样使用 CSS 选择器:

$qp->find("div.classname")->children()->...;

 foreach ($qp->find("p img") as $img) {
     print qp($img)->attr("src");
 }

通常,您想为->find()使用简单的#id.classDIV标签选择器。但是您也可以使用XPath语句,该语句有时会更快。同样,典型的 jQuery 方法(例如->children()->text() ,尤其是->attr()简化提取正确的 HTML 代码段的过程。 (并且已经对其 SGML 实体进行了解码。)

$qp->xpath("//div/p[1]");  // get first paragraph in a div

QueryPath 还允许将新标记注入到流中( ->append ),然后输出并美化一个更新的文档( ->writeHTML )。它不仅可以解析格式错误的 HTML,还可以解析各种 XML 方言(带有名称空间),甚至可以从 HTML 微格式(XFN,vCard)提取数据。

$qp->find("a[target=_blank]")->toggleClass("usability-blunder");

phpQuery 或 QueryPath?

通常,QueryPath 更适合于文档处理。尽管 phpQuery 还实现了一些伪 AJAX 方法(仅 HTTP 请求),以使其更类似于 jQuery。据说 phpQuery 通常比 QueryPath 更快(因为总体功能较少)。

有关差异的更多信息,请参见tagbyte.org 在回溯计算机上进行的比较 。 (原始资料丢失了,因此这里是一个 Internet 存档链接。是的,您仍然可以找到丢失的页面,人们。)

这是QueryPath 的全面介绍

优点

  • 简便可靠
  • 简单易用的替代方案->find("a img, a object, div a")
  • 正确的数据转义(与正则表达式 grepping 相比)

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

simplehtmldom.sourceforge

它以面向对象的方式处理 DOM 元素,新的迭代涵盖了很多不兼容的代码。还有一些很棒的功能,如您在 JavaScript 中看到的那样,例如 “find” 功能,该功能将返回该标记名称的元素的所有实例。

我已经在许多工具中使用了此工具,并在许多不同类型的网页上对其进行了测试,并且我认为它的效果很好。

我这里没有提到的一种通用方法是通过Tidy运行 HTML,可以将其设置为吐出保证有效的 XHTML。然后,您可以在其上使用任何旧的 XML 库。

但是对于您的特定问题,您应该看一下以下项目: http : //fivefilters.org/content-only/-它是Readability算法的修改版本,旨在仅提取文本内容(而不是标头)和页脚)。

对于 1a 和 2:我将投票支持新的 Symfony Componet 类 DOMCrawler( DomCrawler )。此类允许类似于 CSS 选择器的查询。看看这个演示文稿,看看其中的真实示例: news-of-the-symfony2-world

该组件旨在独立运行,可以在不使用 Symfony 的情况下使用。

唯一的缺点是它仅适用于 PHP 5.3 或更高版本。

顺便说一句,这通常称为屏幕抓取 。我用于此的库是Simple HTML Dom Parser

以前,我们已经为我们的需求创建了许多爬虫。归根结底,通常最简单的正则表达式可以做到最好。尽管上面列出的库因其创建的原因而很有用,但是如果您知道要查找的内容,则正则表达式是一种更安全的方法,因为您还可以处理无效的HTML / XHTML结构,如果加载它们会失败通过大多数解析器。