CSS 选择器详细教程:原理、语法、方向/“轴”与实战

CSS 选择器详细教程:原理、语法、方向/"轴"与实战

面向:爬虫与自动化同学(Python 为主),从原理到实战。重点讲"方向/轴"的概念与 CSS 的能力边界。


1. CSS 选择器是什么?

CSS 选择器 是一套用来在 HTML 文档树中定位元素的规则语法。浏览器使用它来应用样式,而爬虫/自动化用它来定位元素。

优势

  • 语法简洁、易读
  • 浏览器原生支持,执行速度快
  • 适合大量"按 class/id/层级"的定位需求

2. 原理:DOM 树与匹配规则

HTML 会被解析成 DOM 树,CSS 选择器就是在树上做"匹配"。

核心思想:

  • 通过 标签、class、id、属性 等条件筛选节点
  • 通过 组合器(combinator) 表达节点之间的方向关系

3. CSS 基础语法速览

3.1 基本选择

css 复制代码
#id
.class
TagName

3.2 属性选择器

css 复制代码
[a]
[a="v"]
[a^="v"]  /* 以 v 开头 */
[a$="v"]  /* 以 v 结尾 */
[a*="v"]  /* 包含 v */

3.3 组合器(方向关系)

css 复制代码
A B    /* 后代 */
A > B  /* 子元素 */
A + B  /* 相邻兄弟 */
A ~ B  /* 后续兄弟 */

3.4 伪类与伪元素

css 复制代码
:first-child
:nth-child(2)
:nth-of-type(3)
:not(.disabled)

4. CSS 的"轴/方向"概念(重点)

XPath 有"轴(axis)"概念,比如 parent::ancestor::following-sibling::。CSS 没有"轴"这个术语,但组合器 + 伪类可以表达常见方向关系。

4.1 CSS 可表达的方向(类轴)

XPath 轴概念 CSS 对应方式 示例
子元素(child) > div > span
后代(descendant) 空格 div span
右侧兄弟(following-sibling) +~ h2 + p / h2 ~ p

4.2 CSS 不擅长/不支持的方向

  • 向上找父级/祖先 (XPath 的 parent::ancestor::
  • 向左找前置兄弟 (XPath 的 preceding-sibling::

这就是为什么复杂定位场景通常更推荐 XPath。

4.3 :has()(现代 CSS 的"反向选择")

CSS4 的 :has() 允许根据子元素反推父元素:

css 复制代码
div:has(> span.author)

注意:

  • 浏览器支持度较新;有些解析器/引擎不支持
  • 在 Selenium 中是否可用取决于浏览器对 :has() 的支持情况

5. 实战一:BeautifulSoup(bs4)里的 CSS 选择器

5.1 基本用法

python 复制代码
from bs4 import BeautifulSoup

html = """<div class='post'><h2>标题</h2></div>"""
soup = BeautifulSoup(html, "lxml")

# 返回列表
items = soup.select("div.post > h2")
# 返回单个(第一个)
item = soup.select_one("div.post > h2")

print(item.get_text())

5.2 属性与伪类

python 复制代码
# 属性选择
links = soup.select("a[href^='https']")

# nth-child
items = soup.select("ul > li:nth-child(2)")

5.3 bs4 注意点

  • select() 返回 列表
  • select_one() 返回 单个元素或 None
  • 伪类支持有限(通常可用的是 :nth-child:not 等常用伪类)

6. 实战二:Selenium 中使用 CSS 选择器

6.1 基本用法

python 复制代码
from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.get("https://example.com")

# 多元素
items = driver.find_elements(By.CSS_SELECTOR, "div.item")
# 单元素
item = driver.find_element(By.CSS_SELECTOR, "div.item")

注意:Selenium 正确写法是 By.CSS_SELECTOR,不是 By.CSS

6.2 在元素内继续定位

python 复制代码
card = driver.find_element(By.CSS_SELECTOR, "div.card")
name = card.find_element(By.CSS_SELECTOR, ".name")

6.3 搭配显式等待

python 复制代码
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

wait = WebDriverWait(driver, 10)
items = wait.until(
    EC.presence_of_all_elements_located((By.CSS_SELECTOR, "div.item"))
)

6.4 "方向/轴"场景示例

python 复制代码
# 找标题后面的第一个段落(相邻兄弟)
content = driver.find_element(By.CSS_SELECTOR, "h2.title + p")

# 找标题后面所有段落(后续兄弟)
contents = driver.find_elements(By.CSS_SELECTOR, "h2.title ~ p")

7. 其他常见使用场景

  1. Scrapy + CSS

    python 复制代码
    response.css("a::attr(href)").getall()
  2. Playwright

    python 复制代码
    page.locator("div.item")
  3. 浏览器控制台

    js 复制代码
    document.querySelectorAll("div.item")
  4. 前端样式规则调试(原始用途)


8. CSS 与 XPath 的取舍建议

需求 推荐
简单、稳定的 class/id 定位 CSS
需要向上找父级/祖先 XPath
需要复杂文本过滤 XPath
需要跨层级灵活定位 XPath

9. 常见坑与最佳实践

9.1 常见坑

  • #id 只能匹配一个元素(理论上),但 HTML 可能不规范
  • 位置伪类 :nth-child 是从 1 开始
  • :nth-child(n)所有子节点为基准,不是同标签

9.2 稳健性建议

  • 优先使用唯一 id / data-*
  • 避免过长层级
  • 尽量用结构关系(>+~)替代下标

10. 一页速查表

css 复制代码
/* 基本 */
#id
.class
Tag

/* 属性 */
[a]
[a="v"]
[a^="v"]
[a$="v"]
[a*="v"]

/* 方向 */
A B
A > B
A + B
A ~ B

/* 伪类 */
:first-child
:nth-child(2)
:not(.disabled)

11. 小结

  • CSS 选择器是 DOM 树上的匹配规则,语法简洁、性能好
  • "轴/方向"在 CSS 中用组合器 表达,但不支持向上
  • bs4 / Selenium / Scrapy / Playwright 都天然支持 CSS
  • 复杂定位建议结合 XPath 一起使用
相关推荐
weixin_39544891几秒前
cursor日志
人工智能·python·机器学习
天天爱吃肉821818 分钟前
【跨界封神|周杰伦×王传福(陶晶莹主持):音乐创作与新能源NVH测试,底层逻辑竟完全同源!(新人必看入行指南)】
python·嵌入式硬件·算法·汽车
岱宗夫up31 分钟前
Python 数据分析入门
开发语言·python·数据分析
码界筑梦坊33 分钟前
325-基于Python的校园卡消费行为数据可视化分析系统
开发语言·python·信息可视化·django·毕业设计
asheuojj35 分钟前
2026年GEO优化获客效果评估指南:如何精准衡量TOP5关
大数据·人工智能·python
多恩Stone36 分钟前
【RoPE】Flux 中的 Image Tokenization
开发语言·人工智能·python
网安墨雨1 小时前
Python自动化一------pytes与allure结合生成测试报告
开发语言·自动化测试·软件测试·python·职场和发展·自动化
powerfulhell1 小时前
寒假python作业5
java·前端·python
铉铉这波能秀1 小时前
LeetCode Hot100 中 enumerate 函数的妙用(2026.2月版)
数据结构·python·算法·leetcode·职场和发展·开发
毕设源码-赖学姐1 小时前
【开题答辩全过程】以 基于python的电影推荐系统为例,包含答辩的问题和答案
开发语言·python