python中lxml 库之 etree 使用详解
目录
一、 etree 介绍
lxml
库是 Python 中一个强大的 XML 处理库,简单来说,etree 模块提供了一个简单而灵活的API来解析和操作 XML/HTML 文档。
二、xpath 解析 html/xml
1、第一步就是使用 etree 连接 html/xml 代码/文件。
语法:
from lxml import etree
root = etree.XML("<root>data</root>")
print(root.tag)
#root
print(etree.tostring(root))
#b'<root>data</root>'
root = etree.HTML("<p>data</p>")
print(root.tag)
#html
print(etree.tostring(root))
#b'<html><body><p>data</p></body></html>'
2、 xpath 表达式定位
xpath 使用路径表达式在 HTML/XML 文档中选取节点。节点是通过沿着路径或者 step 来选取的。 下面列出了最有用的路径表达式:
表达式 | 描述 |
---|---|
/ | 从根节点选取(取子节点) |
// | 任意节点,不考虑位置(取子孙节点) |
. | 选取当前节点 |
… | 选取当前节点的父节点 |
@ | 选取属性 |
contain(@属性,“包含的内容”) | 模糊查询 |
text() | 文本内容 |
① xpath结合属性定位
from lxml import etree
ht = """<html>
<head>
<title>This is a sample document</title>
</head>
<body>
<h1 class="title">Hello!</h1>
<p>This is a paragraph with <b>bold</b> text in it!</p>
<p>This is another paragraph, with a
<a href="http://www.python.org">link</a>.</p>
<p>Here are some reserved characters: <spam&egg>.</p>
<p>And finally an embedded XHTML fragment.</p>
</body>
</html>"""
html = etree.HTML(ht)
title = html.xpath(".//h1[@class='title']")[0] #取列表中的第一个元素
print(etree.tostring(title))
#b'<h1 class="title">Hello!</h1>\n '
print(title.get('class'))
# title
② xpath文本定位及获取
title1 = html.xpath(".//h1[text()='Hello!']")[0] #取列表中的第一个元素
text1 = title1.text
print(text1)
#Hello!
text2 = html.xpath("string(.//h1[@class='title'])")
print(text2)
#Hello!
text3 = html.xpath(".//h1[@class='title']/text()") #返回列表
print(text3)
#['Hello!']
③ xpath层级定位
实际开发时,若需求元素没有像 id、name、class 等基本属性,那么我们就需要借助相邻的元素定位,首先我们可以定位到相邻元素,然后通过层级关系来定位最终元素。
在这里插入代码片
from lxml import etree
ht = """<html>
<head>
<title>This is a sample document</title>
</head>
<body>
<h1 class="title">Hello!</h1>
<p>This is a paragraph with <b>bold</b> text in it!</p>
<p class="para">This is another paragraph, with a
<a href="http://www.python.org">link</a>.</p>
<p>Here are some reserved characters: <spam&egg>.</p>
<p>And finally an embedded XHTML fragment.</p>
</body>
</html>"""
html = etree.HTML(ht)
ele1 = html.xpath(".//p[@class='para']/a")[0] #由上到下的层级关系
print(etree.tostring(ele1))
#b'<a href="http://www.python.org">link</a>.'
ele2 = html.xpath(".//a[@href='http://www.python.org']/parent::p")[0]#父子元素定位
print(etree.tostring(ele2))
#b'<p class="para">This is another paragraph, with a\n <a href="http://www.python.org">link</a>.</p>\n '
ele3 = html.xpath(".//p[@class='para']//preceding-sibling::p")[0] #哥哥元素定位
print(etree.tostring(ele3))
#b'<p>This is a paragraph with <b>bold</b> text in it!</p>\n '
ele4 = html.xpath(".//p[@class='para']//following-sibling::p") #弟弟元素定位
for ele in ele4:
print(etree.tostring(ele))
#b'<p>Here are some reserved characters: <spam&egg>.</p>\n '
#b'<p>And finally an embedded XHTML fragment.</p>\n '
④ xpath索引定位
etree 结合 xpath 进行索引定位主要有两种方式,主要是因为 html.xpath() 返回的是一个列表。
ele1 = html.xpath(".//body/p")[0]
print(etree.tostring(ele1))
#b'<p>This is a paragraph with <b>bold</b> text in it!</p>\n '
ele1 = html.xpath(".//body/p")[-1]
print(etree.tostring(ele1))
#b'<p>And finally an embedded XHTML fragment.</p>\n '
语法2:
html.xpath(“xpath表达式[1]”)[0] #获取第一个元素
html.xpath(“xpath表达式[last()]”)[0] #获取最后一个元素
html.xpath(“xpath表达式[last()-1]”)[0] #获取倒数第二个元素
注:与python列表索引的概念不同,xpath 的标签索引是从1开始;python列表的索引是从0开始。
⑤ xpath模糊匹配
有时会遇到属性值过长的情况,此时我们可以通过模糊匹配来处理,只需要属性值的部分内容即可。
html.xpath(“.//标签名[start-with(@属性, ‘属性值开头’)]”) #匹配开头
html.xpath(“.//标签名[ends-with(@属性, ‘属性值结尾’)]”) #匹配结尾
html.xpath(“.//标签名[contains(text(), ‘部分文本’)]”) #包含部分文本
注:ends-with方法是 xpath 2.0 的语法,而 etree 只支持 xpth 1.0,所以可能不会成功。
ele1 = html.xpath(".//p[starts-with(@class,'par')]")[0] #匹配开头
print(etree.tostring(ele1))
#b'<p class="para">This is another paragraph, with a\n <a href="http://www.python.org">link</a>.</p>\n '
ele2 = html.xpath(".//p[ends-with(@class, 'ara')]")[0] #匹配结尾
print(etree.tostring(ele2))
ele3 = html.xpath(".//p[contains(text(),'is a paragraph with')]")[0] #包含“is a paragraph with”
print(etree.tostring(ele3))
#b'<p>This is a paragraph with <b>bold</b> text in it!</p>\n '
作者:闲人陈二狗