python xpath查找元素
下面的文本部分摘抄自:W3school
选取节点
XPath 使用路径表达式在 XML 文档中选取节点。节点是通过沿着路径或者 step 来选取的。
下面列出了最有用的路径表达式:
表达式 | 描述 |
---|---|
nodename | 选取此节点的所有子节点。 |
/ | 从根节点选取。 |
// | 从当前节点开始选择文档中的任意匹配节点,而不考虑它们的位置(即从当前节点以下的任意层级的节点)。 |
. | 选取当前节点。 |
.. | 选取当前节点的父节点。 |
@ | 选取属性。 |
实例
针对这个文档:
<?xml version="1.0" encoding="ISO-8859-1"?>
<bookstore>
<book>
<title lang="eng">Harry Potter</title>
<price>29.99</price>
</book>
<book>
<title lang="eng">Learning XML</title>
<price>39.95</price>
</book>
</bookstore>
针对上面的文档,我们已列出了一些路径表达式以及表达式的结果:
路径表达式 | 结果 |
---|---|
bookstore | 选取 bookstore 元素的所有子节点。 |
/bookstore | 选取根元素 bookstore。注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径! |
bookstore/book | 选取属于 bookstore 的子元素的所有 book 元素。 |
//book | 选取所有 book 子元素,而不管它们在文档中的位置。 |
bookstore//book | 选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置。 |
//@lang | 选取名为 lang 的所有属性。 |
谓语定位
谓语可以起到限定作用,用中括号:[]
表示。
譬如:
//div/a[@href='www.baidu.com'] # 获取所有 div 下的 a 元素们;但是 a 元素的 href 属性必须是:www.baidu.com
//div[a=20] # 获取所有的 div 标签。但是每一个 div标签 下必须有 a标签,并且 a 标签的内容要等于 20;
//div[1] # 获取第一个 div 标签,[1] 代表选取第一个元素,等同于 //div[position()=1]。
(//div)[1] # 获取第一个 div 标签。和上面 '//div[1]' 作用一样,但是有时候 '//div[1]' 不生效,因此最好使用这种形式。
//div[@name="ddd" and @class="xxx"] # 谓语中可以同时满足多个条件,支持 and, or
实例
在下面的表格中,我们列出了带有谓语的一些路径表达式,以及表达式的结果:
路径表达式 | 结果 |
---|---|
/bookstore/book[1] | 选取属于 bookstore 子元素的第一个 book 元素。 |
/bookstore/book[last()] | 选取属于 bookstore 子元素的最后一个 book 元素。 |
/bookstore/book[last()-1] | 选取属于 bookstore 子元素的倒数第二个 book 元素。 |
/bookstore/book[position()<3] |
选取最前面的两个属于 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。 |
选取未知节点
XPath 通配符可用来选取未知的 XML 元素。
通配符 | 描述 |
---|---|
* | 匹配任何元素节点。 |
@* | 匹配任何属性节点。 |
node() | 匹配任何类型的节点。 |
实例
在下面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:
路径表达式 | 结果 |
---|---|
/bookstore/* | 选取 bookstore 元素的所有子元素。 |
//* | 选取文档中的所有元素。 |
//title[@*] | 选取所有带有属性的 title 元素。 |
选取若干路径
通过在路径表达式中使用 |
运算符,您可以选取若干个路径。
实例
在下面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:
路径表达式 | 结果 |
---|---|
//book/title | //book/price | 选取 book 元素的所有 title 和 price 元素。 |
//title | //price | 选取文档中的所有 title 和 price 元素。 |
/bookstore/book/title | //price | 选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素。 |
XPath 轴
轴可定义相对于当前节点的节点集。
轴名称 | 结果 |
---|---|
ancestor | 选取当前节点的所有先辈(父、祖父等)。 |
ancestor-or-self | 选取当前节点的所有先辈(父、祖父等)以及当前节点本身。 |
attribute | 选取当前节点的所有属性。 |
child | 选取当前节点的所有子元素。 |
descendant | 选取当前节点的所有后代元素(子、孙等)。 |
descendant-or-self | 选取当前节点的所有后代元素(子、孙等)以及当前节点本身。 |
following | 选取文档中当前节点的结束标签之后的所有节点。 |
namespace | 选取当前节点的所有命名空间节点。 |
parent | 选取当前节点的父节点。 |
preceding | 选取文档中当前节点的开始标签之前的所有节点。 |
preceding-sibling | 选取当前节点之前的所有同级节点。 |
self | 选取当前节点。 |
语法:
轴名称::节点测试[谓语]
轴(axis)
- 定义所选节点与当前节点之间的树关系
节点测试(node-test)
- 识别某个轴内部的节点
零个或者更多谓语(predicate)
- 更深入地提炼所选的节点集
实例
例子 | 结果 |
---|---|
child::book | 选取所有属于当前节点的子元素的 book 节点。 |
attribute::lang | 选取当前节点的 lang 属性。 |
child:😗 | 选取当前节点的所有子元素。 |
attribute:😗 | 选取当前节点的所有属性。 |
child::text() | 选取当前节点的所有文本子节点。 |
child::node() | 选取当前节点的所有子节点。 |
descendant::book | 选取当前节点的所有 book 后代。 |
ancestor::book | 选择当前节点的所有 book 先辈。 |
ancestor-or-self::book | 选取当前节点的所有 book 先辈以及当前节点(如果此节点是 book 节点) |
child:😗/child::price | 选取当前节点的所有 price 孙节点。 |
XPath 运算符
下面列出了可用在 XPath 表达式中的运算符:
运算符 | 描述 | 实例 | 返回值 |
---|---|---|---|
| | 计算两个节点集 | //book | //cd | 返回所有拥有 book 和 cd 元素的节点集 |
+ | 加法 | 6 + 4 | 10 |
- | 减法 | 6 - 4 | 2 |
* | 乘法 | 6 * 4 | 24 |
div | 除法 | 8 div 4 | 2 |
= | 等于 | price=9.80 | 如果 price 是 9.80,则返回 true。如果 price 是 9.90,则返回 false。 |
!= | 不等于 | price!=9.80 | 如果 price 是 9.90,则返回 true。如果 price 是 9.80,则返回 false。 |
< | 小于 | price<9.80 | 如果 price 是 9.00,则返回 true。如果 price 是 9.90,则返回 false。 |
<= | 小于或等于 | price<=9.80 | 如果 price 是 9.00,则返回 true。如果 price 是 9.90,则返回 false。 |
> | 大于 | price>9.80 | 如果 price 是 9.90,则返回 true。如果 price 是 9.80,则返回 false。 |
>= | 大于或等于 | price>=9.80 | 如果 price 是 9.90,则返回 true。如果 price 是 9.70,则返回 false。 |
or | 或 | price=9.80 or price=9.70 | 如果 price 是 9.80,则返回 true。如果 price 是 9.50,则返回 false。 |
and | 与 | price>9.00 and price<9.90 | 如果 price 是 9.80,则返回 true。如果 price 是 8.50,则返回 false。 |
mod | 计算除法的余数 | 5 mod 2 | 1 |
示例代码:
# 需要先安装第三方模块lxml
import lxml.etree as etree
html = """
<!DOCTYPE html>
<html>
<head lang="en">
<title>xpath测试</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head>
<body>
<div id="content">
<ul id="ul">
<li>NO.1</li>
<li>NO.2</li>
<li>NO.3</li>
</ul>
<ul id="ul2">
<li>one</li>
<li>two</li>
</ul>
<div>
<p>第二个标签</p>
</div>
</div>
<div id="url">
<a href="http:www.58.com" title="58">58</a>
<a href="http:www.csdn.net" title="CSDN">CSDN</a>
<a href="http:www.csdn.net222" title="CSDN">sssss</a>
</div>
</body>
</html>
"""
selector = etree.HTML(html) # element类型
# etree.dump(selector) # 查看element的内容
# html = etree.parse('./hello.html') # 从文件读取
print('-----------------------------基础用法---------------------------')
tag1 = selector.xpath('html') # 查找html结点,注意,返回值是列表
print(tag1)
tag1 = selector.xpath('/html') # /:代表从根节点开始查找子节点 html
print(tag1)
tag1 = selector.xpath('/html//li') # // : 代表查找所有后代结点 li
print(tag1)
tag1 = selector.xpath('.') # . :代表当前结点自身
print(tag1)
tag1 = selector.xpath('/html/head') # 查找根节点的 html 子节点的 head 子节点
print(tag1)
tag1 = tag1.xpath('..') # .. 代表父节点
print(tag1)
tag1 = selector.xpath('//@href') # @代表选择属性,也就是查找所有后代结点的 href 属性的内容,返回的是href的值哦
print(tag1)
tag1 = selector.xpath('//@href="http:www.58.com"') # 是否存在 href="http:www.58.com" 的元素,返回True/False
print(tag1)
print('-----------------------------特殊过滤----------------------------')
tag1 = selector.xpath('//a[1]') # [1]代表选择找到的第一个a标签,不清除为啥用在属性上不起作用,譬如://@href[1]
print(tag1)
tag1 = selector.xpath('//a[last()]') # last() 代表选择最后一个a标签
print(tag1)
tag1 = selector.xpath('//a[last()-1]') # 倒数第二个a标签
print(tag1)
tag1 = selector.xpath('//a[position()<3]') # 选择前2个a标签
print(tag1)
tag1 = selector.xpath('//div[@id="content"]') # 选择拥有属性id='content'的所有div
print(tag1)
tag1 = selector.xpath('//div[@id]') # 选择拥有id属性的div
print(tag1)
tag1 = selector.xpath('//div[@id="url"][a>10]') # 返回的是div。div 的 id="url",并且此div的子节点 a 的内容要>10
print(tag1)
tag1 = selector.xpath('//@*') # *代表所有,@代表属性。也就是筛选所有的属性名
print(tag1)
tag1 = selector.xpath('//*') # 选择所有的结点。
print(tag1)
tag1 = selector.xpath('//div[@*]') # 选择拥有任何属性的div。没有属性的div不会被选择
print(tag1)
print('--------------------------运算符--------------------------')
tag1 = selector.xpath('//head | //body') # | 代表 “或”,选择head或者body标签
print(tag1)
tag1 = selector.xpath('6+5') # 6+5
print(tag1)
tag1 = selector.xpath('//a=58') # 是否存在a的内容=58的标签,返回True或False(a是一个标签,判断a标签的内容是否等于58)
print(tag1)
print('-------------------------Axes(轴)-----------------------')
# child::meta,代表选择当前结点的所有meta子结点
child = selector.xpath('//head/child::meta[@content]')
# ancestor::*,代表选择当前结点的所有祖先结点(父,祖父..)
anc = selector.xpath('//div[@id="content"]/ancestor::*')
# ancestor-or-self:祖先和当前结点
anc_self = selector.xpath('//div[@id="content"]/ancestor-or-self::*')
# attribute:当前结点的所有属性名
attr = selector.xpath('//div[@id="content"]/attribute::*')
# descendant:所有后代结点(子,孙)
desc = selector.xpath('//div[@id="content"]/descendant::*')
# descendant-or-self:所有后代结点(子,孙)和自己
descendant = selector.xpath('//div[@id="content"]/descendant-or-self::*')
# 当前结点后面的所有结点(不管层级,所有结点)
following = selector.xpath('//div[@id="content"]/following::*')
# 命名空间
namespace = selector.xpath('//div[@id="content"]/namespace::*')
# 当前结点的父节点
parent = selector.xpath('//div[@id="content"]/parent::*')
# 当前结点前面的所有结点(不管层级,所有结点)
preceding = selector.xpath('//div[@id="content"]/preceding::*')
# 当前结点前面的所有兄弟结点
preceding_sibling = selector.xpath('//div[@id="content"]/preceding-sibling::*')
# 当前结点自身
self = selector.xpath('//div[@id="content"]/self::*')
print(child,anc,anc_self,attr,desc,descendant,following,namespace,parent,preceding,preceding_sibling,self,sep='\n')
print('-------------------------func---------------------------')
# contains(),筛选href属性值中包含58的a标签
tag1 = selector.xpath('//a[contains(@href,"58")]')
print(tag1)
tag1 = selector.xpath('concat("1","6")') # 字符拼接
print(tag1)
tag2 = selector.xpath('//meta[@content]/@content')
tag1 = selector.xpath('starts-with(//meta[@content]/@content,"text")') # 判断是否以text字符串为起始,True/false
print(tag2,tag1)
print('-------------------------常用方法---------------------------')
# 获取div标签下所有的文本(所有的文本,包含它的子孙后代的文本),但是可能会将换行符作为字符串 \n 显示出来
con = selector.xpath('//div[@id="url"]//text()')
# 获取当前标签的文本,不包含子孙。
con2 = selector.xpath('//div[@id="url"]/text()')
# 通过 .text 获取element的内容文本
divs = selector.xpath('//div[@id="url"]/*')
for d in divs:
print(d.text,d.tag,d.attrib) # 分别是:标签的文本,标签的tag,标签所有的属性键值对(字典格式)