如何解析HTML/XML并从中提取信息?
当前回答
不使用正则表达式解析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/")));
其他回答
QueryPath很好,但要小心“跟踪状态”,因为如果你没有意识到它的含义,这可能意味着你浪费了大量调试时间,试图找出发生了什么以及代码为什么不工作。
这意味着对结果集的每一次调用都会修改对象中的结果集,这与jquery中的每个链接都是一个新的集一样是不可链接的,您有一个单独的集,它是查询的结果,而每个函数调用都会更改该单独的集。
为了获得类似jquery的行为,您需要在执行类似过滤器/修改的操作之前进行分支,这意味着它将更紧密地反映jquery中发生的情况。
$results = qp("div p");
$forename = $results->find("input[name='forename']");
$results现在包含输入的结果集[name='rename']而不是原始查询“div p”。这让我很困惑,我发现QueryPath跟踪过滤器和查找结果,以及修改结果并将其存储在对象中的所有内容。你需要这样做
$forename = $results->branch()->find("input[name='forname']")
那么$results将不会被修改,您可以一次又一次地重用结果集,也许有更多知识的人可以稍微澄清一下,但从我的发现来看,基本上是这样的。
本机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架构师或作者。
Advanced Html Dom是一个简单的Html Dom替代品,它提供了相同的界面,但它是基于Dom的,这意味着不会出现任何相关的内存问题。
它还具有完整的CSS支持,包括jQuery扩展。
顺便说一下,这通常被称为屏幕刮擦。我为此使用的库是SimpleHTMLDomParser。
对于1a和2:我将投票支持新的Symfony Componet类DOMCrawler(DOMCrawler)。此类允许类似于CSS选择器的查询。看看这个演示文稿,看看真实世界的例子:news-of-the-symfony2-world。
该组件设计为独立工作,可以在没有Symfony的情况下使用。
唯一的缺点是它只适用于PHP5.3或更高版本。