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


Answers:


1896

本机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中可以找到一个基本的概念概述

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

XMLReader

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

与DOM一样,XMLReader也基于libxml。我不知道如何触发HTML解析器模块,因此使用XMLReader解析损坏的HTML的机会可能不如使用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 for html 5解析,值得一试。


网页服务

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

ScraperWiki

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


常用表达

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

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

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

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

另请参阅解析Cthulhu方式的HTML


图书

如果你想花一些钱,看看

我不隶属于PHP Architect或作者。


10
@Naveed取决于您的需求。我不需要CSS Selector查询,这就是为什么我将DOM与XPath一起使用的原因。phpQuery旨在成为jQuery端口。Zend_Dom是轻量级的。您真的必须检查出他们,看看您最喜欢哪一个。
戈登

2
@ Ms2ger通常,但不是完全。就像上面已经指出的那样,您可以使用基于libxml的解析器,但是在某些特殊情况下,它们会阻塞。如果需要最大的兼容性,最好使用专用的解析器。我更喜欢保持这种区别。
Gordon

9
您不使用PHP简单HTML DOM解析器的观点似乎没有意义。
Petah'2

3
截至2012年3月29日,DOM不支持html5,XMLReader不支持HTML,针对PHP的html5lib上一次提交是在2009年9月。如何解析HTML5,HTML4和XHTML?
Shiplu Mokaddim 2012年

4
@Nasha我特意从上面的列表中排除了臭名昭著的Zalgo咆哮,因为它本身并没有太大帮助,而且自从编写以来就引起了很多货运狂热。不管正则表达式作为解决方案多么合适,人们都对这个链接一无所知。如需更平衡的意见,请参阅我确实包含的链接,stackoverflow.com/questions/4245008/…上
Gordon

322

尝试简单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);

8
首先,我需要准备一些东西,例如不良的DOM,Invlid代码,还针对DNSBL引擎进行js分析,这也将用于查找恶意网站/内容,还因为我围绕框架构建了自己的网站,已经建立起来,它必须干净,可读且结构良好。SimpleDim很棒,但是代码有点混乱
RobertPitt 2010年

9
@Robert您可能还想查看htmlpurifier.org中与安全相关的内容。
戈登

3
他有一个正确的观点:simpleHTMLDOM很难扩展,除非您使用装饰器模式,否则我认为这很难。我发现自己颤抖着只是对基础类进行了更改。
艾里克(Erik)2010年

1
我所做的是在将HTML发送到SimpleDOM之前,将其html整理整齐。
MB34 2012年

1
我目前正在使用它,并将其作为项目的一部分运行以处理数百个URL。它变得非常缓慢,并且定期超时仍然存在。这是一个很棒的初学者脚本,直观易学,但是对于更高级的项目来说太基本了。
luke_mclachlan '16

236

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


19
真正。它与PHP的内置XPath和XSLTProcessor类一起使用,这对于提取内容非常有用。
Kornel

8
对于真正损坏的HTML,在将其交给DOM之前,您始终可以通过htmltidy运行它。每当我需要从HTML抓取数据时,我总是使用DOM,或者至少使用simplexml。
Frank Farmer

9
加载格式错误的HTML i的另一件事是,调用libxml_use_internal_errors(true)来防止警告将停止解析可能是明智的。
赫斯基

6
我已经使用DOMDocument解析了大约1000个html源(以不同字符集编码的各种语言),没有任何问题。您可能会遇到与此相关的编码问题,但并不是无法克服的。您需要了解3件事:1)loadHTML使用元标记的字符集来确定编码2)#2如果html内容不包含此信息,则可能导致错误的编码检测3)错误的UTF-8字符可能使解析器跳闸。在这种情况下,请结合使用mb_detect_encoding()和Simplepie RSS Parser的编码/转换/剥离不好的UTF-8字符代码来解决。

1
DOM实际上支持XPath,请看一下DOMXPath
瑞安·麦考

147

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

首先,一个常见的误称: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注释有时是提取更为有用的锚点。特别是伪HTML变体<$var>或SGML残差很容易与正则表达式配合。
  • 通常,正则表达式可以节省后期处理。但是,HTML实体通常需要手动维护。
  • 最后,对于诸如提取<img src = url之类的极其简单的任务,它们实际上是一种可能的工具。相对于SGML / XML解析器的速度优势主要体现在这些非常基本的提取过程中。

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

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


20
DOMComment可以阅读评论,因此没有理由为此使用Regex。
戈登2010年

4
SGML工具箱或XML解析器都不适合解析现实世界的HTML。为此,仅适合使用专用的HTML解析器。
Alohci

12
@Alohci DOM使用libxml,并且libxml有一个单独的HTML解析器模块,该模块将在加载HTML时使用,loadHTML()因此它可以非常加载“真实世界”(读取损坏的)HTML。
戈登2010年

6
好吧,只是关于您的“现实世界考虑”立场的评论。当然,在解析HTML时,Regex存在有用的情况。还有使用GOTO的有用情况。变量变量也有一些有用的情况。因此,没有任何特定的实现可以使用它来确定代码。但这是一个非常强烈的警告信号。而且,一般的开发人员不太可能细致入微地分辨出差异。因此,一般来说,Regex GOTO和Variable-Variables都是邪恶的。有非邪恶的用途,但这些是例外(并且在那非常罕见)...(恕我直言)
ircmaxell 2010年

11
@mario:实际上,可以使用正则表达式对HTML 进行“正确”解析,尽管通常需要花费很多时间才能完成正常工作。在一般情况下,这只是一种皇家痛苦。在特定情况下,如果输入定义明确,它就显得微不足道了。在这种情况下,人们应该使用正则表达式。一般情况下,大型老式解析器确实是您所需要的,尽管临时用户并不总是清楚该在哪里划界线。不管哪种代码越简单,就越成功。
tchrist

131

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");
 }

通常,您想为使用简单的#id.classDIV标记选择器->find()。但是您也可以使用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相比)

88

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

simplehtmldom.sourceforge

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

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


61

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

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


56

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

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

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


之所以说类似jQuery的CSS查询,是因为w3c文档中缺少某些东西,但它们是jquery中的额外功能。
Nikola Petkanski

53

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


8
并非完全正确(en.wikipedia.org/wiki/Screen_scraping#Screen_scraping)。线索在“屏幕”中。在上述情况下,不涉及任何屏幕。尽管公认的是,该术语最近遭受了很多滥用。
鲍比·杰克

4
我不是屏幕抓取工具,根据我的协议,将由内容提供商授权解析将要解析的内容。
罗伯特·皮特(RobertPitt)2010年

41

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



36

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



24

是的,您可以为此使用simple_html_dom。但是,我已经对simple_html_dom进行了大量工作,尤其是对于Web抓取,并且发现它过于脆弱。它可以完成基本工作,但我还是不会推荐它。

我从来没有使用过curl来达到目的,但是我了解到curl可以更有效地完成工作,并且更加坚固。

请查看此链接: scraping-websites-with-curl


2
curl可以获取文件,但不会为您解析HTML。那是困难的部分。
cHao 2012年

23

QueryPath很好,但是请注意“跟踪状态”,因为如果您没有意识到这意味着什么,那可能意味着您浪费了大量的调试时间来试图找出发生了什么以及代码为什么不起作用。

这意味着对结果集的每次调用都会修改对象中的结果集,它不像jquery中那样可链接,在jquery中每个链接都是一个新集合,您只有一个集合,这是查询的结果,并且每个函数调用都进行修改那一套。

为了获得类似jquery的行为,您需要在执行类似filter / modify的操作之前进行分支,这意味着它将更紧密地反映jquery中发生的事情。

$results = qp("div p");
$forename = $results->find("input[name='forename']");

$results现在包含的结果集input[name='forename']不是原来的查询,"div p"这让我大跌眼镜,我发现QueryPath跟踪筛选器和查找的内容以及修改结果并将其存储在对象中的所有内容。您需要这样做

$forename = $results->branch()->find("input[name='forname']")

然后$results将不会被修改,您可以一次又一次地重用结果集,也许某个有更多知识的人可以稍微澄清一下,但是从我发现的结果来看,基本上就像这样。


20

Advanced Html Dom是提供相同接口的简单HTML DOM替换,但是它基于DOM,这意味着不会发生任何相关的内存问题。

它还具有完整的CSS支持,包括jQuery扩展。


我从Advanced Html Dom获得了不错的成绩,我认为它应该在公认的答案中。对于任何依赖它的人来说,重要的一点是要知道“该项目的目标是成为基于PHP的简单html dom库的基于DOM的直接替换...如果您使用file / str_get_html,那么您不需要改变任何事情。” archive.is/QtSuj#selection-933.34-933.100是您可能需要对代码进行更改以适应某些不兼容性。我已经在该项目的github问题中注意到了我所知道的四个。github.com/monkeysuffrage/advanced_html_dom/issues
ChrisJJ

工作了!谢谢
Faisal Shani

18

对于HTML5,html5 lib已经被放弃了很多年。我可以找到的唯一具有最近更新和维护记录的HTML5库是html5-php,它是在一周多前才发布到beta 1.0的。


17

我写了一个通用的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 仓库XmlExtractor


17

我创建了一个名为 PHPPowertools / DOM-Query,该库使您可以像使用jQuery一样对HTML5和XML文档进行爬网。

在引擎盖下,它使用symfony / DomCrawler将CSS选择器转换为XPath选择器。即使将一个对象传递给另一个对象,它也始终使用相同的DomDocument来确保良好的性能。


使用示例:

namespace PowerTools;

// Get file content
$htmlcode = file_get_contents('https://github.com');

// Define your DOMCrawler based on file string
$H = new DOM_Query($htmlcode);

// Define your DOMCrawler based on an existing DOM_Query instance
$H = new DOM_Query($H->select('body'));

// Passing a string (CSS selector)
$s = $H->select('div.foo');

// Passing an element object (DOM Element)
$s = $H->select($documentBody);

// Passing a DOM Query object
$s = $H->select( $H->select('p + p'));

// Select the body tag
$body = $H->select('body');

// Combine different classes as one selector to get all site blocks
$siteblocks = $body->select('.site-header, .masthead, .site-body, .site-footer');

// Nest your methods just like you would with jQuery
$siteblocks->select('button')->add('span')->addClass('icon icon-printer');

// Use a lambda function to set the text of all site blocks
$siteblocks->text(function( $i, $val) {
    return $i . " - " . $val->attr('class');
});

// Append the following HTML to all site blocks
$siteblocks->append('<div class="site-center"></div>');

// Use a descendant selector to select the site's footer
$sitefooter = $body->select('.site-footer > .site-center');

// Set some attributes for the site's footer
$sitefooter->attr(array('id' => 'aweeesome', 'data-val' => 'see'));

// Use a lambda function to set the attributes of all site blocks
$siteblocks->attr('data-val', function( $i, $val) {
    return $i . " - " . $val->attr('class') . " - photo by Kelly Clark";
});

// Select the parent of the site's footer
$sitefooterparent = $sitefooter->parent();

// Remove the class of all i-tags within the site's footer's parent
$sitefooterparent->select('i')->removeAttr('class');

// Wrap the site's footer within two nex selectors
$sitefooter->wrap('<section><div class="footer-wrapper"></div></section>');

[...]

支持的方法:


  1. 由于明显的原因,将其重命名为“选择”
  2. 重命名为“ void”,因为“ empty”是PHP中的保留字

注意 :

该库还包括其自己的用于PSR-0兼容库的零配置自动加载器。包含的示例无需任何其他配置即可直接使用。或者,您可以将其与作曲家一起使用。


看起来像是适合该工作的工具,但不适用于Worpress的PHP 5.6.23。有关如何正确包含它的任何其他说明?随附于:define(“ BASE_PATH”,dirname(FILE)); define(“ LIBRARY_PATH”,BASE_PATH。DIRECTORY_SEPARATOR。'lib / vendor'); 需要LIBRARY_PATH。DIRECTORY_SEPARATOR。'Loader.php'; 加载器:: init(array(LIBRARY_PATH,USER_PATH)); 在functions.php中
锂实验室

15

您可以尝试使用类似HTML Tidy的方法来清理所有“损坏的” HTML,并将HTML转换为XHTML,然后可以使用XML解析器进行解析。





11

有很多处理HTML / XML DOM的方法,其中大多数已经提到。因此,我不会尝试列出这些人。

我只想补充一点,我个人更喜欢使用DOM扩展,为什么:

  • iit充分利用了基础C代码的性能优势
  • 它是OO PHP(并允许我对其进行子类化)
  • 它的级别很低(这使我可以将其用作更高级行为的非膨胀基础)
  • 它提供对DOM各个部分的访问(例如,与SimpleXml不同,后者忽略了一些鲜为人知的XML功能)
  • 它具有用于DOM爬网的语法,该语法类似于本机Javascript中使用的语法。

而且,尽管我错过了使用CSS选择器的能力DOMDocument,但是有一种相当简单方便的方法来添加此功能:子类化DOMDocument并将类JS querySelectorAllquerySelector方法添加到子类中。

为了解析这些选择,我建议使用非常简约CssSelector组件Symfony框架。该组件只是将CSS选择器转换为XPath选择器,然后可以将其输入到DOMXpath以检索相应的Nodelist。

然后,您可以将此子类(仍为非常低的子类)用作更多高级类的基础,例如。解析非常特定类型的XML或添加更多类似jQuery的行为。

下面的代码直接给出了我的DOM-Query库,并使用了我描述的技术。

对于HTML解析:

namespace PowerTools;

use \Symfony\Component\CssSelector\CssSelector as CssSelector;

class DOM_Document extends \DOMDocument {
    public function __construct($data = false, $doctype = 'html', $encoding = 'UTF-8', $version = '1.0') {
        parent::__construct($version, $encoding);
        if ($doctype && $doctype === 'html') {
            @$this->loadHTML($data);
        } else {
            @$this->loadXML($data);
        }
    }

    public function querySelectorAll($selector, $contextnode = null) {
        if (isset($this->doctype->name) && $this->doctype->name == 'html') {
            CssSelector::enableHtmlExtension();
        } else {
            CssSelector::disableHtmlExtension();
        }
        $xpath = new \DOMXpath($this);
        return $xpath->query(CssSelector::toXPath($selector, 'descendant::'), $contextnode);
    }

    [...]

    public function loadHTMLFile($filename, $options = 0) {
        $this->loadHTML(file_get_contents($filename), $options);
    }

    public function loadHTML($source, $options = 0) {
        if ($source && $source != '') {
            $data = trim($source);
            $html5 = new HTML5(array('targetDocument' => $this, 'disableHtmlNsInDom' => true));
            $data_start = mb_substr($data, 0, 10);
            if (strpos($data_start, '<!DOCTYPE ') === 0 || strpos($data_start, '<html>') === 0) {
                $html5->loadHTML($data);
            } else {
                @$this->loadHTML('<!DOCTYPE html><html><head><meta charset="' . $encoding . '" /></head><body></body></html>');
                $t = $html5->loadHTMLFragment($data);
                $docbody = $this->getElementsByTagName('body')->item(0);
                while ($t->hasChildNodes()) {
                    $docbody->appendChild($t->firstChild);
                }
            }
        }
    }

    [...]
}

另请参见Symfony的创建者Fabien Potencier决定使用CSS选择器解析XML文档,他决定为Symfony创建CssSelector组件以及如何使用它。


9

使用FluidXML,您可以使用XPathCSS选择器查询和迭代XML 。

$doc = fluidxml('<html>...</html>');

$title = $doc->query('//head/title')[0]->nodeValue;

$doc->query('//body/p', 'div.active', '#bgId')
        ->each(function($i, $node) {
            // $node is a DOMNode.
            $tag   = $node->nodeName;
            $text  = $node->nodeValue;
            $class = $node->getAttribute('class');
        });

https://github.com/servo-php/fluidxml


7

来自XML的JSON和数组分为三行:

$xml = simplexml_load_string($xml_string);
$json = json_encode($xml);
$array = json_decode($json,TRUE);

da!


7

不使用正则表达式解析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/")));


0

如果您熟悉jQuery选择器,则可以使用ScarletsQuery for PHP

<pre><?php
include "ScarletsQuery.php";

// Load the HTML content and parse it
$html = file_get_contents('https://www.lipsum.com');
$dom = Scarlets\Library\MarkupLanguage::parseText($html);

// Select meta tag on the HTML header
$description = $dom->selector('head meta[name="description"]')[0];

// Get 'content' attribute value from meta tag
print_r($description->attr('content'));

$description = $dom->selector('#Content p');

// Get element array
print_r($description->view);

该库通常需要不到1秒的时间来处理脱机html。
它还接受无效的HTML或标记属性上缺少引号。


0

解析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;
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.