一. 什么是Xpath?
XPath 是 XML 的查询语言,本节介绍该语言的语法。
XPath 使用路径表达式来选取 XML 文档中的节点或节点集。节点是通过沿着路径 (path) 或者步 (steps) 来选取的。
二. 快速使用
1. 前期准备
doc = '''
<html>
<head>
<base href='http://example.com/' />
<title>Example website</title>
</head>
<body>
<div id='images'>
<a href='image1.html' aa='bb'>Name: My image 1 <br /><img src='image1_thumb.jpg' /></a>
<a href='image2.html'>Name: My image 2 <br /><img src='image2_thumb.jpg' /></a>
<a href='image3.html'>Name: My image 3 <br /><img src='image3_thumb.jpg' /></a>
<a href='image4.html'>Name: My image 4 <br /><img src='image4_thumb.jpg' /></a>
<a href='image5.html' class='li li-item' name='items'>Name: My image 5 <br /><img src='image5_thumb.jpg' /></a>
<a href='image6.html' name='items'><span><h5>test</h5></span>Name: My image 6 <br /><img src='image6_thumb.jpg' /></a>
</div>
</body>
</html>
'''
2. 调用使用
from lxml import etree
html = etree.HTML(doc)
# html=etree.parse('search.html',etree.HTMLParser())
3. 所有节点
a = html.xpath('//*')
print(a)
'''
[<Element html at 0x1739ea9d108>, <Element head at 0x1739ed18548>, <Element base at 0x1739ed184c8>, <Element title at 0x1739ed18588>, <Element body at 0x1739ed185c8>, <Element div at 0x1739ed18648>, <Element a at 0x1739ed18688>, <Element br at 0x1739ed186c8>, <Element img at 0x1739ed18708>, <Element a at 0x1739ed18608>, <Element br at 0x1739ed18748>, <Element img at 0x1739ed18788>, <Element a at 0x1739ed187c8>, <Element br at 0x1739ed18808>, <Element img at 0x1739ed18848>, <Element a at 0x1739ed18888>, <Element br at 0x1739ed188c8>, <Element img at 0x1739ed18908>, <Element a at 0x1739ed18948>, <Element br at 0x1739ed18988>, <Element img at 0x1739ed189c8>, <Element a at 0x1739ed18a08>, <Element span at 0x1739ed18a48>, <Element h5 at 0x1739ed18a88>, <Element br at 0x1739ed18ac8>, <Element img at 0x1739ed18b08>]
'''
4. 指定节点(结果为列表)
a = html.xpath('//head')
print(a) # [<Element head at 0x29d0dff8548>]
5. 子节点,子孙节点
a = html.xpath('//div/a')
print(a)
'''
[<Element a at 0x20093fe85c8>, <Element a at 0x20093fe8548>, <Element a at 0x20093fe8608>, <Element a at 0x20093fe8648>, <Element a at 0x20093fe8688>, <Element a at 0x20093fe8708>]
'''
a = html.xpath('//body/a') # 无数据
print(a) # []
a = html.xpath('//body//a')
print(a)
'''
[<Element a at 0x20093fe86c8>, <Element a at 0x20093fe85c8>, <Element a at 0x20093fe8548>, <Element a at 0x20093fe8608>, <Element a at 0x20093fe8648>, <Element a at 0x20093fe8708>]
'''
5. 父节点
a = html.xpath('//body//a[@href="image1.html"]/..')
print(a) # [<Element div at 0x2afcd6e8588>]
a = html.xpath('//body//a[1]/..')
print(a) # [<Element div at 0x2afcd6e8588>]
# 也可以这样
a = html.xpath('//body//a[1]/parent::*')
print(a) # [<Element div at 0x2afcd6e8588>]
6. 属性匹配
a = html.xpath('//body//a[@href="image1.html"]')
print(a) # [<Element a at 0x18ae52784c8>]
7. 文本获取: /text() 取当前标签的文本
a = html.xpath('//body//a[@href="image1.html"]/text()')
print(a) # ['Name: My image 1 ']
a = html.xpath('//body//a/text()')
print(a)
'''
['Name: My image 1 ', 'Name: My image 2 ', 'Name: My image 3 ', 'Name: My image 4 ', 'Name: My image 5 ', 'Name: My image 6 ']
'''
8. 属性获取: @href 取当前标签的属性
a = html.xpath('//body//a/@href')
print(a)
'''
['image1.html', 'image2.html', 'image3.html', 'image4.html', 'image5.html', 'image6.html']
'''
# 注意从1 开始取(不是从0)
a = html.xpath('//body//a[1]/@href')
print(a) # ['image1.html']
9. 属性多值匹配
# a 标签有多个class类,直接匹配就不可以了,需要用contains
a = html.xpath('//body//a[@class="li"]')
print(a) # []
a = html.xpath('//body//a[contains(@class,"li")]')
print(a) # [<Element a at 0x2de3717c548>]
a = html.xpath('//body//a[contains(@class,"li")]/text()')
print(a) # ['Name: My image 5 ']
10. 多属性匹配
a = html.xpath('//body//a[contains(@class,"li") or @name="items"]')
print(a) # [<Element a at 0x26440c6c548>, <Element a at 0x26440c6c4c8>]
a = html.xpath('//body//a[contains(@class,"li") and @name="items"]/text()')
print(a) # ['Name: My image 5 ']
a = html.xpath('//body//a[contains(@class,"li")]/text()')
print(a) # ['Name: My image 5 ']
11. 按序选择
a = html.xpath('//a[2]/text()')
print(a) # ['Name: My image 2 ']
a = html.xpath('//a[2]/@href')
print(a) # ['image2.html']
# 取最后一个
a = html.xpath('//a[last()]/@href')
print(a) # ['image6.html']
# 位置小于3的
a = html.xpath('//a[position()<3]/@href')
print(a) # ['image1.html', 'image2.html']
# 倒数第二个
a = html.xpath('//a[last()-2]/@href')
print(a) # ['image4.html']
12. 节点轴选择
1) ancestor:祖先节点
# 使用了* 获取所有祖先节点
a = html.xpath('//a/ancestor::*')
print(a) # [<Element html at 0x1ed8898d108>, <Element body at 0x1ed88c28608>, <Element div at 0x1ed88c28588>]
# 获取祖先节点中的div
a = html.xpath('//a/ancestor::div')
print(a) # [<Element div at 0x1ed88c28588>]
# attribute:属性值
a = html.xpath('//a[1]/attribute::*')
print(a) # ['image1.html', 'bb']
a = html.xpath('//a[1]/@aa')
print(a) # ['bb']
2) child:直接子节点
a = html.xpath('//a[1]/child::*')
print(a) # [<Element br at 0x1ec054e8588>, <Element img at 0x1ec054e8608>]
a = html.xpath('//a[1]/child::img/@src')
print(a) # ['image1_thumb.jpg']
3) descendant:所有子孙节点
a = html.xpath('//a[6]/descendant::*')
print(a) # [<Element span at 0x20b3d2ab588>, <Element h5 at 0x20b3d2ab5c8>, <Element br at 0x20b3d2ab608>, <Element img at 0x20b3d2ab648>]
a = html.xpath('//a[6]/descendant::h5/text()')
print(a) # ['test']
4) following: 当前节点之后所有节点(兄弟节点和兄弟内部的节点)
a = html.xpath('//a[1]/following::*')
print(a)
'''
[<Element a at 0x20749da2548>, <Element br at 0x20749da24c8>, <Element img at 0x20749da2588>, <Element a at 0x20749da25c8>, <Element br at 0x20749da2608>, <Element img at 0x20749da2688>, <Element a at 0x20749da26c8>, <Element br at 0x20749da2708>, <Element img at 0x20749da2748>, <Element a at 0x20749da2648>, <Element br at 0x20749da2788>, <Element img at 0x20749da27c8>, <Element a at 0x20749da2808>, <Element span at 0x20749da2848>, <Element h5 at 0x20749da2888>, <Element br at 0x20749da28c8>, <Element img at 0x20749da2908>]
'''
a = html.xpath('//a[1]/following::*[1]/@href')
print(a) # ['image2.html']
5) following-sibling:当前节点之后同级节点(只找兄弟)
a = html.xpath('//a[1]/following-sibling::*')
print(a)
'''
[<Element a at 0x20749da2548>, <Element a at 0x20749da2588>, <Element a at 0x20749da25c8>, <Element a at 0x20749da2608>, <Element a at 0x20749da2688>]
'''
a = html.xpath('//a[1]/following-sibling::a')
print(a)
'''
[<Element a at 0x20749da2548>, <Element a at 0x20749da2588>, <Element a at 0x20749da25c8>, <Element a at 0x20749da2608>, <Element a at 0x20749da2688>]
'''
a = html.xpath('//a[1]/following-sibling::*[2]')
print(a) # [<Element a at 0x20749da2588>]
a = html.xpath('//a[1]/following-sibling::*[2]/@href')
print(a) # ['image3.html']
三. xpath语法参考表
1. 选取节点
XPath 使用路径表达式在 XML 文档中选取节点。节点是通过沿着路径或者 step 来选取的。 下面列出了最有用的路径表达式:
表达式 | 描述 |
---|---|
nodename | 选取此节点的所有子节点。 |
/ | 从根节点选取。 |
// | 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。 |
. | 选取当前节点。 |
.. | 选取当前节点的父节点。 |
@ | 选取属性。 |
在下面的表格中,我们已列出了一些路径表达式以及表达式的结果:
路径表达式 | 结果 |
---|---|
bookstore | 选取 bookstore 元素的所有子节点。 |
/bookstore | 选取根元素 bookstore。注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径! |
bookstore/book | 选取属于 bookstore 的子元素的所有 book 元素。 |
//book | 选取所有 book 子元素,而不管它们在文档中的位置。 |
bookstore//book | 选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置。 |
//@lang | 选取名为 lang 的所有属性。 |
提示:如果 XPath 的开头是一个斜线(/)代表这是绝对路径。如果开头是两个斜线(//)表示文件中所有符合模式的元素都会被选出来,即使是处于树中不同的层级也会被选出来。
1. 谓语(Predicates)
谓语用来查找某个特定的节点或者包含某个指定的值的节点。
谓语被嵌在方括号中。
在下面的表格中,我们列出了带有谓语的一些路径表达式,以及表达式的结果:
路径表达式 | 结果 |
---|---|
/bookstore/book[1] | 选取属于 bookstore 子元素的第一个 book 元素。 |
/bookstore/book[last()] | 选取属于 bookstore 子元素的最后一个 book 元素。 |
/bookstore/book[last()-1] | 选取属于 bookstore 子元素的倒数第二个 book 元素。 |
/bookstore/book[position()❤️] | 选取最前面的两个属于 bookstore 元素的子元素的 book 元素。 |
//title[@lang] | 选取所有拥有名为 lang 的属性的 title 元素。 |
//title[@lang='eng'] | 选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。 |
/bookstore/book[price>35.00] | 选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。 |
/bookstore/book[price>35.00]/title | 选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。 |
3. 选取未知节点
XPath 通配符可用来选取未知的 XML 元素。
通配符 | 描述 |
---|---|
* | 匹配任何元素节点。 |
@* | 匹配任何属性节点。 |
node() | 匹配任何类型的节点。 |
在下面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:
路径表达式 | 结果 |
---|---|
/bookstore/* | 选取 bookstore 元素的所有子元素。 |
//* | 选取文档中的所有元素。 |
//title[@*] | 选取所有带有属性的 title 元素。 |
4. 选取若干路径
通过在路径表达式中使用"|"运算符,您可以选取若干个路径。
在下面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:
路径表达式 | 结果 |
---|---|
//book/title | //book/price | 选取 book 元素的所有 title 和 price 元素。 |
//title | //price | 选取文档中的所有 title 和 price 元素。 |
/bookstore/book/title | //price | 选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素。 |
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:04 爬虫解析库之xpath库 - Python技术站