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


当前回答

我已经编写了一个通用XML解析器,可以轻松处理GB文件。它基于XMLReader,非常容易使用:

$source = new XmlExtractor("path/to/tag", "/path/to/file.xml");
foreach ($source as $tag) {
    echo $tag->field1;
    echo $tag->field2->subfield1;
}

下面是github repo:XmlExtractor

其他回答

解析xml的最佳方法:

$xml='http://www.example.com/rss.xml';
$rss = simplexml_load_string($xml);
$i = 0;
foreach ($rss->channel->item as $feedItem) {
  $i++;
  echo $title=$feedItem->title;
  echo '<br>';
  echo $link=$feedItem->link;
  echo '<br>';
  if($feedItem->description !='') {
    $des=$feedItem->description;
  } else {
    $des='';
  }
  echo $des;
  echo '<br>';
  if($i>5) break;
}

本机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结构,如果通过大多数解析器加载,则会失败。

Symfony框架具有可以解析HTML的捆绑包,您可以使用CSS样式来选择DOM,而不是使用XPath。

不使用正则表达式解析HTML有几个原因。但是,如果您完全控制将生成什么HTML,那么可以使用简单的正则表达式。

上面是一个通过正则表达式解析HTML的函数。请注意,此函数非常敏感,要求HTML遵守某些规则,但它在许多场景中都非常有效。如果您想要一个简单的解析器,并且不想安装库,请尝试一下:

function array_combine_($keys, $values) {
    $result = array();
    foreach ($keys as $i => $k) {
        $result[$k][] = $values[$i];
    }
    array_walk($result, create_function('&$v', '$v = (count($v) == 1)? array_pop($v): $v;'));

    return $result;
}

function extract_data($str) {
    return (is_array($str))
        ? array_map('extract_data', $str)
        : ((!preg_match_all('#<([A-Za-z0-9_]*)[^>]*>(.*?)</\1>#s', $str, $matches))
            ? $str
            : array_map(('extract_data'), array_combine_($matches[1], $matches[2])));
}

print_r(extract_data(file_get_contents("http://www.google.com/")));