Post

0301lxml

lxml 是 Python 的一个解析库,支持 HTML 和 XML 的解析,支持 XPath 解析方式(xml 是一个非常重要的库,比如 BeautifulSoup、Scrapy 框架都需要用到此库)

网页数据的解析提取(p90)

XML 路径语言(XML path language)

用来在XML文档中查找信息,同样适用HTML文档的搜索

表达式描述
nodename选取此节点的所有子节点
/从当前节点选取直接子节点
//从当前节点选取子孙节点
.选取当前节点
..选取当前节点的父节点
@选取属性
*任意元素
*@任意属性
1
//title[@lang='eng'] #选择所有名称(nodename)为 tilte, 属性 lang='eng'的节点

安装:

pip3 install lxml

使用

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from lxml import etree
text="""<div>
  <ul>
    <li class="item-0"><a href="link1.html">first item</a></li>
    <li class="item-inactive"><a href="link2.html">second item</a></li>
    <li class="item-2"><a href="link3.html">third item</a></li>
    <li class="item-1"><a href="link4.html">fourth item</a></li>
    <li class="item-0" name="it4"><a href="link5.html">fifth item</a></li>
  </ul>
</div>
"""
html=etree.HTML(text)

print( html.xpath('//*') ) 									#1选取所有子节点选取所有子节点
print( html.xpath('//li/a') )								#2选取子节点选选取所有 li 节点下的 直接节点a。 如果改成://ul/a 则返回[]

print( html.xpath('//a[@href="link4.html"]/../@class') )	#3选取父节点查找子孙节点a,属性href="link4.html,的父节点,获取该父节点的class值
                                                            #4 ..=parent::*,上句等价于://a[@href="link4.html"]/parent::*/@class

print( html.xpath('//li[@class="item-0"]/a/text()') )		#5文本获取text():获取节点 li,属性 class="item-0"",的所有直接子节点 a的 文本
print( html.xpath('//li[@class="item-0"]//text()') )		# 获取节点 li,属性 class="item-0"",的所有子节点的 文本

print( html.xpath('//li/a/@href'))							#6获取属性

##7属性包含(contain)匹配
print( html.xpath('//li[contains(@class,"-inactive")]/a/text()') ) #返回['second item']

属性操作符:

通过and、or等操作可以组合多个属性选择(p96)

运算符描述实例
and、or与、或//li[contains(@class,”-0”) and @name=”it4” ]/a/text(),返回 fifth item
mod取莫//li[position() mod 2=0 ]/a/text(),返回[‘second item’, ‘fourth item’]
|多个路径(或)计算两个节点集//li[@class=”item-inactive”]/a/text() | //li[@class=”item-1”]/a/text(),返回[‘second item’, ‘fourth item’]
+、-、*、div加、减、乘、除 
=、!=等于、不等于 
<、>、<=、>=小于、大于、小于等于、大于等于html.xpath(“//li[position() < 3]/a/text()”)

节点按序选择

1
2
3
4
5
#注意节点是从1开始!!不是从0开始的
#1.position()、last():获取节点 当前、最后一个序号
print( html.xpath('//li[1]/a/text()'))
print( html.xpath('//li[first()]/a/text()'))
print( html.xpath('//li[position()<3]/a/text()'))

节点轴选择(p97)

操作符描述例子
text()获取文本li[@class=”item-inactive”]/a/text()
parent获取父节点//a[@href=”link4.html”]/parent::*/@class
ancestor获取所有祖先节点//li[1]/ancestor::*‘,返回 html、body、div、ul节点
descendant获取所有子孙节点//ul/descendant::li[1]/a/text()’,返回[‘first item’]
//ul/descendant::li[@class=”item-inactive”]/a/text()’,返回[‘second item’]
child获取所有直接子节点//ul/child::*[1]/a/text(),返回[‘first item’]
attribute获取所有属性//li[last()]/attribute::*,返回[‘item-0’, ‘it4’]
following获取当前节点之后的所有节点//li[1]/following::*[2]/@href,返回[‘link2.html’](注意following会将嵌套的子节点和父节点平铺。比如<li><a><\/a><\/li>:li是第一个节点而a是第二个节点)
following-sibling获取当前节点之后的所有同级节点//li[1]/following-sibling::*,返回后面四个 li 节点
contains包含html.xpath(‘//li/a[contains(text(),”first”)]/text()’),返回first item
starts-with以字符串开头html.xpath(‘//li/a[starts-with(text(),”first”)]/text()’),返回first item
This post is licensed under CC BY 4.0 by the author.