学习一时爽,一直学习一直爽 !html
Hello,你们好,我是Connor,一个从无到有的技术小白。上一次咱们说到了 requests
的使用方法。到上节课为止,咱们已经学完了全部的 Python 经常使用的访问库。那么当咱们获取到了访问的内容以后,咱们就应该从网页上提取咱们想要的内容了。因此,今天咱们来说网页内容的经常使用提取工具之一:Xpath
。相比于 BeautifulSoup
而言,Xpath
更加简单易上手。node
Xpath
是一门在 XML 文档中查找信息的语言。XPath 用于在 XML 文档中经过元素和属性进行导航。他是一种路径语言(XML Path Language),用来肯定XML文档中某部分的位置。python
XPath基于XML的树状结构,提供在数据结构树中找寻节点的能力。起初XPath的提出的初衷是将其做为一个通用的、介于XPointer与XSL间的语法模型。可是XPath很快的被开发者采用来看成小型*查询语言被普遍使用。好比说,当你打开一个网页后按 F12
进行元素检查。当你想要复制某个元素的路径的时候,你能够经过右键进行 Copy 操做。你会发现里面有 Copy Xpath
的选项。因而可知 Xpath 使用的普遍程度。数据结构
说了这么多Xpath使用的怎么怎么普遍,怎么怎么好用,咱们仍是来点实在的,看看在 Python 爬虫中到底如何使用 Xpath
来抓取咱们想要的内容吧:工具
在前面的教程中,我几乎从未提过某个库的安装,可是为何在这里我要提出如何安装呢?缘由很简单,Xpath只是 lxml
库中的一个模块,在 Python 不少库中都提供有 Xpath
的功能,可是最基本的仍是 lxml
的这个库。效率最高。因此,你知道了,想要使用 Xpath
那么你就须要安装 lxml
库:post
pip install lxml
复制代码
其实说白了,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)
复制代码
若是咱们想要使用路径查找,那咱们首先须要知道 Xpath 的语法。Xpath 的主要语法有以下:url
表达式 | 描述 |
---|---|
nodename | 选取名为nodename的子节点 |
/ | 从根节点选取 |
// | 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。 |
. | 选取当前节点 |
.. | 选取当前节点的父节点 |
@ | 选取属性 |
In [1]: page.xpath('head')
Out[1]: [<Element head at 0x7f185bfe5b08>]
复制代码
当前的节点位置是在 html,因此直接查询 head
节点能够查询出来,li
是html的孙节点,若是查询 li
将返回空值:spa
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']
复制代码
选取属性支持任意的标签属性,可是要注意若是选取出的节点有多个,须要指定是哪个节点的属性。
经过路径查找到节点之后,就须要从超找到的节点中选取咱们须要的内容了。查找节点也有一些语法,以下:
表达式 | 结果 |
---|---|
nodename[index] | 选取符合要求的第 index 个元素 |
nodename[last()] | 选取最后一个元素 |
nodename[position()< num] | 选取前 num 个元素 |
nodename[@attribute] | 选取带有属性名为 attribute 的元素 |
nodename[@attribute='value'] | 选取带有属性名为 attribute 且 值为 value 的元素 |
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>]
复制代码
当咱们匹配时会出现路径不肯定的状况,这个时候咱们就要涉及到匹配未知节点。匹配未知节点也有对应的语法,以下:
通配符 | 描述 |
---|---|
* | 匹配任何元素节点 |
@* | 匹配任何属性节点 |
匹配任何属性节点:
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>]
复制代码
经过 属性方法能够获取属性内的内容,可是位于节点之间的内容没法获取到,这个时候就能够经过 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]: '总裁的新鲜小妻子'
复制代码
有的时候咱们须要同时查找多个条件,这个时候你能够经过在路径表达式中使用管道符("|"),选取若干个路径:
In [1]: page.xpath('//li[1]/img[2]/@src | //li[1]/a[3]/text()')
Out[1]: ['/kukuku/images/second.png', '总裁的新鲜小妻子']
复制代码
同时选取多个路径并不会生成一个新的列表,只有一个列表,因此你要考虑好如何提取你的返回结果。通常状况下仍是不建议使用多条件来进行查找,由于多种提取结果混在一个列表不利于提取,即使能够提取,但也会增长计算量,下降程序性能。因此,尽可能不要使用这种方法。
Xpath用来用去仍是那么费劲啊,有没有什么别的更简单的方法啊???固然有的,你能够喝着美味的汤就作完你须要作的事情了。敬请期待下期——BeautifulSoup:美味的汤
以上就是全部的 Xpath 有关的内容啦,可能并不比别人讲的细,可是已经足够你作爬虫使用了。其实我也但愿可以讲的更加细致一点,奈何我是一个正则党,我我的不太喜欢使用Xpath,若是你真的想要深刻了解Xpth的话,推荐你到 W3C Xpath教程 >>> 去看看它们是怎么用的。
好了,这就是今天的内容了,我是Connor,一个从无到有的技术小白。不知道你今天又收获了多少呢???咱们下期再见!
学习一时爽,一直学习一直爽 !
Python 爬虫十六式 - 第一式:HTTP协议 >>>
Python 爬虫十六式 - 第二式:urllib 与 urllib3 >>>
Python 爬虫十六式 - 第三式:Requests的用法 >>>
Python 爬虫十六式 - 第五式:BeautifulSoup,美味的汤 >>>
Python 爬虫十六式 - 第六式:JQuery的假兄弟-pyquery >>>
Python 爬虫十六式 - 第七式:正则的艺术 >>>
Python 爬虫十六式 - 第八式:实例解析-全书网 >>>