本文目录导读:

在Symfony项目中,CSS选择器(CSS Selector)主要通过 Symfony DomCrawler 组件 实现,它允许你使用CSS选择器语法来解析和遍历HTML/XML文档。
安装与基础使用
安装组件
composer require symfony/dom-crawler composer require symfony/css-selector # CSS选择器转换器
基本用法
use Symfony\Component\DomCrawler\Crawler;
$html = '<html>
<body>
<div class="content">
<h1>标题</h1>
<p class="text">第一段</p>
<p class="text">第二段</p>
<a href="/link1" class="link">链接1</a>
<a href="/link2" class="link">链接2</a>
<ul id="list">
<li data-id="1">项目1</li>
<li data-id="2">项目2</li>
</ul>
</div>
</body>
</html>';
$crawler = new Crawler($html);
常用CSS选择器示例
标签选择器
// 选择所有p标签
$paragraphs = $crawler->filter('p');
// 获取第一个p标签的内容
$firstParagraph = $crawler->filter('p')->first()->text();
// 遍历所有p标签
$crawler->filter('p')->each(function ($node) {
echo $node->text();
});
类选择器
// 选择class为"text"的元素
$textElements = $crawler->filter('.text');
// 选择同时包含两个class的元素
$elements = $crawler->filter('.text.link');
// 多类选择器
$elements = $crawler->filter('.text.link');
ID选择器
// 选择id为"list"的元素
$list = $crawler->filter('#list');
属性选择器
// 选择有href属性的元素
$withHref = $crawler->filter('[href]');
// 选择href等于特定值
$specificLink = $crawler->filter('[href="/link1"]');
// 选择href包含特定文本
$partialMatch = $crawler->filter('[href*="link"]');
// 选择href以特定文本开头
$startsWith = $crawler->filter('[href^="/link"]');
// 选择href以特定文本结尾
$endsWith = $crawler->filter('[href$="1"]');
// 选择data属性
$dataItems = $crawler->filter('[data-id]');
$item1 = $crawler->filter('[data-id="1"]');
组合选择器
// 后代选择器
$divParagraphs = $crawler->filter('div p');
// 子元素选择器
$directChildren = $crawler->filter('div > p');
// 相邻兄弟选择器
$adjacentSibling = $crawler->filter('h1 + p');
// 通用兄弟选择器
$generalSibling = $crawler->filter('h1 ~ p');
伪类选择器
// 第一个子元素
$firstChild = $crawler->filter('li:first-child');
// 最后一个子元素
$lastChild = $crawler->filter('li:last-child');
// 第n个子元素
$nthChild = $crawler->filter('li:nth-child(2)');
// 奇数/偶数元素
$oddItems = $crawler->filter('li:nth-child(odd)');
$evenItems = $crawler->filter('li:nth-child(even)');
// 不包含某个选择器
$notClass = $crawler->filter('p:not(.special)');
高级操作
链式调用
// 先选择父元素,再选择子元素
$result = $crawler
->filter('.content')
->filter('p')
->first()
->text();
获取属性和文本
// 获取文本内容
$text = $crawler->filter('h1')->text();
// 获取HTML内容
$html = $crawler->filter('div')->html();
// 获取属性值
$href = $crawler->filter('a')->attr('href');
// 获取多个属性
$attributes = $crawler->filter('a')->extract(['href', 'class']);
数据提取
// 提取多个元素的数据
$links = $crawler->filter('a')->each(function ($node) {
return [
'text' => $node->text(),
'href' => $node->attr('href'),
'class' => $node->attr('class'),
];
});
// 提取表格数据
$tableData = $crawler->filter('table tr')->each(function ($row) {
return $row->filter('td')->each(function ($cell) {
return $cell->text();
});
});
实际开发示例
网页爬虫示例
// 在Controller中使用
public function scrapeWebsite()
{
$client = new \Symfony\Component\BrowserKit\HttpBrowser(); // 需要安装 browser-kit
$crawler = $client->request('GET', 'https://example.com');
// 提取文章标题
$articles = $crawler->filter('article')->each(function ($node) {
return [
'title' => $node->filter('h2')->text(),
'description' => $node->filter('.description')->text(),
'link' => $node->filter('a')->attr('href'),
'image' => $node->filter('img')->attr('src'),
];
});
// 提取分页链接
$nextPage = $crawler->filter('a.next-page')->attr('href');
// 提取表单数据
$form = $crawler->filter('#search-form')->form();
$form['q'] = '搜索关键词';
$result = $client->submit($form);
}
表单处理
// 选择和提交表单
$form = $crawler->filter('form')->form();
$form['username'] = 'user123';
$form['password'] = 'pass456';
$crawler = $client->submit($form);
// 获取表单字段
$fields = $form->getValues();
注意事项
- 性能考虑:对于大型文档,避免过度使用
each(),考虑使用reduce()或直接提取 - 命名空间:确保XML文档正确处理命名空间
- 编码问题:处理非UTF-8编码时需注意字符编码
- :CSS选择器只能处理静态HTML,动态内容需要配合JavaScript渲染工具
常见问题解决
// 处理命名空间
$crawler = new Crawler($xmlContent);
$crawler->registerNamespace('ns', 'http://example.com/ns');
$elements = $crawler->filter('ns|element');
// 处理编码问题
$html = mb_convert_encoding($html, 'UTF-8', 'GBK');
$crawler = new Crawler($html);
CSS选择器是Symfony DomCrawler最强大的功能之一,合理使用可以大幅提高HTML解析和数据提取的效率。