XPath,全称 XML Path Language,即 XML 路径语言,它是一门在XML文档中查找信息的语言。XPath 最初设计是用来搜寻XML文档的,但是它同样适用于 HTML 文档的搜索。
我们现用表格列举一下几个常用规则:
表达式描述 nodename选取此节点的所有子节点 /从当前节点选取直接子节点 //从当前节点选取子孙节点 .选取当前节点 ..选取当前节点的父节点 @选取属性
在这里列出了XPath的常用匹配规则,例如 / 代表选取直接子节点,// 代表选择所有子孙节点,. 代表选取当前节点,.. 代表选取当前节点的父节点,@ 则是加了属性的限定,选取匹配属性的特定节点。
// 所有节点
html = etree.parse('./test.html', etree.HTMLParser())
result = html.xpath('//*')
// 子节点
result = html.xpath('//li/a')
// 父节点
result = html.xpath('//a[@href="https://ask.hellobi.com/link4.html"]/../@class')(html.xpath('//a[@href="https://ask.hellobi.com/link4.html"]/parent::*/@class'))
// 属性匹配
result = html.xpath('//li[@class="item-0"]')
// 文本获取
result = html.xpath('//li[@class="item-0"]/text()')
// 属性获取
result = html.xpath('//li/a/@href')
// 属性多值
contains() 方法,第一个参数传入属性名称,第二个参数传入属性值
text = '''
<li class="li li-first"><a href="https://ask.hellobi.com/link.html">first item</a></li>
'''
html = etree.HTML(text)
result = html.xpath('//li[contains(@class, "li")]/a/text()')
(匹配多个属性可以使用运算符 and 来连接)
result = html.xpath('//li[contains(@class, "li") and @name="item"]/a/text()')
// 按序选择
/**
第一次选择我们选取了第一个 li 节点,中括号中传入数字1即可,注意这里和代码中不同,序号是以 1 开头的,不是 0 开头的。
第二次选择我们选取了最后一个 li 节点,中括号中传入 last() 即可,返回的便是最后一个 li 节点。
第三次选择我们选取了位置小于 3 的 li 节点,也就是位置序号为 1 和 2 的节点,得到的结果就是前 2 个 li 节点。
第四次选择我们选取了倒数第三个 li 节点,中括号中传入 last()-2即可,因为 last() 是最后一个,所以 last()-2 就是倒数第三个。
*/
result = html.xpath('//li[1]/a/text()')
result = html.xpath('//li[last()]/a/text()')
result = html.xpath('//li[position()<3]/a/text()')
result = html.xpath('//li[last()-2]/a/text()')
// 节点轴选择
/**
第一次选择我们调用了 ancestor 轴,可以获取所有祖先节点,其后需要跟两个冒号,然后是节点的选择器,这里我们直接使用了 *,表示匹配所有节点,因此返回结果是第一个 li 节点的所有祖先节点,包括 html,body,div,ul。
第二次选择我们又加了限定条件,这次在冒号后面加了 div,这样得到的结果就只有 div 这个祖先节点了。
第三次选择我们调用了 attribute 轴,可以获取所有属性值,其后跟的选择器还是 *,这代表获取节点的所有属性,返回值就是 li 节点的所有属性值。
第四次选择我们调用了 child 轴,可以获取所有直接子节点,在这里我们又加了限定条件选取 href 属性为 link1.html 的 a 节点。
第五次选择我们调用了 descendant 轴,可以获取所有子孙节点,这里我们又加了限定条件获取 span 节点,所以返回的就是只包含 span 节点而没有 a 节点。
第六次选择我们调用了 following 轴,可以获取当前节点之后的所有节点,这里我们虽然使用的是 * 匹配,但又加了索引选择,所以只获取了第二个后续节点。
第七次选择我们调用了 following-sibling 轴,可以获取当前节点之后的所有同级节点,这里我们使用的是 * 匹配,所以获取了所有后续同级节点。
https://www.w3school.com.cn/xpath/xpath_axes.asp
*/
result = html.xpath('//li[1]/ancestor::*')
result = html.xpath('//li[1]/ancestor::div')
result = html.xpath('//li[1]/attribute::*')
result = html.xpath('//li[1]/child::a[@href="https://ask.hellobi.com/link1.html"]')
result = html.xpath('//li[1]/descendant::span')
result = html.xpath('//li[1]/following::*[2]')
result = html.xpath('//li[1]/following-sibling::*')
print(result)