最近一直在从事数据抓取工作,难免要对HTML页面进行解析操作,下面是使用DomCrawler解析页面的介绍。

使用composer安装DomCrawler

composer require symfony/dom-crawler

DomCrawler使用两种方式对HTML进行节点选取及遍历。

一种使用函数filterXPath(),使用XPath语言对HTML的节点进行操作。

XPath 是一门在 XML 文档中查找信息的语言。XPath 可用来在 XML 文档中对元素和属性进行遍历。XPath教程

$crawler = $crawler->filterXPath('descendant-or-self::body/p');

另一种使用filter()函数,使用CSS选择器对HTML的节点进行操作。使用CSS选择器需要安装组件CssSelector component。

composer require symfony/css-selector
$crawler = $crawler->filter('body > p');

 

下面是使用DomCrawler的一些示例

<?php

require_once "vendor/autoload.php";

use Symfony\Component\DomCrawler\Crawler;


$html = <<<'HTML'
<!DOCTYPE html>
<html>
    <body>
        <p class="message">Hello World!</p>
        <p>Hello Crawler!</p>
        <p>Hello PHP!</p>
    </body>
</html>
HTML;

$crawler = new Crawler($html);

foreach ($crawler as $domElement) {
    var_dump($domElement->nodeName);
}

// 节点选择 使用XPath
$crawler = $crawler->filterXPath('descendant-or-self::body/p');
echo 'body下的所有p元素节点,默认显示第一个'.$crawler->html().PHP_EOL;

// 节点遍历  第一个节点
echo 'eq(0)第一个节点: '.$crawler->eq(0)->html().PHP_EOL;

// first()第一个节点
echo 'first()第一个节点: '.$crawler->first()->html().PHP_EOL;

// 当前节点的同级的下面所有兄弟节点
$crawler->nextAll()->each(function (Crawler $node, $i) {
    echo '当前节点的同级的下面所有兄弟节点:'.$i.' '.$node->text().PHP_EOL;
});


// eq(1)第二个节点
echo 'eq(1)第二个节点:'.$crawler->eq(1)->html().PHP_EOL;

// last()最后一个节点
echo 'last()最后一个节点:'.$crawler->last()->html().PHP_EOL;

// 当前节点的同级的前面所有兄弟节点
$crawler->last()->previousAll()->each(function (Crawler $node, $i){
    echo '当前节点的同级的前面所有兄弟节点:'.$i.' '.$node->text().PHP_EOL;
});

echo PHP_EOL;
echo PHP_EOL;


// 使用CSS选择器

$crawler = new Crawler($html);

// CSS第一个节点
echo 'CSS eq(0): '.$crawler->filter('body > p')->eq(0)->text().PHP_EOL;

// CSS第一个节点
echo 'CSS first()第一个节点: '.$crawler->filter('body > p')->first()->text().PHP_EOL;

// CSS last() 最后一个节点
echo 'CSS last() 最后一个节点: '.$crawler->filter('body > p')->last()->text().PHP_EOL;

// CSS body的所有子节点
$crawler->filter('body')->children()->each(function (Crawler $node, $i) {
    echo 'CSS body的所有子节点: '.$i.' '.$node->text().PHP_EOL;
});

// CSS 样式message节点的父节点
echo 'CSS 样式message节点的父节点:'.$crawler->filter('.message')->parents()->nodeName().PHP_EOL;

// CSS body下所有带样式message的p节点
echo 'CSS body下所有带样式message的p节点: '.$crawler->filter('body')->children('p.message')->text().PHP_EOL;

// CSS 过滤每一个节点
$crawler = $crawler->filter('body > p')->reduce(function (Crawler $node, $i) {
//         filters every other node
        return ($i % 2) == 0;
    });
$crawler->each(function (Crawler $node, $i){
    echo 'CSS 过滤后的节点: '.$i.' '.$node->text().PHP_EOL;
});

 

详情请参阅DomCrawler官方文档