XPath(全称:XML Path Language)即 XML 路径语言,它是一门在 XML 文档中查找信息的语言,最初被用来搜寻 XML 文档,同时它也适用于搜索 HTML 文档。因此,在爬虫过程中可以使用 XPath 来提取相应的数据。
提示:XML 是一种遵守 W3C 标椎的标记语言,类似于 HTML,但两者的设计目的是不同,XML 通常被用来传输和存储数据,而 HTML 常用来显示数据。
您可以将 Xpath 理解为在XML/HTML文档中检索、匹配元素节点的工具。
Xpath 使用路径表达式来选取XML/HTML文档中的节点或者节点集。Xpath 的功能十分强大,它除了提供了简洁的路径表达式外,还提供了100 多个内建函数,包括了处理字符串、数值、日期以及时间的函数。因此 Xpath 路径表达式几乎可以匹配所有的元素节点。
Python 第三方解析库 lxml 对 Xpath 路径表达式提供了良好的支持,能够解析 XML 与 HTML 文档。
Xpath节点
XPath 提供了多种类型的节点,常用的节点有:元素、属性、文本、注释以及文档节点。
<?xml version="1.0" encoding="utf-8"?>
<website>
<site>
<title lang="zh-CN">website name</title>
<name>编程帮</name>
<year>2010</year>
<address>www.biancheng.net</address>
</site>
</website>
节点关系
XML 文档的节点关系和 HTML 文档相似,同样有父、子、同代、先辈、后代节点。
<?xml version="1.0" encoding="utf-8"?>
<website>
<site>
<title lang="zh-CN">website name</title>
<name>编程帮</name>
<year>2010</year>
<address>www.biancheng.net</address>
</site>
</website>
上述示例分析后,会得到如下结果:
title name year address 都是 site 的子节点
site 是 title name year address 父节点
title name year address 属于同代节点
title 元素的先辈节点是 site website
website 的后代节点是 site title name year address
etree.HTML()
etree.HTML()可以用来解析字符串格式的HTML文档对象,将传进去的字符串转变成_Element对象。作为_Element对象,可以方便的使用getparent()、remove()、xpath()等方法。并且自动补全html代码方便更好操作和查找。
from lxml import etree
s=""" <div class="ti">
<h3>你和李维宁相同技能:</h3>
<div class="option">
<input type="radio" name="r2" value="true"/>
<label>反向操作</label>
</div>
<div class="option">
<input type="radio" name="r2" />
<label>精准卡点</label>
</div>
<div class="option">
<input type="radio" name="r2"/>
<label>和孙哥撞撞</label>
</div>
<div class="jie">
<div>解析: <span hidden="hidden">反向操作</span></div>
</div>
</div>"""
#将字符串转换为html
html=etree.HTML(s)
print(html)
html_string=etree.tostring(html)
print(html_string.decode('utf-8'))
/代表根节点
data = html.xpath('/html')
print(data)
//代表后面的节点可以在任意位置
data2 = html.xpath('//a')
for i in data2:
if hasattr(i, 'text'):
print(i.text)
else:
print(i)
具体路径
data3 = html.xpath('/html/body//div/label')
for i in data3:
print(i)
.代表当前节点 ..代表上级节点
data4 = html.xpath('/html/body/div')
for i in data4:
li = i.xpath('./h3')
for j in li:
a = j.xpath('./label')
for k in a:
print(k.text)
print("*" * 100)
for i in data4:
ul = i.xpath('../label')
print(ul)
@选取属性
data4=html.xpath("//input/@type")
print(data4)
data4=html.xpath("//a/@href")
print(data4)
谓语,指定具体的节点
data4=html.xpath("//div[1]/label")
print(data4)
data4=html.xpath("//div[last()]")
print(data4)
data4=html.xpath('//span[@hidden="hidden"]')
for i in data4:
if hasattr(i,'text'):
print(i.text)
*未知节点
data4=html.xpath("//*")
print(len(data4))
for i in data4:
if hasattr(i, 'text'):
print(i.text)
data4=html.xpath("//@*")
print(len(data4))
print(data4)
| 匹配两个节点
data4=html.xpath("//li | //a")
print(len(data4))
案例
from lxml import etree
#解析文件:html文件,但是自定义解析器,因为etree默认是xml解析器
#自定义解释器,
parser=etree.HTMLParser(encoding='utf-8')
#解析html文件为html对象
html=etree.parse("index.html",parser=parser)
# #将对象html转换字符串,解码,打印
html=etree.tostring(html,pretty_print=True)
res=html.decode("utf-8")
print(res)
#打印内容。[]表示带有title属性的a
data=html.xpath('//a[@title]')
for i in data:
#. 当前节点a ,寻找title属性值
title=i.xpath('./@title')
#寻找当前节点文本
desc=i.xpath('./text()')
print(title,desc)