我们之前介绍了利用 Beautiful Soup、pyquery 以及正则表达式来提取网页数据,这确实非常方便。而 Scrapy 还提供了自己的数据提取方法,即 Selector(选择器)。Selector 是基于 lxml 来构建的,支持 XPath 选择器、CSS 选择器以及正则表达式,功能全面,解析速度和准确度非常高。
很多人学习python,不知道从何学起。
很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手。
很多已经做案例的人,却不知道如何去学习更加高深的知识。
那么针对这三类人,我给大家提供一个好的学习平台,免费领取视频教程,电子书籍,以及课程的源代码!
QQ群:961562169
本节将介绍 Selector 的用法。
Selector 是一个可以独立使用的模块。我们可以直接利用 Selector 这个类来构建一个选择器对象,然后调用它的相关方法如 xpath()、css() 等来提取数据。
例如,针对一段 HTML 代码,我们可以用如下方式构建 Selector 对象来提取数据:
运行结果:
我们在这里没有在 Scrapy 框架中运行,而是把 Scrapy 中的 Selector 单独拿出来使用了,构建的时候传入 text 参数,就生成了一个 Selector 选择器对象,然后就可以像前面我们所用的 Scrapy 中的解析方式一样,调用 xpath()、css() 等方法来提取了。
在这里我们查找的是源代码中的 title 中的文本,在 XPath 选择器最后加 text() 方法就可以实现文本的提取了。
以上内容就是 Selector 的直接使用方式。同 Beautiful Soup 等库类似,Selector 其实也是强大的网页解析库。如果方便的话,我们也可以在其他项目中直接使用 Selector 来提取数据。
接下来,我们用实例来详细讲解 Selector 的用法。
由于 Selector 主要是与 Scrapy 结合使用,如 Scrapy 的回调函数中的参数 response 直接调用 xpath() 或者 css() 方法来提取数据,所以在这里我们借助 Scrapy shell 来模拟 Scrapy 请求的过程,来讲解相关的提取方法。
我们用官方文档的一个样例页面来做演示:http://doc.scrapy.org/en/latest/_static/selectors-sample1.html。
开启 Scrapy shell,在命令行输入如下命令:
我们就进入到 Scrapy shell 模式。这个过程其实是,Scrapy 发起了一次请求,请求的 URL 就是刚才命令行下输入的 URL,然后把一些可操作的变量传递给我们,如 request、response 等,如图 13-5 所示。
图 13-5 Scrapy Shell
我们可以在命令行模式下输入命令调用对象的一些操作方法,回车之后实时显示结果。这与 Python 的命令行交互模式是类似的。
接下来,演示的实例都将页面的源码作为分析目标,页面源码如下所示:
进入 Scrapy shell 之后,我们将主要操作 response 这个变量来进行解析。因为我们解析的是 HTML 代码,Selector 将自动使用 HTML 语法来分析。
response 有一个属性 selector,我们调用 response.selector 返回的内容就相当于用 response 的 text 构造了一个 Selector 对象。通过这个 Selector 对象我们可以调用解析方法如 xpath()、css() 等,通过向方法传入 XPath 或 CSS 选择器参数就可以实现信息的提取。
我们用一个实例感受一下,如下所示:
打印结果的形式是 Selector 组成的列表,其实它是 SelectorList 类型,SelectorList 和 Selector 都可以继续调用 xpath() 和 css() 等方法来进一步提取数据。
在上面的例子中,我们提取了 a 节点。接下来,我们尝试继续调用 xpath() 方法来提取 a 节点内包含的 img 节点,如下所示:
我们获得了 a 节点里面的所有 img 节点,结果为 5。
值得注意的是,选择器的最前方加 .(点),这代表提取元素内部的数据,如果没有加点,则代表从根节点开始提取。此处我们用了./img 的提取方式,则代表从 a 节点里进行提取。如果此处我们用 //img,则还是从 html 节点里进行提取。
我们刚才使用了 response.selector.xpath() 方法对数据进行了提取。Scrapy 提供了两个实用的快捷方法,response.xpath() 和 response.css(),它们二者的功能完全等同于 response.selector.xpath() 和 response.selector.css()。方便起见,后面我们统一直接调用 response 的 xpath() 和 css() 方法进行选择。
现在我们得到的是 SelectorList 类型的变量,该变量是由 Selector 对象组成的列表。我们可以用索引单独取出其中某个 Selector 元素,如下所示:
我们可以像操作列表一样操作这个 SelectorList。
但是现在获取的内容是 Selector 或者 SelectorList 类型,并不是真正的文本内容。那么具体的内容怎么提取呢?
比如我们现在想提取出 a 节点元素,就可以利用 extract() 方法,如下所示:
这里使用了 extract() 方法,我们就可以把真实需要的内容获取下来。
我们还可以改写 XPath 表达式,来选取节点的内部文本和属性,如下所示:
我们只需要再加一层 /text() 就可以获取节点的内部文本,或者加一层 /@href 就可以获取节点的 href 属性。其中,@符号后面内容就是要获取的属性名称。
现在我们可以用一个规则把所有符合要求的节点都获取下来,返回的类型是列表类型。
但是这里有一个问题:如果符合要求的节点只有一个,那么返回的结果会是什么呢?我们再用一个实例来感受一下,如下所示:
我们用属性限制了匹配的范围,使 XPath 只可以匹配到一个元素。然后用 extract() 方法提取结果,其结果还是一个列表形式,其文本是列表的第一个元素。但很多情况下,我们其实想要的数据就是第一个元素内容,这里我们通过加一个索引来获取,如下所示:python>>> response.xpath('//a[@href="/links.html?l=QUFIaityVFErMTJmNjRzRlNLRGFSa2l3bFlWdnVYbVo%3D"]/text()').extract()[0]
'Name: My image 1 '
这样,我们直接利用 extract_first() 方法将匹配的第一个结果提取出来,同时我们也不用担心数组越界的问题。
另外我们也可以为 extract_first() 方法设置一个默认值参数,这样当 XPath 规则提取不到内容时会直接使用默认值。例如将 XPath 改成一个不存在的规则,重新执行代码,如下所示:
参与评论
手机查看
返回顶部