首先要下载包:pip install lxml
基本使用如下代码所示:
# xpath 解析:先安装lxml:pip install lxml
from lxml import etree
xml = """
<book>
<id>1</id>
<name>山花遍地开</name>
<price>9.99</price>
<nick>臭豆腐</nick>
<author>
<nick id="1001">周六福</nick>
<nick id="joy">周杰伦</nick>
<nick id="jolin">蔡依林</nick>
<div>
<nick>呼哈1</nick>
</div>
<span>
<nick>呼哈2</nick>
</span>
</author>
<partner>
<nick id="ppd">胖胖哒</nick>
<nick id="nnn">nonono</nick>
</partner>
</book>
"""
# etree.XML(xml) 表示解析的字符串是XML
# 此外还有etree.HTML(text) 表示解析的是HTML
# etree.parse('文件路径') 可以传入一个文件,然后解析该文件
tree = etree.XML(xml)
# 获取book节点
book = tree.xpath('/book') # /表示层级关系,第一个/是根节点
print(book) # [<Element book at 0x26f27a5cdc0>]
# 获取book节点下的name节点
name = tree.xpath('/book/name')
print(name) # [<Element name at 0x26f27e57740>]
# text() 获取节点的文本内容
# 获取name节点的文本内容
name_text = tree.xpath('/book/name/text()')
print(name_text) # ['山花遍地开']
# 获取author节点下的nick儿子节点,即直接被author节点包裹,而不是隔着其他节点的
# 如"周六福"、"周杰伦"、"蔡依林"是被直接包裹,而"呼哈1"隔着一层div节点
author_son_nick = tree.xpath('/book/author/nick/text()')
print(author_son_nick) # ['周六福', '周杰伦', '蔡依林']
# // 表示获取父节点下的某个名称的所有子节点,包括儿子、孙子、重孙子等
# 如此处获取author节点下的所有nick节点,包括直接包裹和隔着其他节点的,只要是在author下的都算
author_offspring_nick = tree.xpath('/book/author//nick/text()')
print(author_offspring_nick) # ['周六福', '周杰伦', '蔡依林', '呼哈1', '呼哈2']
# * 通配符,可以匹配任意的节点
# 如此处*可以匹配div节点和span节点,得到author节点下的div和span下的nick节点
# 即“呼哈1”、“呼哈2”
nick = tree.xpath('/book/author/*/nick/text()')
print(nick) # ['呼哈1', '呼哈2']
test.html代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Title</title>
</head>
<body>
<h1>标题1</h1>
<h2>标题2</h2>
<h3>标题3</h3>
<div id="content" class="default">
<p>段落</p>
<ul>
<li><a class="baidu" href="http://www.baidu.com">百度</a></li>
<li><a class="iqiyi" href="http://www.iqiyi.com">爱奇艺</a></li>
</ul>
<img src="https://www.python.org/static/img/python-logo.png" />
</div>
</body>
</html>
使用xpath解析test.hml文件:
# 注意,以下注释中的标签、节点、元素都是一个意思,只是叫法不用
# 对一个HTML文件进行解析
tree = etree.parse('test.html')
# 获取html节点
html = tree.xpath('/html')
print(html) # [<Element html at 0x1d819cc7300>]
# 获取div节点下ul里的li标签中的两个a标签里文本
as_text = tree.xpath('/html/body/div/ul/li/a/text()')
print(as_text) # ['百度', '爱奇艺']
# [index] 中括号加索引表示获取第index个标签,注意索引从1开始
# 获取ul里的第一个li标签下的a标签中的文本
first_a_text = tree.xpath('/html/body/div/ul/li[1]/a/text()')
print(first_a_text) # ['百度']
# [@属性名=属性值] 根据某个属性值获取指定节点
# 获取class属性为"iqiyi"的a标签
iqiyi_a = tree.xpath('/html/body/div/ul/li/a[@class="iqiyi"]/text()')
print(iqiyi_a) # ['爱奇艺']
# 遍历ul中的li
ul_li_list = tree.xpath('/html/body/div/ul/li')
print(ul_li_list) # [<Element li at 0x1fd7694c1c0>, <Element li at 0x1fd7694c200>]
for li in ul_li_list:
# ./表示相对当前节点,即相对li查找a标签
a_text = li.xpath('./a/text()')
print(a_text) # 分别打印['百度']、['爱奇艺']
# @属性名 表示获取标签的某个属性值
# 打印a标签的href属性
href = li.xpath('./a/@href')
print(href) # 分别打印['http://www.baidu.com']、['http://www.iqiyi.com']
# 一次性获取div节点下ul里的li标签中的两个a标签的href属性值(和获取文本类似)
href_val = tree.xpath('/html/body/div/ul/li/a/@href')
print(href_val) # ['http://www.baidu.com', 'http://www.iqiyi.com']