CSS 选择器的工作原理
浏览器和解析器会把 HTML 转换为文档对象模型(DOM)。选择器会在这棵树上匹配元素,匹配到的元素可供读取、点击或设置样式。在浏览器 JavaScript 中,querySelector() 返回第一个匹配项,querySelectorAll() 则返回所有匹配项。
常见模式包括:
- 类型:
h2匹配所有<h2>元素。 - 类:
.product匹配具有该类的元素。 - ID:
#results匹配具有该 ID 的元素。 - 属性:
[data-price]匹配带有该属性的元素。 - 层级关系:
article.product > h2匹配直接子级标题。
在采集工具中使用选择器
在网页采集中,选择器用于定位需要提取文本或属性的元素:
const products = [...document.querySelectorAll("article.product")].map(card => ({
name: card.querySelector("h2").textContent.trim(),
price: card.querySelector("[data-price]").textContent.trim()
}));
这段代码先找到每张商品卡片,再读取标题和价格。Beautiful Soup 和 Playwright 等工具都提供了接受 CSS 选择器的方法。
静态 HTML 解析器无法选择 JavaScript 后续添加的内容。如果某个元素会出现在浏览器开发者工具中,却不在下载的 HTML 里,可能需要使用 JavaScript 渲染,或查找页面实际调用的数据接口。
CSS 选择器与 XPath
CSS 选择器和 XPath 都能定位元素,但各有优势。
| 功能 | CSS 选择器 | XPath |
|---|---|---|
| 典型语法 | .product[data-id] |
//div[@data-id] |
| 按文本查找 | 无法直接查找 | 支持使用谓词查找 |
| 匹配父级 | 对 :has() 的支持情况各异 |
支持父级轴和祖先轴 |
| 可读性 | 通常更简短 | 更适合复杂路径 |
按类和属性匹配时,CSS 通常更简单。如果选择条件取决于文本,或需要明确沿祖先层级查找,XPath 会更实用。
编写可靠的选择器
- 优先使用稳定的
data-*属性、语义明确的类或唯一 ID。 - 在稳定的容器内限定匹配范围,不要搜索整个页面。
- 避免使用自动生成的类名和很长的
:nth-child()链。 - 检查匹配结果是否为零个或多个,避免页面布局变化后悄悄破坏数据。
选择器会在页面获取完成后运行。代理会改变网站看到的 IP 地址,但无法修复过时的选择器,也不会渲染缺失的内容。
常见问题
CSS 选择器只能用于设置样式吗?
不是。CSS 用选择器设置样式,浏览器、测试工具和采集工具也用选择器定位 HTML 元素。
为什么 CSS 选择器在浏览器中有效,在采集工具中却无效?
通常是因为开发者工具显示的是经过 JavaScript 修改的 DOM,而采集工具只能看到原始 HTML。可以在浏览器中渲染页面,或检查页面从哪里加载数据。
CSS 选择器能按文本匹配元素吗?
仅使用标准 CSS 不能直接做到。可以先选择候选元素,再按文本筛选;如果工具支持,也可以使用 XPath。