Nstproxy 现已升级为 Nstdata。了解此次变化。 周一至周五 09:00 - 18:00(UTC+08:00) 公司地址
19H MAXGRAND PLAZA NO.3 TAI YAU STREET SAN PO KONG, KOWLOON HONG KONG
©2026 NST LABS TECH LTD. 保留所有权利。Ivy LinCommunity & Content Lead
XPath vs. CSS 选择器:如何选择用于网页抓取
TL;DR
- CSS 选择器通常对于元素结构和属性简洁,而 XPath 对于显式轴和文本导向遍历非常有用。
- 选择一个你的实际引擎支持的选择器,而不是关于语法类型的通用声明。
- 现代 CSS 具有关系选择器,但在浏览器和服务器端解析器之间支持有所不同。
- Parsel 的
::text 和 ::attr(...) 是提取扩展,而非标准浏览器 CSS 选择器。
- 稳定的身份、范围、基数和值检查比选择器开始于 CSS 还是 XPath 更为重要。
- 选择器无法提取接收到的文档中缺失的内容;获取和呈现必须单独诊断。
Should You Use XPath or CSS Selectors for Web Scraping?
当 CSS 选择器能够清楚地表达所需的结构或属性关系时使用它,而当 XPath 的轴或文本操作可以更清晰地说明记录关系时使用 XPath。最好的选择器是你的提取引擎支持的,并且你的团队可以对代表性文档进行维护。没有一个通用的胜者适用于所有浏览器、XML 工具和服务器端 HTML 解析器。
一个有用的起始规则是选择最简单的表达式,以识别在显式识别的记录中的预期字段。然后断定应该存在多少结果及其可能包含的值。一个匹配页面上每个价格的短选择器比一个稍微长一些与正确产品身份相关的选择器更糟糕。
获取层保持独立。Nstdata Crawl 可以为下游解析器提供页面表示,但 CSS 和 XPath 在实际返回的表示上进行操作。选择器不能恢复因不完整渲染或清理而被省略的字段。
How Do XPath and CSS Compare in Practice?
XPath 和 CSS 在表达风格、遍历操作、结果类型和引擎支持上有所不同。这些差异只有在与具体提取任务关联时才变得有用。
| Decision field | CSS selectors | XPath |
|---|
| Common strength | 简洁的元素、类、属性和结构匹配 | 显式轴、节点选择和基于字符串的谓词 |
| Result in a browser | 通常匹配的元素 | 可以选择节点和其他 XPath 结果类型 |
| Text extraction | 通常是单独的 API 操作 | 可以在表达式中选择文本节点 |
| Relationship support | 取决于支持的选择器,包括关系特征 | 轴表示祖先、兄弟、后代等 |
| Portability risk | 解析器支持和库扩展 | XPath 版本和主机实现 |
| Maintenance risk | 生成的类和位置链 | 绝对路径和脆弱的文本假设 |
该MDN CSS 选择器参考和描述了基础的选择器家族。在将表达式从 DevTools 转移到 Python 或 Java 解析器之前,请检查所用工具的文档。
MDN XPath 参考
Why Is “CSS Cannot Select a Parent” an Incomplete Rule?
“CSS 无法选择父元素”是一个不完整的规则,因为现代的关系选择器可以表达一些旧 CSS 指导不涵盖的关系。实际引擎的支持仍然是决定性因素。支持选择器的浏览器并不意味着较旧的服务器端解析器也支持它。
例如,关系匹配可以识别包含特定后代的元素。XPath 使用自己的谓词或轴来表达这种关系。哪个版本更清晰取决于文档和引擎。不要将一个引擎的支持差距视为对所有 CSS 实现的陈述。
文本匹配需要类似的关注。标准 CSS 不是一般文本查询语言。库可以添加特殊文本谓词,自动化框架可以提供文本或可访问定位器。这些便利是具有自己语义的工具 API。在文档中保持这种区分是很重要的,特别是对于必须可移植的提取器。
What Should You Prepare Before Writing a Selector?
在编写选择器之前,准备一个代表性文档、稳定的记录身份、字段定义和预期结果计数。捕捉普通和变更页面的情况。如果你的来源有变体、货币或列表/详细关系,请将这些情况纳入固定集。
为了演示,使用 Python 并安装 parsel。测试包版本为 1.12.1。对于受控 HTML 示例,不需要帐户或远程页面访问。该Parsel 使用指南记录了 CSS 和 XPath 提取,包括其 CSS 扩展。
保持至少一个负案例:没有匹配的记录、两个匹配的身份、缺少字段或意外单位。在一个保存的页面上有效的选择器,如果在源更改后默默接受错误的行,则不是一个可靠的数据契约。解析器比较指南 有助于将引擎行为与选择器偏好区分开。
如何比较等效的 CSS 和 XPath 表达式?
通过要求它们从同一文档返回相同意图字段来比较等效表达式。以下固定装置包含两个类似产品的记录,提取范围限于 A17 身份。
第一步:保存选择器探针
将其保存为 selector_probe.py,避免与 Python 标准库模块冲突的名称。该固定装置和变量是插图;解析器和断言是执行代码。
from parsel import Selector
html = """<main>
<article data-sku="A17"><h2>台灯</h2><span class="price">29.00</span></article>
<article data-sku="B42"><h2>落地灯</h2><span class="price">79.00</span></article>
</main>"""
root = Selector(text=html)
css_prices = root.css('article[data-sku="A17"] .price::text').getall()
xpath_prices = root.xpath('//article[@data-sku="A17"]//span[@class="price"]/text()').getall()
assert css_prices == xpath_prices == ["29.00"]
owner = root.xpath('//h2[normalize-space(.)="台灯"]/ancestor::article/@data-sku').getall()
assert owner == ["A17"]
print({"prices": css_prices, "owner": owner})
第二步:运行断言
运行 python selector_probe.py。验证结果包含价格 ['29.00'] 和所有者 ['A17']。这确认了在控制固定装置上的等效提取,并演示了 XPath 的显式祖先遍历。它不是一般性能比较。
第三步:添加源更改案例
更改固定装置以包含另一条记录、额外布局包装、缺少价格或多个价格。决定哪些更改应保留结果,哪些应失败接受。示例的确切类匹配故意与单个 price 类的固定装置绑定;对于具有多个类标记的源,请使用令牌感知 XPath 谓词或其他文档化策略,而不是确切的相等性。
成功的测试应建立身份、基数和字段含义。当源预计包含记录时,不要将空数组视为成功更新。
如何使选择器更耐用?
通过将选择器锚定到稳定的语义并在选择字段之前限制其范围来使选择器更耐用。当源提供时,优先考虑文档化的数据属性、稳定的 ID 或显式记录关系。生成的类和长位置路径通常编码独立于数据变化的表示细节。
从记录容器开始,在其中选择。如果页面同时包含列表价格和促销价格,请定义架构要求的价格。分别检查货币和变体上下文,而不是提取数值文本。这些是含义检查,且无论哪个语法族都不会自动执行。
保持提取和规范化的区别。文本规范化可能会折叠有意义的空白,组合隐藏标签或根据使用的 API 省略嵌套内容。保存代表性的预期值,并在更改时检查源。结构化提取工作流 解释了为什么序列化只是接受的一个阶段。
浏览器自动化是否应使用与静态解析器相同的选择器?
浏览器自动化应使用适合其运行时的选择器和定位器,而不是盲目地重用静态解析器表达式。浏览器可能会暴露呈现的文本、框架、影子根和异步更新,而保存的 HTML 文档并不能以相同的方式表示这些内容。
Playwright 定位器指南 描述了定位器行为和自动等待。对于 UI 交互,可访问的角色和标签定位器可能比长 DOM 路径更清晰地表达意图。对于数据提取,稳定的源属性和显式字段检查可能仍然适用。
不要假设定位器等待会建立数据完整性。一个元素可以在其值被填充之前存在,或者同一个选择器可以匹配同意屏幕。等待一个有意义的字段或状态,并验证接受的内容。将框架和影子根边界视为明确的实现要求,而不是循环随机选择器的理由。
Nstdata Crawl 如何在基于选择器的提取之前提供帮助?
当解析器缺少所需文档时,Nstdata Crawl 可以提供帮助,因为获取或渲染是实际的限制。Nstdata Crawl 是一个用于 LLM 准备数据的网络爬虫 API,能够将有限的网站转换为可重用的页面输出。网站发现和递归爬行支持受控的覆盖。JavaScript 渲染可以在表示转换之前填充动态内容。您的提取器仍然可以选择正确的记录关系并验证字段。
- HTML 和替代证据: HTML 对于 DOM 感知解析非常有用,Markdown 用于 AI 上下文,链接用于发现,PDF 或截图用于审查。原始输出可以帮助解释在解析之前为何某个字段消失。
- 有限来源收集: 设置页面和深度限制,使用包含/排除规则,并将返回的 URL 与经过批准的清单进行比较。提取选择器不能替代爬取范围。
- 内置代理路由: 标准调用避免了单独的代理主机、端口、用户名、密码和协议配置。考虑在 爬取计费模型 中,随着 URL 使用的路由流量。
要进行初步的托管内容检查,请通过 Dashboard → Crawl Playground 创建一个密钥,在 Python 3.10 或更高版本下安装 nstdata-ai-crawl,并设置 NSTDATA_API_TOKEN 和 APPROVED_PAGE_URL。下面的凭证依赖示例需要您自己的密钥和允许的目标。它验证返回的 Markdown 以供检查;在下一阶段应用 DOM 选择器时请求 HTML。
[截图:Nstdata Crawl Playground 具有批准的目标和请求的格式;保持 API 密钥隐藏。]
import os
from pathlib import Path
from nstdata_ai_crawl import NstDataClient, ScrapeRequestDto
with NstDataClient(os.environ["NSTDATA_API_TOKEN"],
max_response_bytes=1_048_576) as client:
result = client.submit_scrape_task_sync(ScrapeRequestDto(
url=os.environ["APPROVED_PAGE_URL"], formats=["markdown"],
onlyMainContent=True, timeout=60000,
))
if result.success is not True or result.status != "completed":
raise RuntimeError("集合未成功完成")
if result.data is None or result.data.truncated is True:
raise RuntimeError("缺少或部分内容需要审查")
text = result.data.get_markdown()
if not text or not text.strip():
raise RuntimeError("未返回可用的 Markdown")
expected = os.environ.get("EXPECTED_TEXT")
if expected and expected not in text:
raise RuntimeError("缺少所需的源文本")
Path("accepted-page.md").write_text(text, encoding="utf-8")
print("已保存 accepted-page.md;请在摄取之前验证事实")
在更改提取器之前检查输出。如果在每个有用的表示中都缺少所需的文本,则问题出在 CSS 或 XPath 之上。 JavaScript 重度页面指南 有助于将不完整的渲染与解析器失败分开。
当选择器停止工作时您应该怎么做?
当选择器停止工作时,在重写表达式之前,将接收到的文档与接受的模板进行比较。记录记录是否消失、移动、改变身份或以不同的表示到达。
| 症状 | 可能原因 | 下一个检查 |
|---|
| 两种语法中均无匹配项 | 内容缺失或记录范围变化 | 检查获取和保留的 HTML |
| 匹配项过多 | 选择器未限制在某一身份 | 检查容器和结果计数 |
| 在 DevTools 中工作但在解析器中失败 | 不支持的引擎功能或不同的 DOM | 检查版本和实际输入表示 |
| 正确的数量,错误的项目 | 表现匹配但无身份 | 验证实体键和上下文 |
| 运行之间文本变化 | 动态状态或标准化 | 比较渲染状态和提取 API |
将被拒绝的行分开,并保留最后接受的数据。不要仅仅为了让结果不为空而用更广泛的选择器替换稳定的选择器。
您应该保留哪个选择器?
保留最清楚地表达源关系的选择器,并在您的实际引擎中通过代表性的正面和负面测试。记录所有扩展或版本假设,以便其他维护者可以重现该行为。当失败在选择器阶段之前开始时,Nstdata 的 HTML 和视觉输出可以提供额外的证据。
常见问题解答
不。性能取决于引擎、文档、表达式和工作负载。在做出性能声明之前,请测量等效任务。
不是。在这个例子中,它是一个 Parsel 提取扩展,不应未修改地复制到浏览器的 querySelector 调用中。
某些关系可以通过关系选择器来表达,但必须在实际浏览器或解析器中检查支持情况。
问:XPath 能否提取从未到达文档的 JavaScript 数据?
不能。XPath 在提供的文档上运行;渲染或其他批准的获取方法必须首先提供内容。
稳定的身份、正确的作用域、支持的引擎行为、预期计数和字段验证通常比语法偏好更重要。
Ivy Lin
Nov. 12th 2026
支持 JavaScript 渲染,成功率达 99.8%
将任意网站转换为 Markdown、HTML、JSON、链接、PDF 等格式,无需管理爬取基础设施。