5. XPath 解析库

XPath

XPath,全称XML Path Language,即XML路径语言,它提供简洁明了的路径选择表达式,用于在 XML 文档中通过元素和属性进行导航。

XPath常用规则

表达式 描述
nodename 选取此节点所有子节点
/ 从当前节点选取直接子节点
// 从当前节点选取所有子孙节点
. 选取当前节点
.. 选取当前节点的父节点
@ 选取属性

实例HTML文档


子节点、父节点、文本及属性

  • Python通过lxml库,利用XPath进行HTML解析
# 从lxml库导入etree模块
from lxml import etree

# 声明一段HTML文本
text
    '''
    实例HTNL文档(略)
    '''

# 调用HTML类进行初始化,构造XPath解析对象
html = etree.HTML(text)

# 调用tostring()方法输出修正后的HTML代码(bytes类型)
result = etree.tostring(html)

# 调用decode()方法将bytes类型的HTML代码转成str类型
print(result.decode('utf-8'))

f = open('test.html','wt',encoding = 'utf-8')
f.write(result.decode('utf-8'))
f.close()

'''
# 直接读取文本文件进行解析
html = etree.parse('test.html',etree.HTMLParse())
result = etree.tostring(html)
print(result.decode('utf-8'))
'''

  • 用//开头的XPath规则来选取所有符合要求的节点
  • 通过/或//查找元素的子节点或子孙节点
  • 通过..查找元素的父节点
  • 用@符号进行属性过滤或获取属性
  • 用text()方法获取节点中的文本
from lxml import etree
html = etree.parse('test.html',etree.HTMLParse())

 # 选取所有节点
result = html.xpath('//*') 

# 选取所有li节点的所有直接a子节点
result = html.xpath('//li/a') 

# 选取所有ul节点下所有子孙a节点
result = html.xpath('//ul//a') 

# 选中属性href为ink1.html的a节点,再选中取其父节点获取其class属性
result = html.xpath('//a[@href="link1.html"]/../@class') 

# 选取class为item-0的li节点
result = html.xpath('//li[@class="item-0"]')

# 选取属性为item-0的li节点,获取其直接子节点a的文本(以列表形式返回)
result = html.xpath('//li[@class="item-0"]/a/text()')

# 获取所有li节点所有直接a子节点的href属性(以列表形式返回)
result = html.xpath('//li/a/@href')
  • 通过contains()方法进行属性多值匹配(第一个参数传入属性名称,第二个参数传入属性值)
  • 多重属性匹配根据多个属性确定一个节点,需要同时匹配多个属性,可通过and运算符来连接
from lxml import etree
html = etree.parse('test.html',etree.HTMLParse())

'''
  • third item
  • ''' # 匹配class属性为item-inactive的li节点并获取其直接a子节点的文本 result = html.xpath('//li[contains(@class,"item-inactive")]/a/text()') # 匹配class属性为为item-inactive、name属性为item的li节点并获取其直接a子节点的文本 result = html.xpath('//li[contain(@class,"item-inactive") and @name="item"]/a/text')
    • XPath运算符
    运算符 描述
    or
    and
    mod 计算除法的余数
    | 计算两个节点集
    + 加法
    - 减法
    * 乘法
    div 除法
    = 等于
    != 不等于
    < 小于
    <= 小于或等于
    > 大于
    >= 大于或等于

    按序选择

    • 匹配多个节点可利用中括号传入索引的方法获取特定次序的节点
    from lxml import etree
    html = etree.parse('test.html',etree.HTMLParse())
    
    # 选取匹配到的第一个li节点
    result = html.xpath('//li[1]/a/text')
    
    # 选取匹配到的最后一个li节点
    result = html.xpath('//li[last()]/a/text')
    
    # 选取匹配到的位置序号小于3的li节点
    result = html.xpath('//li[position()<3]/a/text')
    
    # 选取匹配到的倒数第三个li节点
    result = html.xpath('//li[last()-2]/a/text')
    

    节点轴选择

    XPath轴可定义相对于当前节点的节点集。

    描述
    ancestor 选取当前节点的所有先辈(父、祖父等)
    ancestor-or-self 选取当前节点的所有先辈(父、祖父等)以及当前节点本身
    attribute 选取当前节点的所有属性
    child 选取当前节点的所有子元素
    descendant 选取当前节点的所有后代元素(子、孙等)
    descendant-or-self 选取当前节点的所有后代元素(子、孙等)以及当前节点本身
    following 选取文档中当前节点的结束标签之后的所有节点
    namespace 选取当前节点的所有命名空间节点
    parent 选取当前节点的父节点
    preceding 选取文档中当前节点的开始标签之前的所有节点
    preceding-sibling 选取当前节点之前的所有同级节点
    self 选取当前节点
    from lxml import etree
    html = etree.parse('test.html',etree.HTMLParse())
    
    '''
    
  • first item
  • ''' # 轴后跟两个冒号再跟节点选择器 # 获取第一个li节点的所有祖先节点(html、body、div和ul) result = html.xpath('//li[1]/ancestor::*') # 获取第一个li节点的div祖先节点 result = html.xpath('//li[1]/ancestor::div') # 获取第一个li节点的所有属性值 result = html.xpath('//li[1]/attribute::*') # 获取第一个li节点href属性为link1.html的a节点 result = html.xpath('//li[1]/child::a[@href="link1.html"]') # 获取第一个li节点的所有包含span而不包含a的子孙节点 result = html.xpath('//li[1]/descendant::span') # 获取第一个li节点后的第二个后续节点 result = html.xpath('//li[1]/following::*[2]') # 获取第一个li节点后的所有同级节点 result = html.xpath('//li[1]/following-sibling::*')

    你可能感兴趣的:(5. XPath 解析库)