Python爬虫-xpath方法爬虫技术分享,更高效,代码简洁!

news2024/11/21 0:18:28

这里写目录标题

  • 一、获取文档树对象
    • 二、文本转化文档树对象
      • 文件转化文档树对象
      • 节点、元素、属性、内容
      • 路径表达式
      • 通配符
      • 谓语
      • 多个路径
      • 函数
      • 实战信息
    • ↓ ↓ ↓ 加下方名片找我,直接拿源码还有案例 ↓ ↓ ↓

一、获取文档树对象

通过Xpath 获取文档的对象,获取到对象后,可以通过文档的对象去去获取到树中的元素。

二、文本转化文档树对象

def strToEleObj():
    doc = '''
          <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>
          '''
    # 把文本转换成一个文档树对象
    html = etree.HTML(doc)
    result = etree.tostring(html)
    print(str(result, 'utf-8'))

文件转化文档树对象

def fileToEleObj():
    # 读取外部文件 index.html
    html = etree.parse('./index.html')
    # pretty_print=True 会格式化输出
    result = etree.tostring(html, pretty_print=True)  # pretty_print=True 会格式化输出
    print(result)

节点、元素、属性、内容

xpath 的思想是通过 路径表达 去寻找节点。节点包括元素,属性,和内容

路径表达式

/ 根节点,节点分隔符,
// 任意位置
. 当前节点
… 父级节点
@ 属性

例子:

from lxml import etree
'''
    路径表达式
'''
def get_el_list():
    doc = '''
              <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>
              '''
    # 把文本转换成一个文档树对象
    html = etree.HTML(doc)
    # 获取当前节点
    print('获取当前节点---> ', html.xpath('.'))
    # 获取 根节点 标签 ,当前元素无根节点 通过 打印 etree.tostring(html) ,会发现根节点为 <html> </html> 包裹的内容 ,上一行获取的当前节点为 html
    print('获取 根节点 标签---> ', html.xpath('/'))
    # 获取 li 标签
    print('获取 li 标签---> ', html.xpath('//li'))
    # 获取 li 下的 a 标签属性
    print('获取li下的 a 标签属性----> ', html.xpath('//li/a/@href'))
    # 获取 p 标签 ,此标签不存在 返回结果为空数组
    print('获取 p 标签----> ', html.xpath('//p '))

输出结果

获取当前节点--->  [<Element html at 0x2a989854200>]
获取 根节点 标签--->  []
获取 li 标签--->  [<Element li at 0x2a9898ece40>, <Element li at 0x2a9899240c0>, <Element li at 0x2a989924180>, <Element li at 0x2a9899241c0>, <Element li at 0x2a989924200>]
获取li下的 a 标签属性---->  ['link1.html', 'link2.html', 'link3.html', 'link4.html', 'link5.html']
获取 p 标签---->  []

  1. 将doc 转换成 文档对象后,为 包裹的内容;故获取到的当前的节点对象为HTML;
  2. 当前节点为HTML,无根节点故返回为空数组即:[];
  3. 查询不存在的节点时,返回空数组即:[]

通配符

*   任意元素
@*  任意属性
node()  任意子节点(元素,属性,内容)

例子:


'''
    通配符
'''
from lxml import etree
def get_el_by_anyChar():
    doc = '''
              <div>
                  <ul class="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>
              '''
    # 把文本转换成一个文档树对象
    html = etree.HTML(doc)
    # 获取 ul 下的所有子节点
    print('获取 ul 下的所有子节点---> ', html.xpath('//ul/node()'))
    # 获取 任意元素[所有的]
    print('获取 ul 下 任意元素[所有的]---> ', html.xpath('//ul/*'))
    # 获取 任意属性 [所有的]
    print('获取 ul 下 任意属性[所有的]---> ', html.xpath('//ul/@*'))

输出结果

获取 ul 下的所有子节点--->  ['\n                       ', <Element li at 0x1d4792b5e80>, '\n                       ', <Element li at 0x1d4792b5e00>, '\n                       ', <Element li at 0x1d4792b5f00>, '\n                       ', <Element li at 0x1d4792b5f40>, '\n                       ', <Element li at 0x1d4792b5ec0>, ' 闭合标签\n                   ']
获取 任意元素--->  [<Element li at 0x1d47928dd80>, <Element li at 0x1d4792b5e80>, <Element li at 0x1d4792b5fc0>, <Element li at 0x1d4792b5e00>, <Element li at 0x1d4792b5f00>]
获取 任意属性--->  ['ul']

谓语

//a[n] n为大于零的整数,代表子元素排在第n个位置的<a>元素
//a[last()]   last()  代表子元素排在最后个位置的<a>元素
//a[last()-]  和上面同理,代表倒数第二个
//a[position()<3] 位置序号小于3,也就是前两个,这里我们可以看出xpath中的序列是从1开始
//a[@href]    拥有href的<a>元素
//a[@href='www.baidu.com']    href属性值为'www.baidu.com'<a>元素
//book[@price>2]   price值大于2<book>元素

例子;

from lxml import etree
def get_el_by_wei():
    doc = '''
                  <div>
                      <ul class="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>
                  '''
    # 把文本转换成一个文档树对象
    html = etree.HTML(doc)
    # 获取第一个 li / a 元素 里面的文本
    print('获取第一个 ---> ', html.xpath('//li[1]/a/text()'))
    # 获取最后一个 li / a 元素 里面的文本
    print('获取最后一个 ---> ', html.xpath('//li[last()]/a/text()'))
    # 获取倒数第二个 li / a元素 里面的文本
    print('获取 倒数第二个---> ', html.xpath('//li[last()-1]/a/text()'))
    # 获取位置序号小于3,也就是前两个 li / a元素 里面的文本
    print('获取位置序号小于3 ---> ', html.xpath('//li[position()<3]/a/text()'))
    # 获取拥有href的<a>元素下的文本
    print('获取第一个 ---> ', html.xpath('//a[@href]/text()'))
    # 获取 a 标签下 href = link3.html的a元素下的文本 注意 不是 == 而是 =
    print('获取 a 标签下 href = link3.html的<a>元素---> ', html.xpath('//a[@href="link3.html"]/text()'))
    # 获取 ul class == ul 的
    print('获取 ul class == ul  ---> ', html.xpath('//ul[@class="ul"]'))

多个路径

用| 连接两个表达式,可以进行 或匹配

//book/title | //book/price  

例子;

from lxml import etree
def get_el_mutil_path():
    doc = '''
                  <div>
                      <ul class="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>
                  '''
    # 把文本转换成一个文档树对象
    html = etree.HTML(doc)
    # 获取li 下 class = item-inactive 或者 item-1
    print('获取li 下 class = item-inactive 或者 item-1 ---> ', html.xpath('//li[@class="item-inactive"] | //li[@class="item-1"] '))

输出结果;

获取li 下 class = item-inactive 或者 item-1 --->  [<Element li at 0x1b490955f40>, <Element li at 0x1b490966200>, <Element li at 0x1b490966180>]

函数

contains(string1,string2)
starts-with(string1,string2)
# 文本
text()
# 最后一个
last()
# 位置
position()
# 回去所有节点
node()

'''
    函数
'''
from lxml import etree
def get_el_func():
    doc = '''
                     <div>
                         <ul class="ul" >
                              <li class="item-0 active"><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>
                     '''
    # 把文本转换成一个文档树对象
    html = etree.HTML(doc)
    # 匹配 class 包含 active 的 元素
    print(html.xpath("//*[contains(@class,'active')]"))
    # 获取所有 li / a 文本
    print(html.xpath("//li/a/text()"))
    # 获取最后一个 li / a 文本
    print(html.xpath("//li[last()]/text()"))
    # 获取位置为1的li /a 文本 ,节点时从1开始 而不是0
    print(html.xpath("//li[position()=1]/a/text()"))

输出结果;

[<Element li at 0x23ea36d0400>, <Element li at 0x23ea36d0180>]
['first item', 'second item', 'third item', 'fourth item', 'fifth item']
[' # 注意,此处缺少一个 ']
['first item']

实战信息

获取某电影网站电影名称、简单描述、图片

import requests
from lxml import etree

'''
     获取电影信息列表
'''
def get_moive_info_list(url):
        # 定义头部信息
        headers = {
                'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'
        }
        res = requests.get(url, headers=headers)
        # res.text 返回的是 文本
        html = res.text
        print('输出响应信息->',html)
        # 将文本转换成文档对象
        selector = etree.HTML(html)
        # 返回是电影名列表
        title_list = selector.xpath('//a[@class="pic-pack-outer"]/h3/text()')
        print('电影名称列表:',title_list)
        # 获取简单描述
        desc_list = selector.xpath('//a[@class="pic-pack-outer"]/p/text()')
        print('电影名称简单描述:', desc_list)
        # 图片
        img_list = selector.xpath('//a[@class="pic-pack-outer"]/img/@src')
        print('图片列表:', img_list)

if __name__ == '__main__':
        url = 'https://xxxxxxx/vod/list/n_1_t_25/o1p1.html'
        get_moive_info_list(url)

输出结果

输出响应信息-> <!DOCTYPE html>
·······
</body>
</html>
电影名称列表: ['辣妈犟爸', '五月梨花香', '岁岁平安',.....]
电影名称简单描述: ['年轻村官奋斗历程', '脱贫致富振兴家乡', .....]
图片列表: ['https://image11.m1905.cn/uploadfile/2022/0804/thumb_1_150_203_20220804094442559303.jpg',  .... 'https://image11.m1905.cn/uploadfile/2016/0926/thumb_1_150_85_20160926105222739343.jpg']

请添加图片描述

↓ ↓ ↓ 加下方名片找我,直接拿源码还有案例 ↓ ↓ ↓

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

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

相关文章

matlab定义函数

1新建文件 首先建立M文件或直接点击&#xff08;File/New/Function)建立函数文件&#xff0c;其中函数文件的格式是&#xff1a; function [输出变量] 函数名称(输入变量&#xff09; % 注释 % 函数体 2函数语法 2.1基本语法 function yf(x) %函数的声明 yx^2 就是建立了一个y…

边框虚线滚动动画特效

边框线条效果如上 /*边框虚线滚动动画特效*/.border-animate {background: linear-gradient(90deg, gray 60%, transparent 60%) repeat-x left top/10px 1px,linear-gradient(0deg, gray 60%, transparent 60%) repeat-y right top/1px 10px,linear-gradient(90deg, gray 60%,…

今天面了一个来字节要求月薪23K,明显感觉他背了很多面试题...

最近有朋友去字节面试&#xff0c;面试前后进行了20天左右&#xff0c;包含4轮电话面试、1轮笔试、1轮主管视频面试、1轮hr视频面试。 据他所说&#xff0c;80%的人都会栽在第一轮面试&#xff0c;要不是他面试前做足准备&#xff0c;估计都坚持不完后面几轮面试。 其实&…

用于2.4GHz ISM频段FHSS解决方案的射频IC

比较了 WLAN 和相关系统。IEEE802.11b FHSS 支持 1.6Mbps 数据传输。MAX2644 SiGe LNA用作2.5GHz频段的PA驱动器和接收器低噪声放大器&#xff08;LNA&#xff09;。MAX2240和MAX2242功率放大器&#xff08;PA&#xff09;产生~20dBm输出&#xff0c;具有所需的线性度。MAX2754…

EasyRecovery15Mac中文电脑版安装详细操作教程

EasyRecovery是一款操作安全、恢复性比较高的数据恢复工具&#xff0c;小伙伴们可以使用EasyRecovery恢复各种各样被删除的文件、视频、图片等。EasyRecovery还可以支持恢复被格式化的媒体文件&#xff0c;只是使用EasyRecovery恢复时时间较久。如果小伙伴们有误删除的文件需要…

第三十三章 Unity Mecanim动画系统(下)

本章节&#xff0c;我们继续讲解Unity的 Mecannim 动画系统。在上一章节中&#xff0c;我们设置了动画过渡&#xff0c;但是还没有为这些动画过渡设置过渡条件。这个过渡条件需要在“Animator”窗口中设置。这个窗口的左边是用来编辑“动画层”和“动画参数”的。这里的“动画参…

Redis的20种使用场景

本文介绍Redis除了缓存以外的使用场景。 测试源码&#xff1a;https://github.com/vehang/ehang-spring-boot/tree/main/spring-boot-011-redis 1缓存 本文假定你已经了解过Redis&#xff0c;并知晓Redis最基础的一些使用&#xff0c;如果你对Redis的基础API还不了解&#xff…

Kubernetes服务搭建[配置-部署](Kubeadm)

文章目录 **[1 — 7] ** [ 配置K8S主从集群前置准备操作 ]一&#xff1a;主节点操作 查看主机域名->编辑域名1.1 编辑HOST 从节点也做相应操作1.2 从节点操作 查看从节点102域名->编辑域名1.3 从节点操作 查看从节点103域名->编辑域名 二&#xff1a;安装自动填充&…

Android - 动画

一、概念 补间动画 ViewAnimation&#xff08;Tween&#xff09;&#xff1a;不改变view的位置和属性。属性动画PeopertyAnimation&#xff1a;view的属性根据执行的动画发生真实的改变。帧动画 DrawableAnimation&#xff08;Frame&#xff09;&#xff1a; 二、补间动画 Vi…

SPSS如何进行使用时间序列模型之案例实训?

文章目录 0.引言1.时间序列数据平稳处理2.指数平滑法建模3.ARIMA建模4.季节性分解 0.引言 因科研等多场景需要进行绘图处理&#xff0c;笔者对SPSS进行了学习&#xff0c;本文通过《SPSS统计分析从入门到精通》及其配套素材结合网上相关资料进行学习笔记总结&#xff0c;本文对…

MYSQL用户组管理

1&#xff1a;使用明文密码创建用户 使用密文密码创建用户 1.2 查看用户信息 1.3 重命名用户 rename 1.4 删除用户信息 drop 1.5 修改当前登录用户的密码 set password password(123456); 1.6 修改其他用户的密码 set password for nancylocalhost password(abc123); 1.7…

2023年常见的20道JavaScript面试题及其答案解析,你知道多少

JavaScript中typeof操作符有哪些返回值&#xff1f; 答案&#xff1a;typeof操作符返回字符串数据类型。可能的返回值有&#xff1a;“undefined”、“boolean”、“number”、“string”、“object"和"function”。如何检查一个变量是否为数组&#xff1f; 答案&…

【JavaEE】Thread类

目录 前言 1、创建一个线程 1.1、 体会多线程的执行 1.2、体会单线程的执行 1.3、sleep方法&#xff08;休眠&#xff09; 1.4、通过第三方程序来观察线程详情 1.5、创建线程的方式 1.5.1、继承Thread类&#xff0c;重写run方法来创建线程 1.5.2、实现Runnable接口&am…

linux 查看系统版本

文章目录 一、查看Linux内核版本的命令二、查看Linux系统发行版本的命令三、 延伸&#xff1a; 一、查看Linux内核版本的命令 cat /proc/version 此命令可以查看正在运行的内核版本信息。/proc 目录存储的是当前内核运行状态的一系列特殊文件&#xff0c;包括&#xff1a;内存…

electron源码保护

electron 程序发布后&#xff0c;如果未对程序做保护&#xff0c;则极容易受到破坏&#xff0c;比如被轻松破解密码&#xff0c;或者被修改程序&#xff0c;所以必须对程序做一些安全防护。虽然没有100%的安全防护&#xff0c;但是提升破解难度&#xff0c;直至破解代价超出了范…

UML图中的domain model,object model,system sequence diagram以及interaction diagram

UML图&#xff08;Unified Modeling Language&#xff0c;统一建模语言&#xff09;是一种用于描述、可视化、构建和记录软件系统的标准化建模语言。在UML中&#xff0c;有很多类型的图&#xff0c;其中包括领域模型&#xff08;Domain Model&#xff09;、对象模型&#xff08…

拥抱智能时代:初探RFID系统

在数字化时代&#xff0c;人们越来越追求高效率和高质量的体验&#xff0c;以获得更快乐、更好的生活。RFID系统作为一项智能化管理技术&#xff0c;正越来越广泛地应用于各个领域&#xff0c;以提高效率和质量。本文将介绍RFID系统的基本概念、工作原理和实际应用案例&#xf…

OpenAI的编程语言和框架,给程序员带来了帮助有哪些

OpenAI 是一个人工智能开发公司&#xff0c;成立于2015年&#xff0c;总部位于美国旧金山。这家公司致力于研究和开发先进的人工智能技术&#xff0c;旨在将这些技术应用到解决全球一些最棘手的问题上。 OpenAI 以其卓越的技术和实验室出品的 groundbreaking AI papers 而闻名…

Android焦点流程梳理

作者&#xff1a;Cy13er 前言 最近在看一些焦点处理的问题&#xff0c;认真处理起来发现不跟着源码自己走一遍焦点相关的流程&#xff0c;对于问题的分析上会比较困难。所以本文主要对焦点流程进行一次梳理&#xff0c;在处理类似问题时也可以作为手册阅读。 起源 一切都要从…

Apache Kafka 进阶(一)

官网 Apache Kafka是一个开源的分布式事件流平台&#xff0c;被数千家公司用于高性能数据管道、流分析、数据集成和关键任务应用。 核心能力 高吞吐量 在网络有限的吞吐量下&#xff0c;使用延迟低至2ms的机器集群交付消息。可扩展性 将生产集群扩展到1000个代理&#xff0c…