如何解析HTML/XML并从中提取信息?
当前回答
为什么不应该以及何时应该使用正则表达式?
首先,一个常见的误称:Regexp不用于“解析”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=urls等极其简单的任务,它们实际上是一个可能的工具。与SGML/XML解析器相比,速度优势主要用于这些非常基本的提取过程。
有时甚至建议使用正则表达式/<--内容-->(.+?)<--END-->/并使用更简单的HTML解析器前端处理其余部分。
注意:我实际上有一个应用程序,在那里我交替使用XML解析和正则表达式。就在上周,PyQuery解析中断,正则表达式仍然有效。是的,很奇怪,我自己也解释不了。但事情就是这样发生的。因此,请不要因为现实世界的考虑与正则表达式=邪恶模因不匹配就投票否决。但我们也不要对此投太多赞成票。这只是这个话题的一个旁注。
其他回答
XML_HTMLMax相当稳定——即使不再维护它。另一种选择是通过HtmlTidy将HTML导入,然后用标准的XML工具解析它。
使用FluidXML,您可以使用XPath和CSS选择器查询和迭代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
是的,您可以使用simple_html_dom。然而,我已经使用simple_html_dom做了很多工作,特别是在web抓取方面,发现它太脆弱了。它做了基本的工作,但无论如何我都不推荐它。
我从未使用过卷发,但我学到的是,卷发可以更有效地完成这项工作,而且更结实。
请查看此链接:使用curl刮取网站
简单HTML DOM是一个很棒的开源解析器:
simplehtmldom.sourceforge
它以面向对象的方式处理DOM元素,新的迭代包含了大量不兼容代码。还有一些很棒的函数,如JavaScript中的“find”函数,它将返回该标记名元素的所有实例。
我已经在许多工具中使用了这个,在许多不同类型的网页上测试了它,我认为它非常有用。
对于1a和2:我将投票支持新的Symfony Componet类DOMCrawler(DOMCrawler)。此类允许类似于CSS选择器的查询。看看这个演示文稿,看看真实世界的例子:news-of-the-symfony2-world。
该组件设计为独立工作,可以在没有Symfony的情况下使用。
唯一的缺点是它只适用于PHP5.3或更高版本。
推荐文章
- xsd:include和xsd:import之间有什么区别?
- 如何在表中删除行和列之间不需要的空间?
- 如何清除所有<div>的内容在一个父<div>?
- PHP有代码混淆器吗?
- HTML的“nonce”属性用于脚本和样式元素的目的是什么?
- 我如何在HTML中创建一个泪滴?
- 在另一个js文件中调用JavaScript函数
- 跨源请求头(CORS)与PHP头
- PHP sprintf转义%
- 我怎么能强迫一个长字符串没有任何空白被包装?
- 如何看到PHP加载的扩展?
- 在哪里放置JavaScript在HTML文件?
- 如何在引导栏中居中内容?
- 如何使用Laravel和Eloquent查询两个日期之间?
- 从Laravel 5中的另一个控制器访问控制器方法