系统学习 By.XPATH 的核心语法、实操示例与最佳实践
XPath(XML Path Language)是 W3C 定义的文档树导航标准,也是 Selenium 中功能最强大、最灵活的元素定位方式。它通过路径表达式遍历 HTML DOM 树的任意方向(父、子、兄弟、祖先、后代),结合属性匹配(@id/@name/@class)、文本函数(text()/contains())、位置索引与逻辑运算符(and/or)实现精准定位。理论上页面中任何元素都能用 XPath 定位,但需注意其依赖 DOM 层级结构,页面变动时可能失效,建议优先使用相对路径(//)而非绝对路径。
driver.find_element(By.XPATH, "/html/body/div[1]/header/h1")(① 绝对路径
driver.find_element(By.XPATH, "//input")(② 相对路径
//input 仅需标签名即可定位,无需逐层书写完整 DOM 路径//input 取第一个,页面多个 input 时要加索引或属性// 比 / 慢(全局遍历),但现代浏览器差异可忽略//div//span//a 虽然合法但可读性差,建议用轴或属性//input[@id='x'] 比 //input 稳定得多//div[contains(@class,'btn')] 可能匹配多个,配合 and 缩小范围//tag[@id='xxx'] 或 //button[text()='提交']
driver.find_element(By.XPATH, "(//input)[2]")(③ 元素索引
//标签 匹配多个元素时,用 [n] 取第 n 个,下标从 1 开始://标签 再加 [n],不是 //标签[n](后者含义不同)。(//input)[0] 是错的!XPath 下标从 1 开始,不是 0。driver.find_element(By.XPATH, "//input[@id='userName']")(④ 属性
[@属性='值'] 筛选元素,实战首选:[@class='btn primary'] 要全写,漏一个就匹配不到 → 用 contains。el-123),注意检查。driver.find_element(By.XPATH, "//div[contains(@class,'demo')]")(⑤ 模糊属性值
starts-with(@属性, '前缀'):匹配属性值以某字符串开头contains(@属性, '关键字'):匹配属性值包含某字符串(最常用)contains(., '文字') 还能匹配元素的文本内容。and 缩小范围。starts-with 不能写成 Starts-With。driver.find_element(By.XPATH, "//button[normalize-space()='提交表单']")(⑥ 文本匹配
[text()='xxx'] 或 [normalize-space()='xxx'][contains(text(),'关键字')] — 文本包含某关键字即可contains(., '文字') 用 .(当前节点)比 text() 范围更广——连子元素里的文本也能匹配。text() 只匹配直接子文本节点,子元素里的文本不算;用 . 可覆盖。driver.find_element(By.XPATH, "//div[@class='form-grid']/div[last()]")(⑦ 函数条件匹配
last() 特别实用——动态列表中取最后一项很方便。driver.find_element(By.XPATH, "//*[@name='email' and @type='text']")(⑧ 逻辑运算符
and / or / not() 组合多个筛选条件:&& / ||,XPath 里是 and / or(英文单词)。not() 是函数不是运算符:[not(@disabled)],不能写 [!@disabled]。driver.find_element(By.XPATH, "//label/following-sibling::input")(⑨ 轴定位
节点/轴名::tag,双冒号 :: 别写成单冒号。driver.find_elements(By.XPATH, "/html/body/div[1]/header/h1")(① 绝对路径)driver.find_elements(By.XPATH, "//input")(② 相对路径)driver.find_elements(By.XPATH, "(//input)[2]")(③ 元素索引)driver.find_elements(By.XPATH, "//input[@id='userName']")(④ 属性)driver.find_elements(By.XPATH, "//div[contains(@class,'demo')]")(⑤ 模糊属性值)driver.find_elements(By.XPATH, "//button[normalize-space()='提交表单']")(⑥ 文本匹配)driver.find_elements(By.XPATH, "//div[@class='form-grid']/div[last()]")(⑦ 函数条件匹配)driver.find_elements(By.XPATH, "//*[@name='email' and @type='text']")(⑧ 逻辑运算符)driver.find_elements(By.XPATH, "//label/following-sibling::input")(⑨ 轴定位)@id/@name/@class/@type 等属性,多属性 and 更稳定。text()='xxx' 或 contains(text(),'xxx')。(//...)[n],XPath 下标从 1 开始。