lxml是一个Python的一个解析库,用于解析HTML和XML,支持Xpaxth解析。由于lxml底层是使用C语言编写的,所以解析效率非常高。
一.安装lxml
主要是介绍windows下的安装
1.使用pip安装
pip install lxml
如果安装出错,表明缺少依赖库,如libxm12。这时候可以采用wheel方式安装
2.本地安装
这里给出个网址
python包Windows 二进制文件
在该页面下搜索lxml的whl文件即可。
下载完成之后,cmd切换运行到下载解压后的目录,执行如下命令
pip install lxml-4.6.3-cp310-cp310-win_amd64.whl
3。操作XML
lxml可以读取xml文件,也可以使用字符串形式的xml文档。如果要读取xml文件,需要使用parse函数,该函数需要传入一个XML文件名。如果要解析字符串形式的XML文档,需要使用fromstring函数,该函数的参数就是XML字符串。
from lxml import etree
# 读取xml文件
tree = etree.parse('products.xml')
print(type(tree))
# 将tree重新转化为字符串形式的xml文档,并输出
print(str(etree.tostring(tree,encoding = "utf-8"),'utf-8'))
# 获得根节点
root = tree.getroot()
print(type(root))
# 输出根节点的名称
print('root:',root.tag)
# 获得根节点的所有子节点
children = root.getchildren()
print('--------------输出产品信息--------------')
# 迭代这些子节点,并输出对应的属性和节点文本
for child in children:
print('product id = ', child.get('id'))
print('child[0].name = ',child[0].text)
print('child[1].price = ', child[1].text)
# 分析字符串形式的XML文档
root = etree.fromstring('''
<products>
<product1 name="iPhone"/>
<product2 name="iPad"/>
</products>
''')
print('------------新产品------------')
# 输出根节点的节点名
print('root =',root.tag)
children = root.getchildren()
# 迭代这些子节点,并输出节点的名称和name属性名
for child in children:
print(child.tag,'name = ',child.get('name'))
4.操作HTML文档
html本质上与xml类似,都是由若干类似<tag></tag>
的节点组成的。他们之间的不同之处在于XML除了这些节点,不能再有其他东西,而HTML的语法比较*,不仅可以有节点,还可以有其他任何文本。
用lxml库操作html与操作XML类似,同样可以通过getroot方法获得根节点,通过get方法获得节点属性值,通过text属性获取节点内容,通过索引的方式引用了子节点。
from lxml import etree
parser = etree.HTMLParser()
print(type(parser))
tree = etree.parse('test.html', parser)
root = tree.getroot()
result = etree.tostring(root,encoding='utf-8',
pretty_print=True, method="html")
print(str(result,'utf-8'))
print(root.tag)
print('lang =',root.get('lang'))
print('charset =',root[0][0].get('charset'))
print('charset =',root[0][1].text)
二.XPath
XPath的英文名称是XML path Language ,中文是XML路径语言,他是一种在XML文档中查找信息的语言,最初是用于在XML文档中搜索节点的,但同样可以用于HTML文档的搜索,因为XML与HTML是同源的;
绝大多数HTML分析库都支持Xpath。这里介绍lxml库中使用Xpath过滤掉HTML代码中的节点
lxml装载HTML代码有如下两种方式
1.从文件装载,通过parse函数指定的HTML文件名
2.从代码装载,通过HTML函数指定HTML代码
2.1提取test.html文件中的标题,以及一段HTML代码中特定a节点的herf属性值和节点文本
from lxml import etree
parser = etree.HTMLParser()
tree = etree.parse('test.html', parser)
# 使用xpath定位title节点,返回一个节点集合
titles = tree.xpath('/html/head/title')
if len(titles) > 0:
# 输出title节点的文本
print(titles[0].text)
# 定义一段html代码
html = '''
<div>
<ul>
<li class="item1"><a href="https://geekori.com"> geekori.com</a></li>
<li class="item2"><a href="https://www.jd.com"> 京东商城</a></li>
<li class="item3"><a href="https://www.taobao.com">淘宝</a></li>
</ul>
</div>
'''
# 分析HTML代码
tree = etree.HTML(html)
# 使用xpath定位class属性值为item2的<li>节点
aTags = tree.xpath("//li[@class='item2']")
if len(aTags) > 0:
# 得到该<li>节点中<a>节点的href属性值和文本
print(aTags[0][0].get('href'),aTags[0][0].text)
# https://www.jianshu.com/p/2ae6d51522c3
注意:
1.通过XPath定位节点返回的是节点集合,即使只有一个节点,返回的也是一个节点集合
2.使用XPath分析的HTML文档并不一定是标准的,可以么有像`、、这些的、节点。任何一段符合HTML语法标准的代码都可以使用XPath进行定位
2.2选取所有节点
//:以两个斜杠(//)开头的XPath规则会选取所有符合要求的节点。表示任意节点,所以//*表示的是选取所有节点
这里展示一个取出所有的<a>
节点,并输出节点的名称
from lxml import etree
parser = etree.HTMLParser()
html = etree.parse('demo.html', parser)
# 选取demo.html文件中所有的节点
nodes = html.xpath('//*')
print('共',len(nodes),'个节点')
# 输出所有节点的节点名
print(nodes)
for i in range(0,len(nodes)):
print(nodes[i].tag,end=' ')
# 按层次输出节点,indent是缩进
def printNodeTree(node, indent):
print(indent + node.tag)
indent += " "
children = node.getchildren()
if len(children) > 0:
for i in range(0,len(children)):
# 递归调用
printNodeTree(children[i],indent)
print()
# 按层次输出节点的节点,nodes[0]是根节点(html节点)
printNodeTree(nodes[0],"")
nodes = html.xpath('//a')
print()
print('共',len(nodes),'个<a>节点')
print(nodes)
# 输出所有<a>节点的文本
for i in range(0,len(nodes)):
print(nodes[i].text,end=' ')
2.3选取子节点
“/”后是直接子节点。“//”是选取所有该子节点(在该父节点之下的所有)
from lxml import etree
parser = etree.HTMLParser()
html = etree.parse('demo.html', parser)
nodes = html.xpath('//li/a')
print('共',len(nodes),'个节点')
print(nodes)
for i in range(0,len(nodes)):
print(nodes[i].text,end=' ')
print()
nodes = html.xpath('//ul//a')
print('共',len(nodes),'个节点')
print(nodes)
for i in range(0,len(nodes)):
print(nodes[i].text,end=' ')
print()
nodes = html.xpath('//ul/a')
print('共',len(nodes),'个节点')
print(nodes)
2.4选取父节点
如果知道子节点,想得到父节点,可以使用"..";“parent: