赞
踩
阅读指导:
这篇文章详细讲解了XPath解析的方法。每个方法都配有相应的代码示例,读者可以通过本文更深入地了解XPath。由于文章篇幅较长,建议通过目录选择您感兴趣的部分进行学习。
XPath(XML Path Language)是一种用于在 XML 文档中查找和选取节点的语言。它提供了一种通过路径表达式来导航 XML 文档的方法。
其优点在于:
表达式 | 描述 |
---|---|
// | 从当前节点,选取其子孙结点 |
/ | 从当前节点,选取其直接子节点 |
. | 选取当前节点 |
.. | 选取当前节点的父节点 |
@ | 选取属性 |
nodename | 选取此节点的所有子节点 |
通过 // 方式来获取所有符合要求的结点
比如:
//* 选取所有节点
//li 选取所有 li 节点
//ul 选取所有 ul 节点
//a 选取多有 a 节点
获取到节点后,返回的是列表元素,每个元素都是ELement类型,可以通过索引的方式获取
示例HTML:
<!-- ./test.html文件 -->
<div>
<ul>
<li class="item-0"><a href="link1.html">first item</a></li>
<li class="item-1"><a href="link2.html">second item</a></li>
<li class="item-inactive"><a href="link3.html">third item</a></li>
<li class="item-1"><a href="link4.html">fourth item</a></li>
<li class="item-0"><a href="link5.html">fifth item</a>
</ul>
</div>
获取 li 元素下的 a 元素
from lxml import etree
html = etree.parse('./test.html', etree.HTMLParser())
result = html.xpath('//li')
print(result)
print(type(result))
print(result[0])
输出:
[<Element li at 0x1905f6f6640>, <Element li at 0x1905f6f6680>, <Element li at 0x1905f6f66c0>, <Element li at 0x1905f6f6700>, <Element li at 0x1905f6f6740>]
<class 'list'>
<Element li at 0x1905f6f6640>
通过 / 和 // 来获取当前元素的子,子孙节点
但是要注意
/ 只获取直接子节点, // 用于获取子孙节点
获取所有 li 元素的 a 标签
from lxml import etree
html = etree.parse('./test.html', etree.HTMLParser())
result = html.xpath('//li/a')
print(result)
print(result[0])
输出:
[<Element a at 0x1a676cd6500>, <Element a at 0x1a676cd6540>, <Element a at 0x1a676cd6580>, <Element a at 0x1a676cd65c0>, <Element a at 0x1a676cd6600>]
<Element a at 0x1a676cd6500>
通过 .. 的方式获取
比如:
获取 li 的class属性值
<li class="item-1"><a href="link4.html">fourth item</a></li>
获取代码:
from lxml import etree
html = etree.parse('./test.html', etree.HTMLParser())
result = html.xpath('//a[@href="link4.html"]/../@class')
print(result)
输出:
['item-1']
代码解释:
首先是定位到超链接为“link4.html”的 a 标签,然后向上翻一级,也就是到了 li 元素,然后再查找这个 a 标签对应的 li 的 class 属性值,即最后的输出为[‘item-1’]
像1.1.4所示,该节点使用 @ 符号来定位其属性,所以通过 @ 符号可以实现属性的过滤。
基本语法:[@a = “b”]
比如 [@class = “abc”],[@herf= “link”]
例:
获取class为“item-0”的 li 标签
<li class="item-0"><a href="link1.html">first item</a></li>
<li class="item-0"><a href="link5.html">fifth item</a>
获取代码:
from lxml import etree
html = etree.parse('./test.html', etree.HTMLParser())
result = html.xpath('//li[@class="item-0"]')
print(result)
输出:
[<Element li at 0x1d7dde06680>, <Element li at 0x1d7dde066c0>]
属性值的获取也是用 @ 符号,但是与属性匹配不同的是,属性匹配需要用总括号加属性名和值来限定某个属性
获取所有 li 标签下的 a 标签的 herf 的值
from lxml import etree
html = etree.parse('./test.html', etree.HTMLParser())
result = html.xpath('//li/a/@href')
print(result)
输出:
['link1.html', 'link2.html', 'link3.html', 'link4.html', 'link5.html']
对于一个节点的某个属性含多个属性值时,使用contains方法定位元素。
contains()传两个参数,第一个是属性名,第二个是属性名中的其中一个属性值。
例:
获取class属性值里面含 “li” 的 li 标签的 a 标签下的文字
<!--./text-->
<li class="li li-first"><a href="link.html">first item</a></li>
获取代码:
from lxml import etree
html = etree.HTML(./text)
result = html.xpath('//li[contains(@class, "li")]/a/text()')
print(result)
输出:
['first item']
对于一个节点具有多个属性时,使用 and 运算符连接多个属性
例:
获取class属性值含 “li” 和 name 属性值为 “item” 的 li 标签下的 a 标签的文字部分
<!--./text-->
<li class="li li-first" name="item"><a href="link.html">first item</a></li>
获取代码:
from lxml import etree
html = etree.HTML(./text)
result = html.xpath('//li[contains(@class, "li") and @name="item"]/a/text()')
print(result)
输出:
['first item']
当某个属性对应多个节点时,就需要对节点进行选择
字面意思,即是通过索引的方式进行选择,但是不同于代码思维的一点就是,索引的第一个数是1,不是0
例:
以索引的形式,获取 li 标签下的 a 标签的文字内容
<!--./text-->
<div>
<ul>
<li class="item-0"><a href="link1.html">first item</a></li>
<li class="item-1"><a href="link2.html">second item</a></li>
<li class="item-inactive"><a href="link3.html">third item</a></li>
<li class="item-1"><a href="link4.html">fourth item</a></li>
<li class="item-0"><a href="link5.html">fifth item</a>
</ul>
</div>
获取代码:
from lxml import etree
html = etree.HTML(./text)
result = html.xpath('//li[1]/a/text()')
print(result)
result = html.xpath('//li[last()]/a/text()')
print(result)
result = html.xpath('//li[position()<3]/a/text()')
print(result)
result = html.xpath('//li[last()-2]/a/text()')
print(result)
输出:
['first item']
['fifth item']
['first item', 'second item']
['third item']
<!-- ./test.html文件 -->
<div>
<ul>
<li class="item-0"><a href="link1.html">first item</a></li>
<li class="item-1"><a href="link2.html">second item</a></li>
<li class="item-inactive"><a href="link3.html">third item</a></li>
<li class="item-1"><a href="link4.html">fourth item</a></li>
<li class="item-0"><a href="link5.html">fifth item</a>
</ul>
</div>
使用text()方式,获取该元素下的直接文字内容
比较下面三种方式获取文字的信息
获取代码:
from lxml import etree
html = etree.parse('./test.html', etree.HTMLParser())
result = html.xpath('//li[@class="item-0"]/text()')
print(result)
result = html.xpath('//li[@class="item-0"]/a/text()')
print(result)
result = html.xpath('//li[@class="item-0"]//text()')
print(result)
输出:
['\n ']
['first item', 'fifth item']
['first item', 'fifth item', '\n ']
代码解释:
第一种是访问class属性为“item-0”的 li 标签下的文字,但是在这行代码里面,li 标签的下一级是 a 标签,没有文字,只有换行符,所以输出也就是['\n ']
第二种这是访问class属性为“item-0”的 li 标签的 a 标签下的文字,所以输出是[‘first item’, ‘fifth item’]
第三种是访问class属性为“item-0”的 li 标签下所有子孙节点的文本,同时也包含了转义字符,所以输出为[‘first item’, ‘fifth item’, '\n ']
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。