最近一直在从事数据抓取工作,难免要对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官方文档