ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

XPath 语法完全指南:从入门到精通

XPath 语法完全指南:从入门到精通 .## 一、XPath 简介XPathXML Path Language是一种在 XML 文档中查找信息的语言它使用路径表达式来选取 XML 文档中的节点或节点集。XPath 最初是为 XSLT 和 XPointer 设计的核心组件但如今已被广泛应用于Web 爬虫Python 的 lxml、Scrapy 框架自动化测试Selenium、Appium 元素定位数据提取从 HTML/XML 中解析结构化数据配置文件XML 配置的动态查询XPath 1.0 是最广泛支持的版本本文所有语法均基于 XPath 1.0。二、XPath 基本概念2.1 节点类型XPath 将 XML 文档抽象为七种节点类型节点类型说明示例元素节点ElementXML 标签book属性节点Attribute标签属性id1文本节点Text标签内文本Hello World注释节点CommentXML 注释!-- comment --处理指令节点PI?xml ...?命名空间节点Namespacexmlns:xsl根节点Root文档根不可见/2.2 节点关系父节点Parent每个元素和属性都有且仅有一个父节点子节点Children元素节点可以有零个或多个子元素兄弟节点Siblings拥有相同父节点的节点祖先节点Ancestor父节点、祖父节点等后代节点Descendant子节点、孙子节点等三、XPath 路径表达式3.1 基本语法XPath 使用类似文件系统的路径表达式来定位节点/ # 从根节点开始绝对路径 // # 从当前节点的后代中选取相对路径 . # 当前节点 .. # 当前节点的父节点 # 选取属性 * # 通配符匹配任意元素节点 * # 通配符匹配任意属性节点 node() # 匹配任意类型节点 text() # 匹配文本节点 comment() # 匹配注释节点3.2 常用路径示例假设有如下 XML 文档bookstorebookcategorycookingtitlelangenEveryday Italian/titleauthorGiada De Laurentiis/authoryear2005/yearprice30.00/price/bookbookcategorychildrentitlelangenHarry Potter/titleauthorJ K. Rowling/authoryear2005/yearprice29.99/price/book/bookstore表达式结果bookstore选取 bookstore 元素的所有子节点/bookstore选取根元素 bookstorebookstore/book选取 bookstore 下所有 book 子元素//book选取所有 book 元素无论位置bookstore//book选取 bookstore 后代中所有 book//lang选取所有名为 lang 的属性/bookstore/book[1]第一个 book 子元素/bookstore/book[last()]最后一个 book 子元素/bookstore/book[position()3]前两个 book//title[lang]所有带 lang 属性的 title//title[langen]lang 属性为 en 的 title/bookstore/book[price30]price 大于 30 的 book四、XPath 轴Axes轴定义了相对于当前节点的节点集是 XPath 强大定位能力的核心。4.1 轴的语法轴名称::节点测试[谓词]4.2 常用轴一览轴名称缩写说明ancestor当前节点的所有祖先父、祖父…ancestor-or-self祖先及自身attribute当前节点的所有属性child默认当前节点的所有子元素descendant//当前节点的所有后代descendant-or-self后代及自身following文档中当前节点结束标签之后的所有节点following-sibling当前节点之后的所有兄弟节点namespace当前节点的所有命名空间节点parent..当前节点的父节点preceding文档中当前节点开始标签之前的所有节点preceding-sibling当前节点之前的所有兄弟节点self.当前节点自身4.3 轴使用示例# 选取当前节点的所有子元素 child::book # 选取当前节点的所有属性 attribute::lang # 等价于 lang # 选取当前节点所有后代中的 title descendant::title # 等价于 .//title # 选取当前节点的父节点 parent::node() # 等价于 .. # 选取当前节点之后的所有兄弟 book following-sibling::book # 选取当前节点之前的所有兄弟 preceding-sibling::*五、XPath 谓词Predicates谓词用于过滤节点集写在方括号[]中返回布尔值。5.1 数值谓词# 第一个子元素 /bookstore/book[1] # 最后一个子元素 /bookstore/book[last()] # 倒数第二个 /bookstore/book[last()-1] # 前三个 /bookstore/book[position() 3]5.2 属性谓词# 存在 lang 属性 //title[lang] # lang 属性等于 en //title[langen] # 多属性条件 //input[typetext and nameusername] # 属性包含某值 //div[contains(class, header)] # 属性以某值开头 //a[starts-with(href, https)]5.3 文本谓词# 文本完全匹配 //a[text()登录] # 文本包含 //button[contains(text(), 提交)] # normalize-space 去除空白后匹配 //div[normalize-space(text())Hello World]5.4 逻辑运算符# and //book[categorycooking and price25] # or //book[price10 or price50] # not() //div[not(class)] # ! //title[lang!en]六、XPath 内置函数XPath 1.0 提供了丰富的内置函数分为四大类。6.1 节点集函数函数说明last()当前节点集中最后一个节点的位置position()当前节点在节点集中的位置从1开始count(node-set)返回节点集中的节点数量name(node-set?)返回节点的名称local-name(node-set?)返回不带命名空间前缀的名称namespace-uri(node-set?)返回命名空间 URI6.2 字符串函数函数说明string(obj?)将对象转换为字符串concat(string, string, ...)字符串拼接contains(s1, s2)s1 是否包含 s2starts-with(s1, s2)s1 是否以 s2 开头substring(s, start, len?)截取子串substring-before(s1, s2)s2 之前的部分substring-after(s1, s2)s2 之后的部分string-length(s?)字符串长度normalize-space(s?)去除首尾空白合并中间空白translate(s1, s2, s3)字符替换6.3 数值函数函数说明number(obj?)转换为数字sum(node-set)节点集数值求和floor(num)向下取整ceiling(num)向上取整round(num)四舍五入6.4 布尔函数函数说明boolean(obj)转换为布尔值not(condition)逻辑非true()返回 truefalse()返回 falselang(string)判断节点语言七、XPath 运算符7.1 完整运算符列表运算符说明示例|节点集合并//h1 | //h2加法price 10-减法price - 5*乘法price * 1.1div除法price div 2mod取模position() mod 2等于id1!不等于class!hidden小于price10小于等于price10大于price10大于等于price10and逻辑与a and bor逻辑或a or b注意XPath 中除法用div取模用mod不能用/和%。八、实战场景HTML 元素定位8.1 Selenium 常用定位技巧fromseleniumimportwebdriverfromselenium.webdriver.common.byimportBy driverwebdriver.Chrome()# 1. 通过 id 定位driver.find_element(By.XPATH,//*[idusername])# 2. 通过 class 定位注意 class 是多值属性driver.find_element(By.XPATH,//div[contains(class, login-form)])# 3. 通过文本定位driver.find_element(By.XPATH,//button[text()登录])# 4. 通过父子关系定位driver.find_element(By.XPATH,//form[idlogin]//input[typesubmit])# 5. 通过兄弟节点定位driver.find_element(By.XPATH,//label[text()密码]/following-sibling::input)# 6. 通过索引定位从1开始driver.find_element(By.XPATH,(//table//tr)[2]/td[3])8.2 Python lxml 解析示例fromlxmlimportetree html html body ul classmenu lia href9/home首页/a/li lia href/about关于/a/li lia href/contact联系/a/li /ul /body /html treeetree.HTML(html)# 获取所有链接文本textstree.xpath(//ul[classmenu]//a/text())print(texts)# [首页, 关于, 联系]# 获取所有 href 属性hrefstree.xpath(//ul[classmenu]//a/href)print(hrefs)# [/home, /about, /contact]# 同时获取文本和属性itemstree.xpath(//ul[classmenu]//a)foriteminitems:print(item.text,item.get(href))九、高级技巧与注意事项9.1 XPath 轴的组合使用# 找到当前 td 所在行的第一个 td ./ancestor::tr/td[1] # 找到当前元素前面最近的一个 h2 ./preceding::h2[1] # 找到当前 div 的下一个兄弟 section ./following-sibling::section[1]9.2 常见陷阱索引从 1 开始XPath 的位置索引从 1 开始不是 0class 属性是多值的classbtn只能匹配完全等于 btn 的元素推荐用contains(class, btn)text() 只取直接子文本如果元素内有嵌套标签text()只取直接文本节点用.或string()获取全部文本命名空间问题有命名空间的文档需要注册命名空间才能正确查询谓词中的 and/orXPath 用and/or不是/||9.3 性能优化建议优先使用//会扫描整个文档尽量缩小范围如//div[idmain]//a避免使用//*全文档扫描属性定位比文本定位更稳定复杂页面优先使用 id 或唯一 class 作为锚点十、总结XPath 是一门强大而简洁的查询语言掌握它的核心在于理解节点模型把 XML/HTML 看作节点树熟练路径表达式/、//、.、..、是基础善用轴定位轴是 XPath 区别于 CSS 选择器的核心优势灵活运用谓词谓词让定位更精确掌握常用函数contains、text()、position()等是高频使用无论是爬虫、自动化测试还是数据解析XPath 都是不可或缺的工具。希望本文能帮助你系统掌握 XPath 语法。如果本文对你有帮助欢迎点赞、收藏、关注三连支持
返回列表