内容简介:学习一时爽,一直学习一直爽 !Hello,大家好,我是Connor,一个从无到有的技术小白。上一次我们说到了
学习一时爽,一直学习一直爽 !
Hello,大家好,我是Connor,一个从无到有的技术小白。上一次我们说到了 requests
的使用方法。到上节课为止,我们已经学完了所有的 Python 常用的访问库。那么当我们获取到了访问的内容之后,我们就应该从网页上提取我们想要的内容了。所以,今天我们来讲网页内容的常用提取 工具 之一: Xpath
。相比于 BeautifulSoup
而言, Xpath
更加简单易上手。
1.Xpath简介
Xpath
是一门在 XML 文档中查找信息的语言。XPath 用于在 XML 文档中通过元素和属性进行导航。他是一种路径语言(XML Path Language),用来确定XML文档中某部分的位置。
XPath基于XML的树状结构,提供在数据结构树中找寻节点的能力。起初XPath的提出的初衷是将其作为一个通用的、介于 XPointer 与 XSL 间的语法模型。但是XPath很快的被开发者采用来当作小型* 查询语言 被广泛使用。比如说,当你打开一个网页后按 F12
进行元素检查。当你想要复制某个元素的路径的时候,你可以通过右键进行 Copy 操作。你会发现里面有 Copy Xpath
的选项。由此可见 Xpath 使用的广泛程度。
说了这么多Xpath使用的怎么怎么广泛,怎么怎么好用,我们还是来点实在的,看看在 Python 爬虫中到底如何使用 Xpath
来抓取我们想要的内容吧:
2. Xpath的安装
在前面的教程中,我几乎从未提过某个库的安装,但是为什么在这里我要提出如何安装呢?原因很简单,Xpath只是 lxml
库中的一个模块,在 Python 很多库中都提供有 Xpath
的功能,但是最基本的还是 lxml
的这个库。效率最高。所以,你知道了,想要使用 Xpath
那么你就需要安装 lxml
库:
pip install lxml 复制代码
3.Xpath的语法
其实说白了, Xpath
就是从 html 中选取节点。节点是通过沿着路径或者通过 step 来选取的。下面,我们将通过如下HTML文档来进行演示:
html_doc =""" <html> <head></head> <body> <li> <a href="/book_16860.html" title="总裁的新鲜小妻"> <img src="/16860s.jpg"> </a> <img src="/kukuku/images/only.png" class="topss png_bg"> <img src="abc.png" class="topss png_bg"> <a href="/book_16860.html">总裁的新鲜小妻子</a> </li> <li> <a href="/book_16861.html" title="斗神天下"> <img src="/16861s.jpg"> </a> <img src="/kukuku/images/only.png" class="topss png_bg"> <img src="def.png" class="topss png_bg"> <a href="/book_16861.html">斗神天下</a> </li> </body> </html>""" 复制代码
首先,大家也都知道我们实际上从网页上获取的都是字符串格式。那么如果我们想要通过 Xpath 来提取我们想要的内容,我们首先要生成 HTML 的 DOM 树:
from lxml import etree page = etree.HTML(html_doc) 复制代码
3.1 路径查找
如果我们想要使用路径查找,那我们首先需要知道 Xpath 的语法。Xpath 的主要语法有如下:
表达式 | 描述 |
---|---|
nodename | 选取名为nodename的子节点 |
/ | 从根节点选取 |
// | 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。 |
. | 选取当前节点 |
.. | 选取当前节点的父节点 |
@ | 选取属性 |
- 查找当前的子节点:
In [1]: page.xpath('head') Out[1]: [<Element head at 0x7f185bfe5b08>] 复制代码
当前的节点位置是在 html,所以直接查询 head
节点可以查询出来, li
是html的孙节点,如果查询 li
将返回空值:
In [2]: page.xpath('li') Out[2]: [] 复制代码
- 从根节点进行查找:
In [3]: page.xpath('/html') Out[3]: [<Element html at 0x11208be88>] 复制代码
从根节点进行查找,根节点下只有一个节点 html
节点,所以从根节点查找只能查找到 html
,如果查找其它内容将返回空列表:
In [4]: page.xpath('/li') Out[4]: [] 复制代码
- 从整个文档所有节点查找:
In [5]: page.xpath('//li') Out[5]: [<Element li at 0x1128c02c8>, <Element li at 0x111c74108>, <Element li at 0x111fd2288>, <Element li at 0x1128da348>] 复制代码
从整个文档进行查找可以查找整个文档中符合条件的节点,包括孙节点及以下。
- 选取当前节点的父节点
In [6]: page.xpath('//li')[0].xpath('..') Out[6]: [<Element body at 0x1128c0ac8>] 复制代码
- 选取属性:
In [7]: page.xpath('//a')[1].xpath('@href') Out[7]: ['/book_16860.html'] 复制代码
选取属性支持任意的标签属性,但是要注意如果选取出的节点有多个,需要指定是哪一个节点的属性。
3.2 节点查找
通过路径查找到节点以后,就需要从超找到的节点中选取我们需要的内容了。查找节点也有一些语法,如下:
表达式 | 结果 |
---|---|
nodename[index] | 选取符合要求的第 index 个元素 |
nodename[last()] | 选取最后一个元素 |
nodename[position()< num] | 选取前 num 个元素 |
nodename[@attribute] | 选取带有属性名为 attribute 的元素 |
nodename[@attribute='value'] | 选取带有属性名为 attribute 且 值为 value 的元素 |
- 选取第一个 img 节点的 src 属性:
In [1]: page.xpath('//li[1]/a[1]/img[1]/@src') Out[1]: ['/16860s.jpg'] 复制代码
**注意: 当你在选取一个节点的属性的时候,有一点需要注意。 通过[index]选取出的节点是每一个符合条件的第[index]个符合条件的元素。 **但是这么说比较抽象,我们举个例子。例如:
In [2]: page.xpath('//li[1]') 选取所有符合 li 节点的第一个节点 Out[2]: [<Element li at 0x7fb517327ac8>] 复制代码
通过上面的例子我们貌似看不出什么,那我们再看下面的这个例子:
In [3]: page.xpath('//li//img[1]') Out[3]: [<Element img at 0x7f0c26328b08>, <Element img at 0x7f0c26328a88>, <Element img at 0x7f0c26328bc8>, <Element img at 0x7f0c26328c08>] 复制代码
你可以看到,我们选取出了4个 img 节点。原因很简单,看下面的代码和解释就能明白了:
<html> <head></head> <body> <li> <a href="/book_16860.html" title="总裁的新鲜小妻"> (一)<img src="/16860s.jpg"> </a> (二)<img src="/kukuku/images/only.png" class="topss png_bg"> (三)<img src="abc.png" class="topss png_bg"> <a href="/book_16860.html">总裁的新鲜小妻子</a> </li> <li> <a href="/book_16861.html" title="斗神天下"> (四)<img src="/16861s.jpg"> </a> (五)<img src="/kukuku/images/only.png" class="topss png_bg"> (六)<img src="def.png" class="topss png_bg"> <a href="/book_16861.html">斗神天下</a> </li> </body> </html> 复制代码
- (一)是第一个
<li>
节点的<a>
节点里的第一个<img>
节点。其路径为<li>/<a>/<img>
- (二)是第一个
<li>
节点的<img>
节点里的第一个<img>
节点。其路径为<li>/<img>
。 - (三)之所以没有被选中,是因为它是
<li>
标签下的第二个<img>
标签 - (四)(五)(六)同理
- 选取第二个元素开始的所有节点:
In [4]: page.xpath('//img[position()>1]') Out[4]: [<Element img at 0x7f78ba63dac8>, <Element img at 0x7f78ba63da48>] 复制代码
- 选取带有指定属性与指定值的节点:
In [5]: page.xpath('//a[@title="斗神天下"]') Out[5]: [<Element a at 0x7fdd0844fa48>] 复制代码
3.3 未知节点
当我们匹配时会出现路径不确定的情况,这个时候我们就要涉及到匹配未知节点。匹配未知节点也有对应的语法,如下:
通配符 | 描述 |
---|---|
* | 匹配任何元素节点 |
@* | 匹配任何属性节点 |
匹配任何属性节点:
In [1]: page.xpath('//li/a/*') Out[1]: [<Element img at 0x7f83af768b08>, <Element img at 0x7f83af768a88>, <Element img at 0x7f83af768bc8>, <Element img at 0x7f83af768c08>] 复制代码
匹配任何元素节点:
In [2]: page.xpath('//li/a[@*]') Out[2]: [<Element a at 0x7ff2dcf69b08>, <Element a at 0x7ff2dcf69a88>, <Element a at 0x7ff2dcf69bc8>, <Element a at 0x7ff2dcf69c08>] 复制代码
3.4 获取节点中的文本
通过 属性方法可以获取属性内的内容,但是位于节点之间的内容无法获取到,这个时候就可以通过 text()
与 string()
方法来获得其中的文本:
通过 text()
获取某个节点中的文本:
In [1]: page.xpath('//li/a[3]/text()') Out[1]: ['总裁的新鲜小妻子', '斗神天下'] 复制代码
可以看到,通过 text()
属性可以很轻松的获取标签之间的文本。
通过 string()
获取某个节点中的文本:
In [1]: page.xpath('string(//li[1]/a[3])') Out[1]: '总裁的新鲜小妻子' 复制代码
3.5 选取多个路径
有的时候我们需要同时查找多个条件,这个时候你可以通过在路径表达式中使用管道符("|"),选取若干个路径:
In [1]: page.xpath('//li[1]/img[2]/@src | //li[1]/a[3]/text()') Out[1]: ['/kukuku/images/second.png', '总裁的新鲜小妻子'] 复制代码
同时选取多个路径并不会生成一个新的列表,只有一个列表,所以你要考虑好如何提取你的返回结果。一般情况下还是不建议使用多条件来进行查找,因为多种提取结果混在一个列表不利于提取,即便可以提取,但也会增加计算量,降低程序性能。所以,尽量不要使用这种方法。
以上就是所有的 Xpath 有关的内容啦,可能并不比别人讲的细,但是已经足够你做爬虫使用了。其实我也希望能够讲的更加细致一点,奈何我是一个正则党,我个人不太喜欢使用Xpath,如果你真的想要深入了解Xpth的话,推荐你到W3C Xpath教程 >>> 去看看它们是怎么用的。
好了,这就是今天的内容了,我是Connor,一个从无到有的技术小白。我们下期再见!
学习一时爽,一直学习一直爽 !
下期预告:Xpath用来用去还是那么费劲啊,有没有什么别的更简单的方法啊???当然有的,你可以喝着美味的汤就做完你需要做的事情了。敬请期待下期——BeautifulSoup:美味的汤
系列文章连接:
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。