热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

小白学Python爬虫(20):Xpath进阶

人生苦短,我用Python前文传送门:小白学Python爬虫(1):开篇小白学Python爬虫(2):前置准备(一)基本类库的安装小白学Python爬虫(3):前置准备(二)Lin


人生苦短,我用 Python


前文传送门:

小白学 Python 爬虫(1):开篇

小白学 Python 爬虫(2):前置准备(一)基本类库的安装

小白学 Python 爬虫(3):前置准备(二)Linux基础入门

小白学 Python 爬虫(4):前置准备(三)Docker基础入门

小白学 Python 爬虫(5):前置准备(四)数据库基础

小白学 Python 爬虫(6):前置准备(五)爬虫框架的安装

小白学 Python 爬虫(7):HTTP 基础

小白学 Python 爬虫(8):网页基础

小白学 Python 爬虫(9):爬虫基础

小白学 Python 爬虫(10):Session 和 COOKIEs

小白学 Python 爬虫(11):urllib 基础使用(一)

小白学 Python 爬虫(12):urllib 基础使用(二)

小白学 Python 爬虫(13):urllib 基础使用(三)

小白学 Python 爬虫(14):urllib 基础使用(四)

小白学 Python 爬虫(15):urllib 基础使用(五)

小白学 Python 爬虫(16):urllib 实战之爬取妹子图

小白学 Python 爬虫(17):Requests 基础使用

小白学 Python 爬虫(18):Requests 进阶操作

小白学 Python 爬虫(19):Xpath 基操


引言

文接上篇,我们接着聊,上篇我们介绍了 Xpath 一些常用的匹配方式, DOM 节点我们可以匹配出来了,这并不是我们的最终目的,我们是要从这些节点中取出来我们想要的数据。本篇我们接着介绍如何使用 Xpath 获取数据。


文本获取

我们先尝试下获取第一篇文章的题目,获取节点中的文本我们可以使用 text() 来进行获取,如图:

代码如下:

from lxml import etree
import requests
respOnse= requests.get('https://www.geekdigging.com/')
html_str = response.content.decode('UTF-8')
html = etree.HTML(html_str)
result_1 = html.xpath('/html/body/section/div/div/main/article[1]/div[2]/div/h3/a/text()')
print(result_1)

结果如下:

['小白学 Python 爬虫(18):Requests 进阶操作']

哇,上面示例里面的表达式好长啊,这个怎么写出来的,怎么写的稍后再说,先介绍一下这个表达式的意思,仔细看一下,这个表达式其实是从整个 HTML 源代码的最外层的 标签写起,一层一层的定位到了我们所需要的节点,然后再使用 text() 方法获取了其中的文本内容。

关于这个表达式怎么来的,肯定不是小编写的,这么写讲实话是有点傻,完全没必要从整个文档的最外层开始写。

其实这个是 Chrome 帮我们生成的,具体操作可见下图:

这时 Chrome 会自动帮我们把这个节点的表达式 copy 到当前的剪切板上,只需要我们在程序里 ctrl + v 一下。


属性获取

有些情况下,我们可能不止需要节点中的文本数据,可能还会需要节点中的属性数据,比如上面的示例,我们除了想知道文章标题,其实还想知道文章的跳转路径:

result_2 = html.xpath('/html/body/section/div/div/main/article[1]/div[2]/div/h3/a/@href')
print(result_2)

结果如下:

['/2019/12/11/1468953802/']

这里需要注意的是,此处和属性匹配的方法不同,属性匹配是中括号加属性名和值来限定某个属性,如 [@class="container"] ,而此处的 @href 指的是获取节点的某个属性,二者需要做好区分。


属性多值匹配

某些时候吧,某些节点的某个属性可能有多个值,这个多见于 class 属性,由于某些编码习惯以及某些其他原因,这个属性经常性会出现多个值,这时如果只使用其中的一个值的话,就无法匹配了。

如果这么写的话:

result_3 = html.xpath('//div[@class="post-head"]')
print(result_3)

结果如下:

[]

可以看到,这里没有匹配到任何节点,这时,我们可以使用一个函数:contains() ,上面的示例可以改成这样:

result_3 = html.xpath('//div[contains(@class, "post-head")]')
print(result_3)

这样通过 contains() 方法,第一个参数传入属性名称,第二个参数传入属性值,只要此属性包含所传入的属性值,就可以进行匹配了。


多属性匹配

除了上面的一个属性有多个值的情况,还经常会出现需要使用多个属性才能确定一个唯一的节点。

这时,我们可以使用运算符来进行处理。

还是这个示例,我们获取 这个节点,如果只是使用 class 属性来进行获取,会获得很多个节点:

result_4 = html.xpath('//img[@class="img-ajax"]')
print(result_4)

结果如下:

[, , , , , , , , , , , ]

如果我们加上 alt 属性一起进行匹配的话,就可以获得唯一的节点:

result_4 = html.xpath('//img[@class="img-ajax" and @alt="小白学 Python 爬虫(18):Requests 进阶操作"]')
print(result_4)

结果如下:

[]

Xpath 支持很多的运算符,详细见下表(来源:https://www.w3school.com.cn/xpath/xpath_operators.asp)

































































































运算符描述实例返回值
|计算两个节点集//book | //cd返回所有拥有 book 和 cd 元素的节点集
+加法6 + 410
-减法6 - 42
*乘法6 * 424
div除法8 div 42
=等于price=9.80如果 price 是 9.80,则返回 true。如果 price 是 9.90,则返回 false。
!=不等于price!=9.80如果 price 是 9.90,则返回 true。如果 price 是 9.80,则返回 false。
<小于price<9.80如果 price 是 9.00,则返回 true。如果 price 是 9.90,则返回 false。
<=小于或等于price<=9.80如果 price 是 9.00,则返回 true。如果 price 是 9.90,则返回 false。
>大于price>9.80如果 price 是 9.90,则返回 true。如果 price 是 9.80,则返回 false。
>=大于或等于price>=9.80如果 price 是 9.90,则返回 true。如果 price 是 9.70,则返回 false。
orprice=9.80 or price=9.70如果 price 是 9.80,则返回 true。如果 price 是 9.50,则返回 false。
andprice>9.00 and price<9.90如果 price 是 9.80,则返回 true。如果 price 是 8.50,则返回 false。
mod计算除法的余数5 mod 21

按顺序选择

有些时候,我们匹配出来很多的节点,但是我们只想获取其中的某一个节点,比如第一个或者最后一个,这时可以使用中括号传入索引的方法获取特定次序的节点。

我们还是文章的题目为例,我们先获取所有的文章题目,再进行选择,示例代码如下:

result_5 = html.xpath('//article/div/div/h3[@class="post-title"]/a/text()')
print(result_5)
result_6 = html.xpath('//article[1]/div/div/h3[@class="post-title"]/a/text()')
print(result_6)
result_7 = html.xpath('//article[last()]/div/div/h3[@class="post-title"]/a/text()')
print(result_7)
result_8 = html.xpath('//article[position() <5]/div/div/h3[@class="post-title"]/a/text()')
print(result_8)

结果如下:

['小白学 Python 爬虫(18):Requests 进阶操作', '小白学 Python 爬虫(17):Requests 基础使用', '小白学 Python 爬虫(16):urllib 实战之爬取妹子图', '如何用 Python 写一个简易的抽奖程序', '小白学 Python 爬虫(15):urllib 基础使用(五)', '我们真的在被 APP “窃听” 么?', '小白学 Python 爬虫(14):urllib 基础使用(四)', '小白学 Python 爬虫(13):urllib 基础使用(三)', '小白学 Python 爬虫(12):urllib 基础使用(二)', '小白学 Python 爬虫(11):urllib 基础使用(一)', '老司机大型车祸现场', '小白学 Python 爬虫(10):Session 和 COOKIEs']
['小白学 Python 爬虫(18):Requests 进阶操作']
['小白学 Python 爬虫(10):Session 和 COOKIEs']
['小白学 Python 爬虫(18):Requests 进阶操作', '小白学 Python 爬虫(17):Requests 基础使用', '小白学 Python 爬虫(16):urllib 实战之爬取妹子图', '如何用 Python 写一个简易的抽奖程序']

第一次,我们选取了当前页面所有的文章的题目。

第二次,我们选择了当前页面第一篇文章的题目,这里注意下,中括号中传入数字1即可,这里的开始是以 1 为第一个的,不是程序中的 0 为第一个。

第三次,我们使用 last() 函数,获取了最后一篇文章的题目。

第四次,我们选择了位置小于 5 的文章题目。


节点轴

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



























































轴名称结果
ancestor选取当前节点的所有先辈(父、祖父等)。
ancestor-or-self选取当前节点的所有先辈(父、祖父等)以及当前节点本身。
attribute选取当前节点的所有属性。
child选取当前节点的所有子元素。
descendant选取当前节点的所有后代元素(子、孙等)。
descendant-or-self选取当前节点的所有后代元素(子、孙等)以及当前节点本身。
following选取文档中当前节点的结束标签之后的所有节点。
namespace选取当前节点的所有命名空间节点。
parent选取当前节点的父节点。
preceding选取文档中当前节点的开始标签之前的所有节点。
preceding-sibling选取当前节点之前的所有同级节点。
self选取当前节点。

我们以 ancestor 轴来做示例:

# 节点轴示例
# 获取所有祖先节点
result_9 = html.xpath('//article/ancestor::*')
print(result_9)
# 获取祖先节点 main 节点
result_10 = html.xpath('//article/ancestor::main')
print(result_10)

结果如下:

[, , , , , ]
[]

关于节点轴就先介绍到这里,更多的轴的用法可以参考:https://www.w3school.com.cn/xpath/xpath_axes.asp 。


示例代码

本系列的所有代码小编都会放在代码管理仓库 Github 和 Gitee 上,方便大家取用。

示例代码-Github

示例代码-Gitee



推荐阅读
  • 使用正则表达式爬取36Kr网站首页新闻的操作步骤和代码示例
    本文介绍了使用正则表达式来爬取36Kr网站首页所有新闻的操作步骤和代码示例。通过访问网站、查找关键词、编写代码等步骤,可以获取到网站首页的新闻数据。代码示例使用Python编写,并使用正则表达式来提取所需的数据。详细的操作步骤和代码示例可以参考本文内容。 ... [详细]
  • 如何实现织梦DedeCms全站伪静态
    本文介绍了如何通过修改织梦DedeCms源代码来实现全站伪静态,以提高管理和SEO效果。全站伪静态可以避免重复URL的问题,同时通过使用mod_rewrite伪静态模块和.htaccess正则表达式,可以更好地适应搜索引擎的需求。文章还提到了一些相关的技术和工具,如Ubuntu、qt编程、tomcat端口、爬虫、php request根目录等。 ... [详细]
  • 延迟注入工具(python)的SQL脚本
    本文介绍了一个延迟注入工具(python)的SQL脚本,包括使用urllib2、time、socket、threading、requests等模块实现延迟注入的方法。该工具可以通过构造特定的URL来进行注入测试,并通过延迟时间来判断注入是否成功。 ... [详细]
  • SpringMVC接收请求参数的方式总结
    本文总结了在SpringMVC开发中处理控制器参数的各种方式,包括处理使用@RequestParam注解的参数、MultipartFile类型参数和Simple类型参数的RequestParamMethodArgumentResolver,处理@RequestBody注解的参数的RequestResponseBodyMethodProcessor,以及PathVariableMapMethodArgumentResol等子类。 ... [详细]
  • 本文介绍了绕过WAF的XSS检测机制的方法,包括确定payload结构、测试和混淆。同时提出了一种构建XSS payload的方法,该payload与安全机制使用的正则表达式不匹配。通过清理用户输入、转义输出、使用文档对象模型(DOM)接收器和源、实施适当的跨域资源共享(CORS)策略和其他安全策略,可以有效阻止XSS漏洞。但是,WAF或自定义过滤器仍然被广泛使用来增加安全性。本文的方法可以绕过这种安全机制,构建与正则表达式不匹配的XSS payload。 ... [详细]
  • Android实战——jsoup实现网络爬虫,糗事百科项目的起步
    本文介绍了Android实战中使用jsoup实现网络爬虫的方法,以糗事百科项目为例。对于初学者来说,数据源的缺乏是做项目的最大烦恼之一。本文讲述了如何使用网络爬虫获取数据,并以糗事百科作为练手项目。同时,提到了使用jsoup需要结合前端基础知识,以及如果学过JS的话可以更轻松地使用该框架。 ... [详细]
  • 本文介绍了Java后台Jsonp处理方法及其应用场景。首先解释了Jsonp是一个非官方的协议,它允许在服务器端通过Script tags返回至客户端,并通过javascript callback的形式实现跨域访问。然后介绍了JSON系统开发方法,它是一种面向数据结构的分析和设计方法,以活动为中心,将一连串的活动顺序组合成一个完整的工作进程。接着给出了一个客户端示例代码,使用了jQuery的ajax方法请求一个Jsonp数据。 ... [详细]
  • 第8章 使用外部和内部链接
    8.1使用web地址LearnAboutafricanelephants. ... [详细]
  • Linux下部署Symfoy2对app/cache和app/logs目录的权限设置,symfoy2logs
    php教程|php手册xml文件php教程-php手册Linux下部署Symfoy2对appcache和applogs目录的权限设置,symfoy2logs黑色记事本源码,vsco ... [详细]
  • 本文介绍了使用CentOS7.0 U盘刻录工具进行安装的详细步骤,包括使用USBWriter工具刻录ISO文件到USB驱动器、格式化USB磁盘、设置启动顺序等。通过本文的指导,用户可以轻松地使用U盘安装CentOS7.0操作系统。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • 本文介绍了在Linux下安装Perl的步骤,并提供了一个简单的Perl程序示例。同时,还展示了运行该程序的结果。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 成功安装Sabayon Linux在thinkpad X60上的经验分享
    本文分享了作者在国庆期间在thinkpad X60上成功安装Sabayon Linux的经验。通过修改CHOST和执行emerge命令,作者顺利完成了安装过程。Sabayon Linux是一个基于Gentoo Linux的发行版,可以将电脑快速转变为一个功能强大的系统。除了作为一个live DVD使用外,Sabayon Linux还可以被安装在硬盘上,方便用户使用。 ... [详细]
  • Jquery 跨域问题
    为什么80%的码农都做不了架构师?JQuery1.2后getJSON方法支持跨域读取json数据,原理是利用一个叫做jsonp的概念。当然 ... [详细]
author-avatar
手机用户2502870493
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有