2

我有这个 HTML:

<div class="body">
   <p>Some text 1</p>
   <h2>Header 2</h2>
   <p>Actual content</p>
</div>

我想从中得到一切,除了<h2>它看起来像这样:

<p>Some text 1</p>
<p>Actual content</p>

试图实现这一目标:

$crawler = new Crawler( $html );

$body = $crawler->filter( 'div.body' );
$body->rewind();
$body = $body->current();

$h2 = $crawler->filter('h2');
$h2->rewind();
$h2 = $h2->current();

$body->removeChild($h2);

但我得到:

[DOMException] 未找到错误

我错过了什么?

4

3 回答 3

6

文档中所述

DomCrawler 组件简化了 HTML 和 XML 文档的 DOM 导航。

并且:

尽管可能,DomCrawler 组件并不是为操作 DOM 或重新转储 HTML/XML 而设计的。

DomCrawler 旨在从 DOM 文档中提取细节而不是修改它们。

然而...

由于 PHP 通过引用传递对象,而Crawler基本上是DOMNode的包装器,因此在技术上可以修改底层 DOM 文档:

// will remove all h2 nodes inside .body nodes
$crawler->filter('.body h2')->each(function ($crawler) {
    foreach ($crawler as $node) {
        $node->parentNode->removeChild($node);
    }
});

这是一个工作示例:https ://gist.github.com/jakzal/8dd52d3df9a49c1e5922

于 2015-04-01T21:18:08.120 回答
1

有几种方法可以满足您的需要。

1 按类别和 P 标签过滤

从您的 html 示例中,您可以使用以下代码:

$crawler = new Crawler( $html );

$result = $crawler->filter( 'div.body > p' )->each(
    function (Crawler $node, $i) {
        return $node->text();
    }
);

echo print_r($result, true);

请注意,闭包返回值将被放置在一个数组中。这个数组将是 $result 变量。返回数组应如下所示:

Array
(
    [0] => Some text 1
    [1] => Actual content
)

2 获取正文并过滤您需要的每个元素

使用您提供的相同 html,仅按类过滤,然后单独选择每个元素:

$crawler = new Crawler( $html );
$body = $crawler->filter( '.body' );
echo $body->filter('p')->eq(0)->text() .'<br />';
echo $body->filter('p')->eq(1)->text() .'<br />';

结果应该打印出 P 标签的内容

Some text 1
Actual content

从此代码中,您可以使用以下html方法获取容器的全部内容,而不是text

$crawler = new Crawler( $html );
$body = $crawler->filter( '.body' );
echo $body->html();

您可能会发现Node Filtering Reduce方法很有用,因为您可以使用基于自定义规则过滤的节点返回 domcrawler。

另请参阅节点遍历方法以获取过滤后所需的节点。

于 2013-10-07T18:44:24.953 回答
0

(代表 OP 发布)

作为一种解决方法,我SimpleHtmlDomBundle在 10 分钟内切换到并解决了我的问题 :)

于 2015-05-20T13:33:21.560 回答