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

2305

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

31个回答

42

我推荐PHP Simple HTML DOM解析器

它真的有很棒的功能,比如:

foreach($html->find('img') as $element)
       echo $element->src . '<br>';

37
这听起来像是对 W3C XPath 技术的良好任务描述。很容易表达查询,例如“返回嵌套在元素中的标记中的所有属性。” 我不是 PHP 专家,无法告诉您 XPath 可能以何种形式可用。如果可以调用外部程序来处理 HTML 文件,则应该可以使用命令行版本的 XPath。 欲了解简要介绍,请参见http://en.wikipedia.org/wiki/XPath

31

3
如果您已经复制我的评论,至少要正确地链接它们;) 那应该是:建议使用第三方替代方案来代替SimpleHtmlDom,这些替代方案实际上使用DOM而不是字符串解析:phpQueryZend_DomQueryPathFluentDom - Gordon
1
好的答案是一个很好的资源。https://dev59.com/l3A65IYBdhLWcg3w1SXU - johnlemon

27

你可以使用simple_html_dom来实现这个目的。然而,我已经用过simple_html_dom了,特别是用于网络爬虫方面,发现它太容易受到攻击了。它可以完成基本工作,但我不建议使用它。

我从未使用过curl来实现这个目的,但我所学到的是,curl可以更有效地完成工作,并且更加稳定。

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


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

25
高级 HTML Dom 是一个简单的 HTML DOM 替代方案,它提供相同的接口,但是基于DOM,这意味着没有相关的内存问题。

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


我从Advanced Html Dom得到了很好的结果,我认为它应该在被接受的答案列表中。但对于任何依赖其的人来说,一个重要的事情要知道是:“这个项目的目标是成为PHP简单html dom库的基于DOM的替代品...如果你使用file/str_get_html,那么你不需要改变任何东西。” https://archive.is/QtSuj#selection-933.34-933.100 是你可能需要更改代码以适应一些不兼容性。我在项目的github问题中注意到了四个我所知道的。https://github.com/monkeysuffrage/advanced_html_dom/issues - ChrisJJ

24

QueryPath很不错,但要小心“跟踪状态”,因为如果你没有意识到它的含义,就可能会浪费大量的调试时间来查找发生了什么以及代码为什么无法工作。

它的意思是每次对结果集的调用都会修改对象中的结果集,而不像jquery那样可链接,其中每个链接都是一个新集合,你只有一个单一的集合,即查询结果,并且每个函数调用都会修改该单一集合。

为了获得类似于jquery的行为,您需要在进行过滤/修改操作之前进行分支,这意味着它将更加密切地反映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将不会被修改,您可以再次重复使用结果集,也许有更多知识的人可以澄清一下这一点,但基本上是我所发现的。


22

对于HTML5,html5库已经多年没有维护了。目前我能找到的唯一一个有最近更新和维护记录的HTML5库是html5-php,它在一周多之前才刚刚发布了beta 1.0版本。


21

我创建了一个名为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. "select"已更名,原因显而易见。
  2. "empty"已更名,因为在PHP中是保留字。

注意:

该库还包括自己的零配置自动加载程序,用于PSR-0兼容库。附带的示例应该可以立即使用,无需进行任何其他配置。或


看起来这是一个正确的工具,但它在PHP 5.6.23中在Worpress中无法加载。有关如何正确包含它的任何其他说明?在functions.php中包含了以下内容:define("BASE_PATH", dirname(FILE)); define("LIBRARY_PATH", BASE_PATH . DIRECTORY_SEPARATOR . 'lib/vendor'); require LIBRARY_PATH . DIRECTORY_SEPARATOR . 'Loader.php'; Loader::init(array(LIBRARY_PATH, USER_PATH)); - lithiumlab

18

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


18
另一个您可以尝试的选项是QueryPath。它受jQuery启发,但是在PHP服务器上使用,并且在Drupal中使用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接