掌握XPath:安装配置、解析流程、语法和实战练习全攻略

目录

引言

xpath安装与使用

解析流程与使用

xpath语法

xpath实战练习


引言

众所周知,XPath是Web开发中重要的工具之一,可以帮助我们在HTML或XML文档中快速定位和选择内容。但是对于初学者来说,XPath的安装配置、语法解析以及实际应用可能会有些困难。因此,在这篇文章中,我们将为大家提供一份全攻略,让大家轻松掌握XPath的使用方法。

从XPath的安装和环境配置开始,我们将为大家逐一介绍XPath的使用流程及其常用语法,同时配合实战练习,旨在让读者们在实践操作中逐步掌握XPath的技能。

无论你是新手还是老手,在掌握XPath的基础知识后,都可以为自己的Web开发工作提供更多便捷和效率,同时也能够更加深入地理解Web开发的一些本质概念。让我们一起来探索XPath的奥秘吧!

xpath安装与使用

安装

  • 安装lxml库

    pip install lxml -i pip源

解析流程与使用

from lxml import etree

# 解析本地HTML文件
# parser = etree.HTMLParser(encoding="utf-8")
# tree = etree.parse('./素材/豆瓣.html', parser=parser)

# 解析网络HTML文件
tree = etree.HTML(open('./素材/豆瓣.html', 'r', encoding='UTF-8').read())
print(tree)

解析流程

  • 实例化一个etree的对象,把即将被解析的页面源码加载到该对象
  • 调用该对象的xpath方法结合着不同形式的xpath表达进行标签定位和数据提取

使用

  • 导入lxml.etree

    from lxml import etree

  • etree.parse()

    解析本地html文件

    html_tree = etree.parse('XX.html')

  • etree.HTML()(建议)

    解析网络的html字符串

    html_tree = etree.HTML(html字符串)

  • html_tree.xpath()

    使用xpath路径查询信息,返回一个列表

注意:如果lxml解析本地HTML文件报错可以按照如下添加参数

parser = etree.HTMLParser(encoding="utf-8")
selector = etree.parse('./lol_1.html',parser=parser)
result=etree.tostring(selector)

xpath语法

XPath 是一门在 XML 文档中查找信息的语言。XPath 用于在 XML 文档中通过元素和属性进行导航。

【留言:xpath语法免费获取教程】

2023最新自动化测试自学教程新手小白26天入门最详细教程,目前已有300多人通过学习这套教程入职大厂!!

  • 路径表达式

    表达式描述
    /从根节点选取。
    //从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。
    ./当前节点再次进行xpath
    @选取属性。

    实例

    在下面的表格中,我们已列出了一些路径表达式以及表达式的结果:

    路径表达式结果
    /html选取根元素。注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径!
    //li选取所有li 子元素,而不管它们在文档中的位置。
    //ul//li选择属于 ul元素的后代的所有 li元素,而不管它们位于 ul之下的什么位置。
    节点对象.xpath('./div')选择当前节点对象里面的第一个div节点
    //@href选取名为 href 的所有属性。
  • 谓语(Predicates)

    谓语用来查找某个特定的节点或者包含某个指定的值的节点。

    谓语被嵌在方括号中。

    实例

    在下面的表格中,我们列出了带有谓语的一些路径表达式,以及表达式的结果:

    路径表达式结果
    /ul/li[1]选取属于 ul子元素的第一个 li元素。
    /ul/li[last()]选取属于 ul子元素的最后一个 li元素。
    /ul/li[last()-1]选取属于 ul子元素的倒数第二个 li元素。
    //ul/li[position()❤️]选取最前面的两个属于 ul元素的子元素的 li元素。
    //a[@title]选取所有拥有名为 title的属性的 a元素。
    //a[@title='xx']选取所有 a元素,且这些元素拥有值为 xx的 title属性。
  • 选取未知节点

    XPath 通配符可用来选取未知的 XML 元素。

    通配符描述
    *匹配任何元素节点。 一般用于浏览器copy xpath会出现
    @*匹配任何属性节点。
    node()匹配任何类型的节点。

    实例

    在下面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:

    路径表达式结果
    /ul/*选取 ul元素的所有子元素。
    //*选取文档中的所有元素。
    //title[@*]选取所有带有属性的 title 元素。
    //node()获取所有节点

    选取若干路径

    通过在路径表达式中使用“|”运算符,您可以选取若干个路径。

    实例

    在下面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:

    路径表达式结果
    //book/title | //book/price选取 book 元素的所有 title 和 price 元素。
    //title | //price选取文档中的所有 title 和 price 元素。
    /bookstore/book/title | //price选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素。
  • 逻辑运算

    • 查找所有id属性等于head并且class属性等于s_down的div标签

      //div[@id="head" and @class="s_down"]
      
    • 选取文档中的所有 title 和 price 元素。

      //title | //price
      

      注意: “|”两边必须是完整的xpath路径

  • 属性查询

    • 查找所有包含id属性的div节点

      //div[@id]
      
    • 查找所有id属性等于maincontent的div标签

      //div[@id="maincontent"]
      
    • 查找所有的class属性

      //@class
      
    • //@attrName

      //li[@name="xx"]//text()  # 获取li标签name为xx的里面的文本内容
      
  • 获取第几个标签 索引从1开始

    tree.xpath('//li[1]/a/text()')  # 获取第一个
    tree.xpath('//li[last()]/a/text()')  # 获取最后一个
    tree.xpath('//li[last()-1]/a/text()')  # 获取倒数第二个
    
  • 内容查询

    查找所有div标签下的直接子节点h1的内容

    //div/h1/text()
    
  • 属性值获取

    //div/a/@href   获取a里面的href属性值
    
  • 获取所有

    //*  #获取所有
    //*[@class="xx"]  #获取所有class为xx的标签
    
  • 获取节点内容转换成字符串

    c = tree.xpath('//li/a')[0]
    result=etree.tostring(c, encoding='utf-8')
    print(result.decode('UTF-8'))
    
from lxml import etree
# 实例化
tree = etree.HTML(open('./素材/豆瓣.html', 'r', encoding='UTF-8').read())
# print(tree)
# / 按照路径层级  一级一级往下找
a_list = tree.xpath('/html/body/div/div/div/a')
# 获取a标签里的文本
# a_list = tree.xpath('/html/body/div/div/div/a/text()')
# print(a_list)
# for a in a_list:
#     print(a)    # <Element a at 0x1d49c8a1a08>
# #     print(a.text)  # 获取标签中文本
#     # 将节点对象转换为字符串
#     print(etree.tostring(a, encoding='UTF-8').decode('UTF-8'))  # <a href="https://www.douban.com/accounts/login?source=book" class="nav-login" rel="nofollow">登录</a>
#     print(type(etree.tostring(a, encoding='UTF-8').decode('UTF-8')))    # <class 'str'>


# // 不考虑位置
# 获取页面中的所有的a标签  无论在哪个位置
# a_list = tree.xpath('//a')
# print(a_list)

# for a in a_list:
#     print(a.text)  # 获取标签中文本
    # 将节点对象转换为字符串
    # print(etree.tostring(a, encoding='UTF-8').decode('UTF-8'))
    # print(type(etree.tostring(a, encoding='UTF-8').decode('UTF-8')))


# /与//的组合使用
# 获取登陆和注册
# a_list = tree.xpath('/html/body/div/div/div[1]/a/text()')
# print(a_list)
# 获取当前路径 /html/body/div/div/div  里面的所有的a 无论位置
# a_list = tree.xpath('/html/body/div/div/div//a/text()')
# print(a_list)

# 匹配ul下的li里面的所有的文本
# li_list = tree.xpath('//ul/li//text()')
# print(li_list)


# 添加查找条件
# li_list = tree.xpath('//ul[@class="cover-col-4 clearfix"]/li//text()')
# print(li_list)

# 查找标题
# title_list = tree.xpath('//div[@class="detail-frame"]/h2/a/text()')
# print(title_list)

# 位置查找
# 获取ul下的所有的直接子li
# li = tree.xpath('//ul[@class="cover-col-4 clearfix"]/li')
# 获取第一个li
# li = tree.xpath('//ul[@class="cover-col-4 clearfix"]/li[1]//text()')
# 获取第二个li
# li = tree.xpath('//ul[@class="cover-col-4 clearfix"]/li[2]//text()')
# 倒数第一个li
# li = tree.xpath('//ul[@class="cover-col-4 clearfix"]/li[last()]//text()')
# 倒数第二个
# li = tree.xpath('//ul[@class="cover-col-4 clearfix"]/li[last()-1]//text()')
# 获取前2个
# li = tree.xpath('//ul[@class="cover-col-4 clearfix"]/li[position()<3]//text()')
# 使用列表切片
# 获取第一个
# li = tree.xpath('//ul[@class="cover-col-4 clearfix"]/li')[0].xpath('.//text()')
# 获取最后一个
# li = tree.xpath('//ul[@class="cover-col-4 clearfix"]/li')[-1].xpath('.//text()')
# print(li)

# ./与.//
# li = tree.xpath('//ul[@class="cover-col-4 clearfix"]/li')[0]
# text = li.xpath('.//text()')  # 根据上面li的节点对象向下继续匹配
# 等同于
# li = tree.xpath('//ul[@class="cover-col-4 clearfix"]/li[1]//text()')
# .代表从当前节点继续向下匹配
# ./ 就是上面/的意思 一层一层往下找
# .// 就是上面//的意思 无论当前想要查找的内容在当前节点的哪个位置 都进行获取

# li = tree.xpath('//ul[@class="cover-col-4 clearfix"]/li')[0]
# text = li.xpath('./div[@class="detail-frame"]/h2/a/text()')  # 根据上面li的节点对象向下继续匹配
# print(text)
# 等同于
# li = tree.xpath('//ul[@class="cover-col-4 clearfix"]/li[1]/div[@class="detail-frame"]/h2/a/text()')
# print(li)


# li = tree.xpath('//ul[@class="cover-col-4 clearfix"]/li')[0]
# 当前匹配和li节点没有关系  因为没有从当前节点往下继续匹配
# text = li.xpath('//div[@class="detail-frame"]/h2/a/text()')
# text = tree.xpath('//div[@class="detail-frame"]/h2/a/text()')
# print(text)

# 属性值获取
# @属性名
# 获取所有的图片
# img_list = tree.xpath('//img')
# 获取所有图片的src地址 也就是连接
# img_list = tree.xpath('//img/@src')
# print(img_list)
# 获取所有超链接的href属性值
# a_list = tree.xpath('//a/@href')
# print(a_list)

# 当前作为了解
# 查找标签具有当前整个属性的节点
# a_list = tree.xpath('//a[@class]')
# a_list = tree.xpath('//a[@id]')
# print(a_list)
# a_list = tree.xpath('//@id')
# print(a_list)

# *  一般我们自己不写 但是复制xpath的时候会见到
# 不管当前是什么标签 条件就是id为content的我就要
# //*[@id="content"]/div/div[2]/ul/li[1]/div/h2/a

# 逻辑运算
'''
<div class="a1" id="a2">div1</div>
<div class="a1" id="a3">div2</div>
'''
# and
# text = tree.xpath('//div[@class="a1" and @id="a2"]/text()')
# print(text)
# or
# text = tree.xpath('//div[@class="a1" or @id="a2"]/text()')
# print(text)

# | 代码中我们去用

xpath实战练习

抓取豆瓣的标题,封面图片标签,图片的src,简介,评分

当前包含虚构类和非虚构类

匹配豆瓣图书虚构类

from lxml import etree

# 实例化
tree = etree.HTML(open('./素材/豆瓣.html', 'r', encoding='UTF-8').read())
'''
抓取封面
标题
简介
'''
li_list = tree.xpath('//ul[@class="cover-col-4 clearfix"]/li')
for li in li_list:
    img = li.xpath('./a/img/@src')
    title = li.xpath('./div/h2/a/text()')
    # info1 = li.xpath('./div/p[@class="color-gray"]/text()')
    # info2 = li.xpath('./div/p[@class="detail"]/text()')
    info = li.xpath('./div/p[@class="color-gray"]/text() | ./div/p[@class="detail"]/text()')
    print(info)

匹配豆瓣图书非虚构类

from lxml import etree
# 实例化
tree = etree.HTML(open('./素材/豆瓣.html', 'r', encoding='UTF-8').read())
'''
抓取封面
标题
简介
'''
li_list = tree.xpath('//ul[@class="cover-col-4 pl20 clearfix"]/li')
for li in li_list:
    img = li.xpath('./a/img/@src')
    title = li.xpath('./div/h2/a/text()')
    info = li.xpath('./div/p[@class="color-gray"]/text() | ./div/p[3]/text()')
    print(info)

整合抓取虚构类与费虚构类的数据

from lxml import etree
import re

# 实例化
tree = etree.HTML(open('./素材/豆瓣.html', 'r', encoding='UTF-8').read())
'''
抓取封面
标题
简介
'''
li_list = tree.xpath('//ul[@class="cover-col-4 pl20 clearfix"]/li | //ul[@class="cover-col-4 clearfix"]/li')
for li in li_list:
    img = li.xpath('./a/img/@src')[0]
    title = li.xpath('./div/h2/a/text()')[0]
    info = li.xpath('./div/p[@class="color-gray"]/text() | ./div/p[@class="detail"]/text() | ./div/p[3]/text()')
    info = re.sub('\s', '', ''.join(info))
    print(img)
    print(title)
    print(info)
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值