XPath是什么?
- XPath 的全称为 XML Path Language
- XPath使用路径形式的格式来标识XML格式文档中的节点
- XPath是XSLT标准中主要的一部分
- XPath 是W3C推荐的一个标准
通俗的说: XPath就是一种在HTML中寻找节点的语法.
例如一个简单的例子:
<div class="cooking">
<span lang="en">Everyday Italian</span>
</div>
获取其中的span元素,可以通过Xpath /div/span 来完成
XPath在爬虫框架CasperJS和Selenium中大量的使用,但在Google出的最新爬虫框架Puppeteer中使用的是JQuery的Selector, 后续会单独写一篇文章介绍。
XPath 不仅仅是这么简单,它有200多种内置的路径表达方式,下面我们来看几个主要的概念
1.节点 (Nodes)
每个节点就是一个独立完整的Tag标签或者是独立的值, 例如:
<author>J K. Rowling</author> (节点 - 独立的标签)
J K. Rowling (节点 - 独立的值)
节点有以下属性:
-
Parent (父节点, 0到1个)
比如在上面简单的例子中,Span节点的父节点是div节点. -
Children (子节点, 0到多个)
比如在上面简单的例子中,div节点的子点是span节点. -
Siblings (邻居节点,0到多个)
比如在以下的html中,input的邻居节点有span节点和table节点
<div>
<span>input your name</span>
<input> </input>
<table> </table>
</div>
- Ancestors (祖先节点, 0到多个)
比如在以下的html中,span节点的祖先节点有 div节点和body节点
<body>
<div>
<span>
text
</span>
</div>
</body>
- Descendants(后辈节点, 0到多个)
比如在上一个html中, body节点的后辈节点有div节点和span节点.
2. 语法 (Syntax)
比较常用的语法就7种,熟练使用这些基本上就足够用来寻找大部分的节点了。
-
节点名字 - 选择所有该名字的节点
比如 div 就表示选择所有div节点. -
/ - 根节点,表示目标文档中的最顶部节点。
例如 /div, 就表示选择在目标文档顶部节点下的所有div节点。 注意只是在root节点下,跨层的孙辈节点就不包含在内了, 例如 /body/div 就不属于/div的选择了 -
// 当前节点下寻找,这里的寻找是不限制层级的,即当前节点下的所有后辈节点都会被搜索。
例如使用 Selenium 可以有以下的写法:
inputDiv = driver.find_element_by_xpath("//div[@class='login']")
inputElementUsername = inputDiv.find_element_by_xpath("//input[@name='email']")
其中第一句是需拿在文档中寻找登陆div (这里driver指代当前页面), 第二句就是在找到的登陆div中 寻找email的输入框。 这里输入框并不一定在登陆div的第一层下。
- . - 当前节点
.. - 父节点
这两个语法的含义和命令行中的.与..是一致的, . 代表当前节点 ..代表父节点 :
../button 在当前节点的父节点中寻找button节点
./button 在当前节点中寻找button节点
- @ 属性选择, 在上面的例子中有出现过,当选择节点的时候,不仅仅可以通过节点名字来区别,还可以额外增加节点的属性。 例如下面的html
<body>
<div class="a"> a </div>
<div class="b"> b </div>
</body>
当要获取body下的a div时, 可以通过指定class属性来寻找节点
//div[@class="a"]
- 声明 (Predicates)
利用之前的几个语法已经可以完成节点定位的, 而这里的声明 (Predicates) 提供了一些高效率的节点定位函数:
/bookstore/book[1] - 选择第一个符合条件的book节点
/bookstore/book[last()] - 选择最后一个符合条件的book节点
/bookstore/book[last()-1] - 选择倒数第二个符合条件的book节点
/bookstore/book[position()<3] - 选择前二个符合条件的book节点,位置小于3,即1,2
/bookstore/book[price>35.00] - 选择价格属性大于35的book节点, 这个price属于属性,可以根据需要调整
-
通配符
这个只需要了解 * 代表任意节点, 其他的没什么用 -
多重路径选择
通过 | 可以选择若干个路径, 例如:
//book/title | //book/price - 选择所有在book节点下的title和price节点
3. 例子
这里针对一些复杂情况做说明并举例,如有需要请留言
- 如何定位有多个class属性的元素?
方法1 可以通过空格间隔写入多个class
"//button[@class='btn btn-netease btn-sm js-btn-ok']"
方法2 可以使用 and 连接多个class属性
"//a[contains(@class,'btn') and contains(@class,'page_next')]"
网友评论