Python3 lxml库使用XPath定位HTML元素

lxml库定位html元素-Python3爬虫

前言

XPath语法略微有点难懂,需要实际操作后,才能有更深的体会。
本文代码基本来自Python3 网络爬虫开发实战

开始

xpath概述:XPath全称是XML Path Language,即XML路径语言

使用规则

表达式描述
@指定属性
选取当前节点的父节点
.选取当前节点
//从当前节点选取子孙节点
/选取当前节点的直接子节点
元素节点名选取指定的元素节点

...///有点类似其在文件路径中的作用

这里的元素节点名实际上类似于css选择器,通过后面的例子会有更深的体会。

给出一个示例,更好理解上述表格:

//title[@lang='eng']

解释:选择所有名称为tiltle,属性lang的值为eng的节点。这里的tiltle实际上就是html元素的标签名称,比如p,div等。


以下示例都是基于如下html文本:


<div>
    <ul>
        <li class="item-0"><a href="link1.html">first item</a></li>
        <li class="item-1"><a href="link2.html">second item</a></li>
        <li class="item-inactive"><a href="link3.html">third item</a></li>
        <li class="item-1"><a href="link4.html">fourth item</a></li>
        <li class="item-0"><a href="link5.html">fifth item</a>
    </ul>
</div>

对于此处给出的html文本,发现它并不是完整的,缺少<html>,<head>,<body>等标签,且最后一个li元素,没有结束标签,但是没关系,lxml的解析器会自动纠错。


如果需要获取对html文本进行分析,首先需要获取到文本,然后通过lxml库的各种方法对文本进行解析。所以首先介绍如何加载要被分析的文本。

HTML源码的加载

  1. 方法一:将HTML源码存储在程序中的字符串变量中加载。
from xlml import etree

text = "..." #这里text中的内容与前面所述的HTML源码一致

html = etree.HTML(text) #获取了一个HTML解析对象,调用该对象的各种方法可以解析源码
//先打印出html现在的内容
result = etree.tostring(html)
print(result)

根据输出结果,可以发现,lxml已经将源码补全,添加了缺失的<html>,<body>等标签,还将漏掉的最后一个</li>补上。

2 .方法二:将HTML源码存储在磁盘(文件)中加载

from xlml import etree
# 假如说要分析的html存储在文件text.html中
html = etree.parse('./text.html', etree.HTMLParser())
result = etree.tostring(html)
print(result)


经过lxml库修改过后的HTML源码:

<html><body><div>
        <ul>
            <li class="item-0"><a href="link1.html">first item</a></li>
            <li class="item-1"><a href="link2.html">second item</a></li>
            <li class="item-inactive"><a href="link3.html">third item</a></li>
            <li class="item-1"><a href="link4.html">fourth item</a></li>
            <li class="item-0"><a href="link5.html">fifth item</a>
        </li></ul>
    </div>
    </body></html>

元素定位:通过文本解析器(生成的对象)的xpath方法定位元素

1. 元素定位基本技巧
  • 定位所有节点
from xlml import etree


html = etree.parse('./text.html', etree.HTMLParser())
result = html.xpath('//*')
#有如下理解://定位路径,*定位元素,这里的*实际上为css选择器
print(result)
# xpath方法将结果以列表形式返回

由于只需要修改xpath方法中的字符串,此后只展示不同xpath语言的不同形式,不会展示完整程序代码

  • 定位子节点:若一直到某个父节点,定位其子节点,可以使用/或·//
#如果选择li节点的所有直接子节点a
result = html.xpath('//li/a')
#//定位路径,使用css选择器li定位指定元素li,然后使用/定位li元素下的路径,最后使用
#使用css选择器a定位到指定的元素
  • 定位父节点
# 定位到属性href为link4.html的元素a的父节点
result = html.xpath('//a[@href="link4.html"]/..')

这里可以看出,使用了@来指定元素所具有的属性。通过属性选择节点,需要将指定的属性包含在方括号中。

可以通过以下代码来验证是否获取成功:

result = html.xpath('//a[@href="link4.html"]/../@class')

可以和上面那段代码做对比,分析差别。只是在选中的父节点后面加上了/@class。这代表着选中父节点的class属性,最终结果为['item-1']

  • 属性匹配:即定位指定属性的元素。

在上面定位父节点中已经初次使用,就是通过在方括号中使用@指定特定属性来实现。这里更进一步讲解多属性匹配:当要定位的元素需要通过多个属性来定位时,可以使用多属性匹配。主要就是通过and运算符来连接多个指定的属性。示例如下:

    
#匹配class='item-1'且href='link2.html'的li元素节点
result = html.xpath('//li[@class='item-1' and @href='link2.html']')
  • 还有更多的定位方法,这里仅介绍一些常用、简单的方法。
2. 元素信息提取

通过XPath提供的各种函数,可以便捷地提取到元素中的信息。由上所述,我们能够定位到单个或多个元素。对元素使用XPath提供的方法,可以提取元素中的信息。

基本使用方法为:先定位到指定元素,然后在元素后加上/方法名()//方法名()

  • 提取元素中的文本:text()方法
# 定位class="item-0"的li元素,并提取其文本信息
result = html.xpath('//li[@class="item-0"]/text()')
print(result)
#结果为:
#['\n     '] 不是我们想要的结果

上述代码不是我们想要的结果,这是由于我们定位到了li元素,但是其中只有一个元素a,而我们想要的文本在元素a中,根据前面所述/是定位当前元素中直接选取子节点,并不能选中到元素a中的文本(因为a中的内容属于li的子孙节点了。)

所以如果想要获取到a中的文本,可以这样写:

result = html.xpath('//li[@class="item-0"]/a/text()')
# 结果为:
# ['first item', 'fifth item']
#符合预期

#还有一种写法
result = html.xpath('//li[@class="item-0"]/a//text()')
# 结果为:
# ['first item', 'fifth item', '\n']
#与预期有偏差,多了\n

分析:对以上第二种结果分析:由于//会从当前标签中的整个内容中寻找。所以也会获取到li节点的文本信息,由于经过XPath的自动补全,导致最后一个li的文本中有一个换行,所以,也会获取到\n

使用/text()是获取当前节点的文本内容。//text()是获取当前节点以及其子孙节点的文本内容。

  • 提取元素属性:

定位到了元素,就可以通过XPath获取其属性。通过在指定元素后加上@href获取。

result = html.xpath('//li/a/@href')

参考资料

  • Python3 网络爬虫开发实战(崔庆才 著)
  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值