Xpath语法
from lxml import etree # 需要下载lxml第三方模块
1.xpath基本概念
1)树:整个HTML(xml)代码结构就是一个树结构
2)节点:树结构中的每一个元素(标签)就是一个节点
3)根节点(根元素):html或者xml最外面的那个标签(元素)
4)节点内容:标签内容
5)节点属性:标签属性
2.xml数据格式
xml和json一样。是一种通用的数据格式(绝大部分编程语言都支持的数据格式)
'''
xml是提供标签的标签(元素)的标签内容和属性来保存数据的。
示例:保存一个超市信息
{
'name':'永辉超市',
'address':'肖家河大厦',
'staff':[
{'name':'小明','id':'520','position':'收银员','salry':4000}
{'name':'小王','id':'620','position':'促销员','salry':3500}
{'name':'小尹','id':'720','position':'清洁工','salry':3000}
{'name':'小红','id':'820','position':'收银员','salry':4000}
{'name':'小东','id':'920','position':'售货员','salry':3800}
],
'goodsList':[
{'name':'泡面','price':3.5,'count':120,'discount':0.9}
{'name':'火腿肠','price':1.5,'count':330,'discount':1}
{'name':'矿泉水','price':3,'count':540,'discount':1}
{'name':'面包','price':5.5,'count':290,'discount':0.85}
]
}
xml数据:
path:files/data.xml 等下下面这个会演示怎么操作 先放入这个文件中
<supermarket name="永辉超市" address="肖家河大厦">
<staffs>
<staff id="s001" class="c1">
<name>小明</name>
<position>收营员</position>
<salary>4000</salary>
</staff>
<staff id="s002" class="c2">
<name>小花</name>
<position>促销员</position>
<salary>3500</salary>
</staff>
<staff id="s003" class="c2">
<name>张三</name>
<position>保洁</position>
<salary>3000</salary>
</staff>
<staff id="s004" class="c1">
<name>李四</name>
<position>收营员</position>
<salary>4000</salary>
</staff>
<staff id="s005" class="c2">
<name>王五</name>
<position>售货员</position>
<salary>3800</salary>
</staff>
</staffs>
<goodsList>
<goods discount="0.9">
<name>泡面</name>
<price>3.5</price>
<count>120</count>
</goods>
<goods>
<name>火腿肠</name>
<price>1.5</price>
<count>332</count>
</goods>
<goods>
<name>矿泉水</name>
<price>2</price>
<count>549</count>
</goods>
<goods discount="8.5">
<name>面包</name>
<price>5.5</price>
<count>29</count>
</goods>
</goodsList>
</supermarket>
'''
3.xpath语法
1)创建树结构获取树的节点
etree.XML(xml数据)
etree.HTML(html数据)
首先创建树的节点对象:
f = open('files/data.xml', encoding='utf-8')
root = etree.XML(f.read())
f.close()
2)根据xpath获取指定标签
节点对象.xpath(路径) - 返回路径对应的所有标签,返回值是列表,列表中的元素是标签对象(节点对象)
路径的写法:
1.绝对路径 :/标签在树结构中的全路径 (路径必须从根节点开始写) 必须‘/’开头
2.相对路径 :路径开头用’.‘表示当前节点,’…‘表示当前节点的上层节点
3.全路径 : 用’//'开头的路径 - 在整个树中获取标签
注意:绝对路径和全路径的写法以及查找方式和是用谁去点的xpath无关
result = root.xpath('/supermarket/staffs/staff/name')
print(result)
result = root.xpath('./staffs/staff/name/text()')
print(result)
staff1 = root.xpath('./staffs/staff')[0]
result = staff1.xpath('./name/text()')
print(result) # ['小明']
result = staff1.xpath('../staff/name/text()')
print(result) #['小明', '小花', '张三', '李四', '王五']
3)获取标签内容
# 节点对象.xpath(获取标签的路径/text()) - 获取指定路径下所有标签的标签内容
result = root.xpath('/supermarket/staffs/staff/name/text()') #获取标签内容
print(result)
result = root.xpath('//name/text()')
print(result)
result = root.xpath('staffs/staff')[0] # staff节点
result1 = result.xpath('name/text()')
print(result1)
4)获取标签属性值
result = root.xpath('/supermarket/@name')
print(result)
result =root.xpath('//staff/@id')
print(result)
5)谓语(条件)
a.位置相关谓语
[N] - 第N个
[last()] - 最后一个
[last()-N] - 倒数第N+1
[position()>N]、[position()<N]、[position()>=N]、[position()<=N]
result = root.xpath('//staff[1]/name/text()')
print(result) #['小明']
result = root.xpath('//staff[last()]/name/text()')
print(result) # ['王五]
result= root.xpath('//staff[position()<3]/name/text()')
print(result) #['小明', '小花']
result= root.xpath('//staff[position()>1]/name/text()')
print(result)
b.属性相关谓语
[@属性名=属性值] - 获取指定属性是指定值的标签
[@属性名] - 获取拥有指定属性名的标签,值不重要
result = root.xpath('//staff[@class="c1"]/name/text()')
print(result)
c.子标签内容相关谓语 - 根据子标签的内容来筛选标签
[子标签>数据]
[子标签<数据]
[子标签=数据]
[子标签<=数据]
[子标签>=数据]
result = root.xpath('//goods[price>=2]/name/text()')
print(result)
result = root.xpath('//goodsList/goods[price>=2]/name/text()')
print(result)
# []必须是前一个标签名的子标签,否则找不到
6)通配符 - 写路径的时候用*来表示任意标签或者任意属性
result = root.xpath('//staff[1]/*/text()')
print(result) #['小明', '收营员', '4000']
任意属性通配符表示该标签下的属性值
result = root.xpath('//goods[@*]/name/text()')
print(result)
result = root.xpath('//*[@*]/@*')
print(result) #测试拿所有的标签中有属性的值
result =root.xpath('//*/*/*[@*]/@*')
print(result) # 只要符号这个条件都可以 ['s001', 'c1', 's002', 'c2', 's003', 'c2', 's004', 'c1', 's005', 'c2', '0.9', '8.5']
7)若干路径 - |
# 路径1|路径2 - 同时获取路径1和路径2的内容
result = root.xpath('//goods/name/text()|//staff/position/text()')
print(result)