lxml是python的一个解析库,支持HTML和XML的解析,支持XPath解析方式,而且解析效率非常高。
windows系统下的安装:
#pip安装
pip3 install lxml
#wheel安装
#下载对应系统版本的wheel文件:http://www.lfd.uci.edu/~gohlke/pythonlibs/#lxml
pip3 install lxml-4.2.1-cp36-cp36m-win_amd64.whl
linux下安装:
yum install -y epel-release libxslt-devel libxml2-devel openssl-devel
pip3 install lxml
lxml 库提供了一个 etree 模块,该模块专门用来解析 HTML/XML 文档
from lxml import etree
调用 etree 模块的 HTML() 方法来创建 HTML 解析对象
parse_html = etree.HTML(html)
HTML() 方法能够将 HTML 标签字符串解析为 HTML 文件,该方法可以自动修正 HTML 文本。
html_str = '''
'''
html = etree.HTML(html_str)
result = etree.tostring(html)#将标签元素转化为字符串
print(result.decode('utf-8'))
运行结果:
上述 HTML 字符串存在缺少标签的情况,比如“C语言中文网”缺少一个 闭合标签,当使用了 HTML() 方法后,会将其自动转换为符合规范的 HTML 文档格式。
最后使用第二步创建的解析对象调用 xpath() 方法,完成数据的提取
r_list = parse_html.xpath('xpath表达式')
lxml提供如下方式输入文本:
可以使用find、findall或者xpath来搜索Element包含的标签对象。区别如下:
>>> root = etree.XML("aText ")
>>> x=root.find('.//a[@x]')
>>> x
<Element a at 0x2242c10>
>>> x.text
'aText'
>>> x.tag
'a'
>>> x2=root.findall('.//a[@x]')
>>> x2
[<Element a at 0x2242c10>]
>>> type(x2)
<type 'list'>
>>> x3=root.xpath('//a[@x]')
>>> type(x3)
<type 'list'>
>>> x3
[<Element a at 0x2242c10>]
此外,lxml还支持css语法的选择方式,对于熟悉JQuery选择器的开发者是一个很好的补充(需要安装pip install cssselect
):
>>> root = etree.XML("aText ")
>>> a1=root.cssselect('._123')
>>> a1[0].tag
'a'
>>> root = etree.XML("aText ")
>>> a1=root.cssselect('a')
>>> a1[0].text
'aText'
>>> a2=root.cssselect('.c123')
>>> a2[0].text
'aText'
>>> b=root.cssselect('#b1')
>>> b[0].tag
'b'
text='''
'''
html = etree.HTML(text) #初始化生成一个XPath解析对象
result = etree.tostring(html,encoding = 'utf-8') #解析对象输出代码
print(type(html))
print(type(result))
print('\n')
print(result.decode('utf-8'))
运行结果:
html = etree.parse('page1.html',etree.HTMLParser()) #指定解析器HTMLParser会根据文件修复HTML文件中缺失的如声明信息
result = etree.tostring(html)
print(type(html))
print(type(result))
print('\n')
print(result.decode(encoding = 'utf-8'))
运行结果:
返回一个列表每个元素都是Element类型,所有节点都包含在其中
html = etree.parse('page1.html',etree.HTMLParser())
result = html.xpath('//*') #//代表获取子孙节点,*代表获取所有
print(type(html))
print(type(result))
print('\n')
print(result)
运行结果:
如要获取li节点,可以使用//后面加上节点名称,然后调用xpath()方法
html.xpath('//li') #获取所有子孙节点的li节点(4)获取子节点
运行结果:
通过/或者//即可查找元素的子节点或者子孙节点
result=html.xpath('//li/a')
运行结果:
要查找父节点可以使用…来实现也可以使用parent::来获取父节点
text='''
'''
html=etree.HTML(text,etree.HTMLParser())
result=html.xpath('//a[@href="link2.html"]/../@class')
result1=html.xpath('//a[@href="link2.html"]/parent::*/@class')
print(result)
print(result1)
运行结果:
在选取的时候,我们还可以用@
符号进行属性过滤。比如,这里如果要选取class
为item-1
的li
节点,
text='''
'''
html=etree.HTML(text,etree.HTMLParser())
result=html.xpath('//li[@class="item-1"]')
print(result)
运行结果:
用XPath中的text()方法获取节点中的文本
html=etree.HTML(text,etree.HTMLParser())
result=html.xpath('//li[@class="item-1"]/a/text()') #获取a节点下的内容
result1=html.xpath('//li[@class="item-1"]//text()') #获取li下所有子孙节点的内容
print(result)
print(result1)
运行结果:
使用@符号即可获取节点的属性
result=html.xpath('//li/a/@href') #获取a的href属性
result=html.xpath('//li//@href') #获取所有li子孙节点的href属性
如果某个属性的值有多个时,可以使用contains()函数来获取
html=etree.HTML(text,etree.HTMLParser())
result=html.xpath('//li[@class="aaa"]/a/text()')
result1=html.xpath('//li[contains(@class,"aaa")]/a/text()')
#通过第一种方法没有取到值,通过contains()就能精确匹配到节点了
print(result)
print(result1)
根据多个属性确定一个节点,这时就需要同时匹配多个属性,此时可用运用and运算符来连接使用
html=etree.HTML(text,etree.HTMLParser())
result=html.xpath('//li[@class="aaa" and @name="fore"]/a/text()')
result1=html.xpath('//li[contains(@class,"aaa") and @name="fore"]/a/text()')
运行结果:
有时候,我们在选择的时候某些属性可能同时匹配多个节点,但我们只想要其中的某个节点,如第二个节点或者最后一个节点,这时可以利用中括号引入索引的方法获取特定次序的节点
html=etree.HTML(text1,etree.HTMLParser())
result=html.xpath('//li[contains(@class,"aaa")]/a/text()') #获取所有li节点下a节点的内容
result1=html.xpath('//li[1][contains(@class,"aaa")]/a/text()') #获取第一个
result2=html.xpath('//li[last()][contains(@class,"aaa")]/a/text()') #获取最后一个
result3=html.xpath('//li[position()>2 and position()<4][contains(@class,"aaa")]/a/text()') #获取第三个
result4=html.xpath('//li[last()-2][contains(@class,"aaa")]/a/text()') #获取倒数第三个