python爬虫之xpath入门

news2024/11/26 22:50:16

文章目录

    • 一、前言
      • 参考文档:
    • 二、xpath语法-基础语法
      • 常用路径表达式
      • 举例说明
    • 三、xpath语法-谓语
      • 表达式举例
      • 注意
    • 四、xpath语法-通配符
      • 语法
      • 实例
    • 五、选取多个路径
      • 实例
    • 六、Xpath Helper
      • 安装
      • 使用说明
      • 例子:
    • 七、python中 xpath 的使用
      • 安装xpath 的依赖包
      • xml节点的获取
      • xpath解析 html内容
        • 1. 以读取 html文件的方式进行解析
        • 2、对 html的内容进行解析

一、前言

XPATH(XML Path Language),它可以在 XML 和 HTML文档中对元素和属性进行查找和遍历。

  1. XPath 使用路径表达式来选取 XML 文档中的节点或节点集。
  2. 这些路径表达式和我们在常规的电脑文件系统中看到的表达式非常类似。
  3. 使用chrome 插件选择标签时候,选中时,选中的标签会添加属性class=“xh-highlight”

参考文档:

基础语法:https://www.w3school.com.cn/xpath/index.asp
python使用 xpath:https://blog.csdn.net/q1246192888/article/details/123649072

二、xpath语法-基础语法

常用路径表达式

表达式说明
nodename选取此节点的所有子节点
/绝对路径,如果写在最前面则从根节点选取,否则是当前节点下的子节点
//相对路径, 从匹配选择的当前节点下的直接或间接节点,而不考虑他们的位置。
.当前节点,类似于 linux 的当前目录
当前节点的父节点,类似与 linux 的上一级目录
text()一个开闭标签之间的文本内容
@某个节点标签内的属性

举例说明

  • footer: 获取 footer 节点下的所有子节点
  • /title: 根节点下所有title 标签
  • //div:根节点下所有的div 标签
  • ./div[@class=test-class].text():当前节点下,属性class=test-class的所有div 的文本内容
  • ./div[@id=test-id]…//a.text(): 当前节点下,属性id=test-id的div的 所有上一级a 标签的文本内容

三、xpath语法-谓语

可以根据标签的属性值、下标等来获取特定的节点

谓语用来查找某个特定的节点或者包含某个指定的值的节点。
谓语被嵌在方括号中。

表达式举例

路径表达式结果
//title[@lang=“eng”]选择lang 属性值为 eng 的所有 title元素
//bookstore/book[1]选取属于 bookstore 子元素的第一个book 元素
//bookstore/book[last()]选取属于 bookstore子元素的最后一个 book 元素
//bookstore/book[last()-1]选取属于 bookstore 子元素的倒数第二个 book 元素
//bookstore/book[position()>1]选择所有 bookstore 下面的 book元素,从第二个开始选择
//book/title[text()=‘Harry Potter’]选择所有 book下的title元素,仅仅选择文本为 Harry Potter 的 title 元素
//div[@id=“test-div-1”]/span选择 id="test-div-1"下的 div下的所有 span 节点
/bookstore/book[price>35]/title选取 bookstore元素的所有 title节点,且其中的 price 子节点的值必须大于35
//div[@id=“test-container”]/span/@class找到 id="test-container"的div下 的 span节点的所有class的值
//span[i>2000]找到所有 span 节点,且其中的 i子节点的text()大于2000
//div[span[2]>=9.4]找到所有的 div 节点,且子节点中第二个 span 的text()内容大于9.4
//div[contains(@id,“test_div_”)]找到所有 div节点,且id包含了"test_div_"
//div[@class=“pagination”]//span[contains(text(),“下一页”)]先找到class="pagination"的 div,再找其子节点span,且文本内容包下一页

注意

  • 只要涉及到条件的加[],只要涉及到加属性值加@
  • 凡事 /text(),/@ 加在最后,是取值,取的是前面 标签的属性值
  • text(),@ 加在[]中,则是修饰符,表示使用标签的属性名或属性值 来筛选节点,
  • xpath 的索引下标是从1开始
  • 常用函数 text()取标签之间的文本,contains(属性,“内容”)表示某节点属性包含的内容

四、xpath语法-通配符

xpath 的通配符用来选取未知的 html/xml 元素

语法

通配符说明
*匹配任何的元素节点
@*匹配任何属性节点
node()匹配任何类型的节点

实例

路径表达式说明
/bookstore/*选取bookstore节点下的所有子节点
//*选取文档中的所有文档
//tittle[@*]选取所有带有属性的 title元素

五、选取多个路径

通过 xpath 的运算符|,选取多个路径,表示多个路径的并集

实例

路径表达式说明
//book/title | //book/price选取 book元素下的所有title和 price元素
//title | //price选取文档中的所有title和 price元素
/bookstore/book/title | //price选取属于 bookstore节点下 book 节点下的所有 title节点 以及文档中所有的 price 元素

六、Xpath Helper

Xpath Helper是一个免费的 chrom插件,是用来方便调试 xpath 用的,可以提高效率,由日本的一名程序员开发,只是目前只有外网可以访问。
我是使用了CMYNetwork加速器 VPN通道来进行安装。当然往上免费的也可以下载到。

扩展链接地址
注:VPN节点最好选择美国的节点

安装

在这里插入图片描述

使用说明

  • 打开一个任意网站,百度贴吧为例,https://tieba.baidu.com/p/8940673717
  • 可以在浏览器的右上角点击图标按钮,或按下 Ctrl+Shift+X快捷键(mac os 上是 Command+Shift+X)就可以开启 xpath helper,如下图
    左侧区域显示的是 xpath 语法来筛选,右侧区域就来显示效果。
    在这里插入图片描述
  • 查找某一个或某一块节点元素的 xpath,可以按 Shift键,将鼠标移动到指定节点元素的位置就可以看到xpath了
    在这里插入图片描述
  • 也可以在右键—>检查,选择具体的节点,然后右键—>Copy—>Copy Xpath
    在这里插入图片描述
    将 copy的xpath复制到 xpath helper的查询框,就可以看结果是否正确了
    在这里插入图片描述

例子:

  • 以查看人工智能贴吧的某一条内容为例子:
<!--查看 class="d_post_content_main"节点下的 id="post_content_149887537934"节点的内容-->
//div[@class="d_post_content_main"]//div[@id="post_content_149887537934"]

在这里插入图片描述

  • 查看分页
    如下是来查找分页的 下一页的href的链接值
//div[@id="thread_theme_5"]//ul[@class="l_posts_num"]//a[text()="下一页"]/@href

在这里插入图片描述

七、python中 xpath 的使用

安装xpath 的依赖包

pip install lxml

xml节点的获取

源码上 xml 解析的源码,https://gitee.com/allen-huang/python/blob/master/crawler/do-parse/test_xml_xpath.py

  • xml 文件的内容
<?xml version="1.0" encoding="UTF-8" ?>
<root>
    <head>
        <title>xml的 xpath 测试</title>
    </head>
    <bookstore>
        <book>
            <title lang="zh">图解 HTTP 协议</title>
            <price>59</price>
        </book>
        <book>
            <title lang="zh">网络爬虫开发实战</title>
            <price>139</price>
        </book>
    </bookstore>
</root>
  • xml的解析文本内容
def test_xml(self):
    tree = etree.parse('book.xml')
    # 获取 head 节点下的 title 节点的文本内容
    print(tree.xpath('head/title/text()'))

    # 获取 bookstore 节点下的 book 的内容
    for element in tree.xpath('//bookstore'):
        # 当前节点下的 book 节点的 title 节点的文本内容
        print(element.xpath('book/title/text()'))
        # 当前节点下的 book 节点的 price 节点的文本内容
        print(element.xpath('book/price/text()'))
    pass

在这里插入图片描述

  • xml的属性筛选
def test_xml_fromstring(self):
    """
    加载 xml 字符串,筛选属性的所有 title 的节点内容
    @return:
    """
    xml_str = """
    <root>
        <head>
            <title>xml的 xpath 测试</title>
        </head>
        <bookstore>
            <book>
                <title lang="zh">图解 HTTP 协议</title>
                <price>59</price>
            </book>
            <book>
                <title lang="zh">网络爬虫开发实战</title>
                <price>139</price>
            </book>
        </bookstore>
    </root>
    """
    tree = etree.fromstring(xml_str)
    title_nodes = tree.xpath("//title[@lang='zh']")
    for node in title_nodes:
        print(node.text)
    
    price_nodes = tree.xpath("//price")
    for node in price_nodes:
        print(node.text)
    pass

在这里插入图片描述

xpath解析 html内容

解析 html的内容的源码地址:https://gitee.com/allen-huang/python/blob/master/crawler/do-parse/test_html_xpath.py

1. 以读取 html文件的方式进行解析

文件也一同放在码云上,book.html
读取一个html文档,需要是标准的html,对于标签不全的html,就会报错,而HTML()会修复html的标签

  • html文件的结构
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
    <title>豆瓣阅读</title>
</head>
<body>
<div class="bookstore-container">
    <ul class="bookstore-list">
        <li id="book-1" class="bookstore-item">
            <a href="https://read.douban.com/reader/ebook/52497819/" class="bookstore-cover">
                <div class="bookstore-info">
                    <div class="title">Java高并发编程:多线程与架构设计</div>
                    <div class="author">王文君</div>
                    <div class="price">59.00</div>
                    <div class="score">8.7</div>
                    <div class="publisher">机械工业出版社</div>
                </div>
            </a>
        </li>
        <li id="book-2" class="bookstore-item">
            <a href="https://read.douban.com/reader/ebook/153139284/" class="bookstore-cover">
                <div class="bookstore-info">
                    <div class="title">Java高并发编程详情</div>
                    <div class="author">王文君</div>
                    <div class="price">55.00</div>
                    <div class="score">8.2</div>
                    <div class="publisher">机械工业出版社</div>
                </div>
            </a>
        </li>
        <li id="book-3" class="bookstore-item">
            <a href="https://read.douban.com/reader/ebook/128052544/" class="bookstore-cover">
                <div class="bookstore-info">
                    <div class="title">深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)</div>
                    <div class="author">周志明</div>
                    <div class="price">99</div>
                    <div class="score">9.4</div>
                    <div class="publisher">机械工业出版社</div>
                </div>
            </a>
        </li>
    </ul>
</div>
</body>
</html>
  • 单元测试中的前置操作,设置共用对象
def setUp(self):
    """
    前置操作
    @todo 1.将一个html文件转化成html对象,etree.parse()默认只能读取一个标准的html文档,对于标签不全的html,需要加上etree.HTMLParser(),否则就会报错,
        而使用HTML()会修复html的标签
    @todo 2.将html字符串转化成html对象,并使用etree.HTML()读取
    @return:
    """
    # 从本地文件中读取 book.html 文档,并使用标准的html解析器
    self.html_load = etree.parse("book.html", etree.HTMLParser())
    # 这里在末尾特意少了一个</li>,用来测试,最后是否自动补全
    self.html_str = """
    <div class="fruits-container">
        <ul>
             <li class="item-0"><a href="apple.html">苹果</a></li>
             <li class="item-1"><a href="orange.html">"橘子"</a></li>
             <li class="item-inactive"><a href="banana.html"><span class="bold">香蕉</span></a></li>
             <li class="item-1"><a href="pear.html">香梨</a></li>
             <li class="item-0"><a href="strawberries.html">草莓</a></li>
             <li class="item-0"><a href="pineapple.html">菠萝</a>
         </ul>
     </div>
    """
    pass
  • 将 Element对象转为字符串
def test_tostring(self):
    """
    获取 html中的最外层的div标签
    @return:
    """
    html_div = self.html_load.xpath('//div[@class="bookstore-container"]')
    print(html_div)
    # 将 html对象转换成字符串是 bytes 类型,并且格式化输出,并进行解码
    print(etree.tostring(html_div[0], pretty_print=True, encoding="utf-8").decode())
    pass

在这里插入图片描述

  • 解析获取豆瓣读书的基本信息:

通过 xpath 将书的链接,书名,作者等存入到 mongodb 中

def test_load_file(self):
    """
    获取 html中所有的li标签
    @return:
    """
    html_li = self.html_load.xpath('//li[@class="bookstore-item"]')
    # 遍历 class="bookstore-item" 的所有li标签
    book_list = []
    for key, li in enumerate(html_li):
        # 获取当前li标签下的a标签的href属性
        url = li.xpath("./a/@href")
        # 获取当前li 标签下的 div=title的文本内容
        title = li.xpath(".//div[@class='title']/text()")
        # 获取当前 li 标签下的 div=author的文本内容
        author = li.xpath(".//div[@class='author']/text()")
        # 获取当前li 标签下的 div=price的文本内容
        price = li.xpath(".//div[@class='price']/text()")
        # 获取当前li 标签下的 div=score的文本内容
        score = li.xpath(".//div[@class='score']/text()")
        # 获取当前li 标签下的 div=publisher的文本内容
        publisher = li.xpath(".//div[@class='publisher']/text()")
        book_dict = {
            # "_id": key,  # 主键
            "url": Tools.get_list_element(url, 0),
            "title": Tools.get_list_element(title, 0),
            "author": Tools.get_list_element(author, 0),
            "price": Tools.get_list_element(price, 0),
            "score": Tools.get_list_element(score, 0),
            "publisher": Tools.get_list_element(publisher, 0)
        }
        book_list.append(book_dict)

    # 格式化打印数据
    pprint(book_list)

    # 将数据存入到 mongodb中
    res = MongoPool().test.bookstore.insert_many(book_list)
    print(res.inserted_ids)
  • 结果:
    在这里插入图片描述
  • mongo 的数据
    在这里插入图片描述
2、对 html的内容进行解析

这是直接使用 etree.HTML()进行分析,它一般是来解析来自远程响应的内容,并自带修复 html 标签的功能

  • html的结构
<div class="fruits-container">
    <ul>
         <li class="item-0"><a href="apple.html">苹果</a></li>
         <li class="item-1"><a href="orange.html">"橘子"</a></li>
         <li class="item-inactive"><a href="banana.html"><span class="bold">香蕉</span></a></li>
         <li class="item-1"><a href="pear.html">香梨</a></li>
         <li class="item-0"><a href="strawberries.html">草莓</a></li>
         <li class="item-0"><a href="pineapple.html">菠萝</a>
     </ul>
 </div>
  • 代码:
def test_parse_html(self):
    """
    使用 etree.HTML() 解析 html 文档
    etree.HTML() 会修复 html 标签,并且将 html 转化成 html 对象
    @return:
    """
    html = etree.HTML(self.html_str)
    print(etree.tostring(html, pretty_print=True, encoding="utf-8").decode())

    # 获取class=item-inactive的 标签最终的 text 内容
    text_list = html.xpath('//li[@class="item-inactive"]//text()')
    print(text_list)

    # 获取class=item-0 的最后一个标签的 text 内容
    itme0_last_text = html.xpath('//li[@class="item-0"][last()]//text()')
    print(itme0_last_text)

    # 获取class=item-1 的所有链接地址
    item1_href = html.xpath('//li[@class="item-1"]//a/@href')
    print(item1_href)

    # 查找所有class=bold 的标签,*所有标签
    bold_info = html.xpath('//*[@class="bold"]')
    # 将 bold_tag 转化成字符串
    print(etree.tostring(bold_info[0], pretty_print=True, encoding="utf-8").decode())
    print(bold_info[0].tag)
    pass

经过测试,打印出来的内容,自动补全为标准化 html
在这里插入图片描述
解析的结果:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1530772.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于VMware虚拟机安装MacOS BigSur系统

这周用VMWare搞了个MacOS虚拟机&#xff0c;也算是完成初中高中时候的梦想了吧~~&#xff08;那时候我的电脑配置还很拉跨&#xff0c;带不动虚拟机&#xff09;~~ 写一篇博客记录一下&#xff0c;当然这也是yonagi04.github.io建站的第一篇新博客 准备工作&#xff08;VMWare…

【Linux更新驱动、cuda和cuda toolkit】

目录 1. 更新显卡驱动1.1. 查看当前显卡驱动版本1.2. 删除原始显卡驱动1.3. 删除CUDA Toolkit1.4. 在NVIDIA官网找到2080Ti对应的最新驱动程序 2. 更新CUDA Toolkit2.1. 下载CUDA Toolkit2.2. 安装.run2.3. 添加环境变量2.4. 检查是否安装好了 最近需要更新服务器的显卡驱动和C…

yolov7 gui 轻松通过GUI来实现车辆行人计数

YOLOv7 GUI 是一款用户友好型图形界面应用程序&#xff0c;专为简化基于YOLOv7&#xff08;You Only Look Once version 7&#xff09;的目标检测流程而设计。该工具允许用户无需深入掌握命令行操作和复杂编程细节&#xff0c;即可方便快捷地运行YOLOv7模型来检测图像或视频中的…

精简版 Obsidian 图床配置 PicGo+ gitee

精简版 Obsidian 图床配置 PicGo gitee 图床的作用 图床&#xff08;Image Hosting Service&#xff09;是一种在线服务&#xff0c;用于存储和托管用户上传的图片文件。用户可以将图片上传到图床服务器&#xff0c;并获得一个可访问的图片链接&#xff0c;然后可以在网页、博…

NVIDIA最新 Blackwell架构简介

NVIDIA Blackwell架构简介 在AI和大型语言模型&#xff08;LLMs&#xff09;迅速发展的领域中&#xff0c;追求实时性能和可扩展性至关重要。从医疗保健到汽车行业&#xff0c;组织正深入探索生成性AI和加速计算解决方案的领域。对生成性AI解决方案的需求激增&#xff0c;促使企…

安防监控视频汇聚平台EasyCVR接入海康Ehome设备,设备在线但视频无法播放是什么原因?

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安…

视频监控平台问题-通过url免密直接浏览实时视频出错的问题解决

目 录 一、通过url免密浏览实时监控视频介绍 二、浏览出错现象描述 1、问题提出 2、问题描述 &#xff08;1&#xff09;现象 &#xff08;2&#xff09;前端调试 &#xff08;3&#xff09;后端日志 三、问题解决 1、问题分析 2&#xff0c;查找资源&#…

【MQTT】Vue中使用mqtt

MQTT&#xff08;Message Queuing Telemetry Transport&#xff09;作为一种轻量级、开放、灵活、简单、易于实现的通信协议。它基于发布/订阅&#xff08;Publish/Subscribe&#xff09;模式的消息传输协议&#xff0c;在上位机和硬件设备间通信时经常用到。虽然在嵌入式软件一…

1、Java虚拟机学习-类的生命周期-加载阶段-以及怎样查看方法区中的对象和堆中对象的关联以及静态变量存在什么地方

类的生命周期 其中连接又可以分为3个小阶段 一、加载阶段 1、加载阶段第一步是类加载器根据类的全限定名通过不同的渠道以二进制流的方式获取字节码信息。 渠道: 2、类加载器在加载完类之后&#xff0c;Java虚拟机会将字节码中的信息保存在内存的方法区中。 方法区是虚拟…

AI - 机器学习GBDT算法

目录 GBDT 提升树 梯度提升树 GBDT算法实战案例 XGBoost &#x1f606;&#x1f606;&#x1f606;感谢大家的观看&#x1f606;&#x1f606; GBDT 梯度提升决策树&#xff08;Gradient Boosting Decision Tree&#xff09;&#xff0c;是一种集成学习的算法&…

基于springboot+vue的餐饮管理系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

GAMES101 学习3

Lecture 13 ~ 16 Shadow mapping 一种图像空间算法生成阴影时不需要知道场景中的几何信息会产生走样现象 最重要的思想&#xff1a;如果有的点不在阴影里你又能看到这个点&#xff0c;那么说明摄像机可以看到这个点&#xff0c;光源也可以看到这个点 经典的Shadow mapping …

提升合规性!Zoho如何优化CRM产品合规性?

在企业数字化和信息化高速发展的今天&#xff0c;CRM管理系统成为越来越多企业的选择。然而&#xff0c;不是所有CRM供应商都有合规意识。合规性不应当只是一项法律规定&#xff0c;更是保证CRM供应商持续发展、赢得客户信赖以及应付监管压力的关键支撑。Zoho对企业合规性的重视…

智能码垛机:企业高效物流管理的得力助手

在快速发展的现代企业中&#xff0c;高效物流管理不仅是提升竞争力的关键&#xff0c;更是降低成本、增加利润的重要手段。随着科技的进步&#xff0c;智能码垛机作为现代物流技术的重要组成部分&#xff0c;正日益成为企业实现高效物流管理的得力助手。 一、智能码垛机的工作原…

基于Python的口罩佩戴识别的设计与实现(UI界面+MySQL数据库+YOLOv5+训练数据集+开题报告+中期检查+论文)

摘要 文旨在基于Python开发一种口罩佩戴识别系统&#xff0c;通过深度学习技术实现对口罩佩戴情况的准确检测。采用了YOLOv5系列目标检测算法作为基础模型&#xff0c;并结合迁移学习进行训练和优化。同时&#xff0c;为了提供更好的用户体验&#xff0c;本系统还设计了用户登录…

排序算法之选择排序介绍

目录 算法简介 算法描述 代码实现 算法简介 选择排序(Selection-sort)是一种简单直观的排序算法。它的工作原理&#xff1a;首先在未排序序列中找到最小&#xff08;大&#xff09;元素&#xff0c;存放到排序序列的起始位置&#xff0c;然后&#xff0c;再从剩余未排序元素…

再谈EMC Unity存储系统内存DIMM问题

以前写过一篇关于EMC Unity 存储系统的DIMM的介绍文章&#xff0c;但是最近还是遇到很多关于内存的问题&#xff0c;还有一些退货&#xff0c;所以有必要再写一篇关于EMC Unity 内存方面的问题&#xff0c;供朋友们参考。如果还有疑问&#xff0c;可以加vx&#xff1a;StorageE…

代码随想录day24(1)二叉树:最大二叉树(leetcode654)

题目要求&#xff1a; 给定一个不含重复元素的整数数组。一个以此数组构建的最大二叉树定义如下&#xff1a; 二叉树的根是数组中的最大元素。左子树是通过数组中最大值左边部分构造出的最大二叉树。右子树是通过数组中最大值右边部分构造出的最大二叉树。 通过给定的数组构…

【爬虫实战】使用Python获取花粉俱乐部中Mate60系列的用户发帖数据

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

重装系统后鼠标识别不了咋办

不知道大家在重装系统时,有没有遇到过系统重装完成后,鼠标不能使用的情况。在这种情况下,我们要怎么操作电脑解决这个问题呢?今天就跟大家分享重装系统后鼠标识别不了咋办。 一、主板没有设置兼容usb 在重装系统时,如果主板没有设置兼容usb,就会出现鼠标使用不了的现象。…