本节摘要:路径不只写在代码里。浏览器开发者工具、页面自动化、抓取配置、XML 编辑器都能求值。HTML 默认命名空间和补全的 tbody 会让「在源码里抄的路径」变空。能用 CSS 选择器稳定命中的,不必上 XPath。本节合并原文 4.2 工具与 4.3 应用场景:配置抽取、RSS、测试定位、数据清洗。
阅读完本节,你应当能够:
自动化和抓取的典型任务:列表里每张卡片取标题。错误示范://div[@class='item']//span[@class='title'] 从整页扫。卡片结构一变,误伤推荐栏同名 class。
较好:先用相对稳的卡片容器选出节点集,再对每个卡片当上下文求 span[@class='title'] 或 .//span[@class='title']。相对路径短,失败时你知道是这张卡片缺标题,而不是整页表达式翻车。
浏览器里 document.evaluate(表达式, 上下文节点, 命名空间解析器, 结果类型, null)。上下文节点就是那张卡片。命名空间解析器对 HTML 文档常要处理 XHTML URI,否则裸 div 可能空。不少人因此以为「浏览器 XPath 坏了」,其实是第 3 章的护照问题。
开发者工具复制 XPath 生成的往往是绝对长链 /html/body/div[3]/div[1]/...,一次布局改版就碎。把它当起点,收成带语义属性的短路径。
| 场景 | XPath 适合吗 | 我怎么选 |
|---|---|---|
| HTML 简单 class | 常不必 | CSS 更短 |
| 要走父轴、文本谓词 | 适合 | CSS 没有父轴 |
| 要 contains 文本 | 适合 | contains(normalize-space(.),'加入购物车') |
| XML 配置 / RSS | 适合 | 天生树 |
| JSON API | 不适合 1.0 | 换 JSON 路径或 3.1 |
| 动态渲染列表 | 路径易碎 | 等数据接口,或等渲染后再相对定位 |
原文集 4.2 覆盖编辑器内求值、测试工具里的定位器。页面测试框架往往同时收 CSS 与 XPath。我倾向:稳定的 id/class 用 CSS;需要「按钮文字等于提交且在某表单内」用 XPath 谓词。
应用场景(原文 4.3):从 SOAP 或 REST 的 XML 体抠字段;RSS/Atom 列表;构建系统读 POM 一类 XML;日志若是 XML 行。都是「树已经在那」,路径比正则干净。HTML 抓取是同一技能的脏数据版:先 normalize-space,再命名空间,再少用 //。
⚠️ 常见坑:复制工具生成的绝对路径进生产。div[3] 是位置谓词,广告插入一个 div,后面全错位。用属性或语义标签,位置当最后手段。
💡 关键直觉:工具负责求值,不负责让路径变稳。稳来自短、相对、属性,不是来自更长的绝对链。

CSS 不能:父轴、前后兄弟轴(现代 CSS 有部分选择器,但文本内容谓词仍弱)、contains 文本、命名空间精细控制。XPath 不能:像 CSS 那样方便地按 class 词表匹配(要用 concat 空格技巧)。两者不是谁取代谁。
抓取工具字段里填 XPath 时,记住平台禁止把表达式写成 Markdown 链接。//a[@链接位置=...] 若裸写在正文,渲染器可能当链接。本教程一律放代码块。你在工具文本框里贴纯文本即可。
编辑器求值适合对着大 XML 试轴。把上下文设到某个 book,试 following-sibling::book[1],比在脑子里数兄弟快。
都是 1.0 思路,但浏览器树是 HTML DOM,lxml 可能是 XML 树。同一字符串不保证同一命中。以实际 DOM 为准。
节点还没渲染。等接口,或等元素出现再求值。XPath 不会帮你等。这是时序问题,不是轴写错。
CSS 不能走父轴,文本内容谓词也弱。XPath 不能像 CSS 那样方便地按 class 词表匹配。稳定的 id 和单一 class 用 CSS;「按钮文字等于提交且在某表单内」用 XPath 谓词。两者不是谁取代谁。抓取工具字段里填表达式时用纯文本,避免渲染器把方括号路径当链接。本教程示范一律放代码块,就是为了这个平台限制。
开发者工具「复制 XPath」生成绝对长链,位置谓词一路 div 方括号三。一次改版全碎。把它当起点,收成带语义属性的短路径,再改成相对卡片。自动化框架往往同时收 CSS 与 XPath,定位器策略写进项目规范,避免每个人一种口味。Selenium 的树是浏览器 DOM,lxml 可能是另一棵 XML 树,同一字符串不保证同一命中。以实际 DOM 为准。
动态页面路径总空,经常是节点还没渲染。XPath 不会帮你等。这是时序,不是轴写错。等接口数据,或等元素出现再求值。把等待写成「再加几个双斜杠」只会更慢更脆。
应用面:SOAP 或 REST 的 XML 体抠字段、RSS 列表、构建系统读项目对象模型一类 XML、XML 日志行。树已经在那,路径比正则干净。HTML 抓取是脏数据版:normalize-space、命名空间、少用双斜杠、相对卡片。JSON API 不要硬用 1.0 XPath 怼文本,换 JSON 路径或 3.1 的 map 模型。
编辑器内求值适合对着大 XML 试轴。把上下文设到某个 book,试后续兄弟,比在脑子里数快。这是学习 1.3 的好场所,也是生产表达式上线前的沙盘。不要在生产配置里直接粘贴还没 count 过的长链。
错误:整页 //div[@class='item']//span[@class='title'],推荐栏同名 class 一起进来。正确:先选出卡片节点集,对每张卡片求 span[@class='title'] 或 .//span[@class='title']。失败时知道是这张卡片缺标题。复制工具生成的 /html/body/div[3]/... 带位置谓词,广告插入一个 div 后面全错。收成语义属性。浏览器 evaluate 要处理 HTML 空间,裸 div 可能空,先怀疑护照和 tbody。
CSS 能稳就用 CSS。需要父轴或按钮文字谓词再用 XPath。动态列表空是没渲染,路径不等待。SOAP、RSS、配置是干净树,比 HTML 适合 XPath。JSON 文本别硬怼 1.0。表达式放代码块,避免方括号当链接。Selenium 树是 DOM,与 lxml 树可能不同。
练习:用两张卡片加一个推荐栏同名 title 的夹具,跑整页双斜杠和相对卡片两种写法,count 标题。相对写法应等于卡片数,整页写法更大。再把绝对链改成短路径。开发者工具复制结果只当起点。等待用框架的显式等待,不要加双斜杠。
整页搜同名标题会把推荐栏一起捞来。先选出卡片再在卡片上取标题,失败时知道是哪张缺字段。工具复制出来的从根到叶带一串位置编号,插入一个广告块后面全错,只能当草稿收成带含义的短路径。浏览器求值要处理超文本空间,裸标签可能空,先怀疑护照和补全的表格体。选择器能稳就用选择器,父方向和按文字筛再请路径。动态列表空是没画出来,路径不会等待,把等待写成更多双斜杠只会更脆。配置、订阅源、报文体是干净树,比页面更适合。对象记法文本不是树,一点零怼不了。表达式放代码块以免被当成链接。不同自动化树和解析树可能不是同一棵,以实际树为准。
做两张卡片加一个推荐栏同名标题的夹具。整页搜查标题的数字会大于卡片数,相对每张卡片取标题的数字应等于卡片数。相对写法失败时知道是哪张缺字段。工具复制出来的从根到叶带一串位置编号,插入一个广告块后面全错,只当草稿收成带含义的短路径。浏览器求值要处理超文本空间,裸标签可能空,先怀疑护照和补全的表格身体。另一套选择器能稳就用它,父方向和按文字筛再请路径。动态列表空是没画出来,路径不会等待。配置、订阅源、报文体是干净树。对象记法文本不是树。表达式放代码块以免被当成链接。不同自动化树和解析树可能不是同一棵。
原文集覆盖编辑器内求值和测试工具里的定位器。页面测试框架往往同时收两套选择法。稳定的标识和单一类别用短的那套,需要按钮文字等于某词且在某表单内用路径筛选。应用面从报文体抠字段、订阅源列表、构建系统读项目对象模型一类文档、日志若是标记语言行,都是树已经在那,路径比正则干净。超文本抓取是同一技能的脏数据版:先压空白,再护照,再少用铺开全体。对象记法接口不要硬用低版本路径怼文本。编辑器求值适合对着大文档试方向,把上下文设到某本书再试后续兄弟,比在脑子里数快,也是上线前的沙盘。
用两张卡片加一个推荐栏同名标题的夹具,跑整页铺开和相对卡片两种写法,计数标题。相对写法应等于卡片数,整页写法更大。再把绝对链改成短路径。开发者工具复制结果只当起点。等待用框架的显式等待,不要加双斜杠。另一套选择器能稳就用它,父方向和按文字筛再请路径。动态列表空是没画出来。配置、订阅源、报文体是干净树。对象记法文本不是树。表达式放代码块以免被当成链接。不同自动化树和解析树可能不是同一棵,以实际树为准。插入广告块后带位置编号的长链会全错,这是位置筛选用在布局层上的代价。相对卡片失败时知道是哪张缺字段,整页失败时你只知道数字不对。
相对卡片计数等于卡片数,整页搜查更大,推荐栏同名被误伤。绝对链带位置编号,广告一插就错。复制结果当草稿。浏览器求值先怀疑空间和补身体。短选择器能稳就用。动态空是没画出来。干净树场景比页面适合路径。对象记法文本怼不了。表达式放代码块。不同树不是同一棵。等待用显式等待。失败时相对写法能定位到哪张卡片缺字段。
相对卡片能把失败定位到某一张,整页搜查只能告诉你数字不对。长链带位置编号只当草稿,广告一插后面全错。
动手验收用两张卡片加一个推荐栏同名标题的夹具:整页搜查标题的数字应大于卡片数,相对每张卡片取标题应等于卡片数。插入一个广告块后,带位置编号的绝对长链会错位,短路径按属性取标题应仍稳。动态列表空了先问有没有画出来,不要靠再加一层双斜杠假装等待。
下一节算性能账:
//扫整棵后代,谓词顺序、编译缓存、以及一条可执行的最佳实践清单。