Scrapy 是一个基于 Python 的网络爬虫,可以用来从网站提取信息。它快速简单,可以像浏览器一样浏览页面。
但是,请注意,它不适合使用JavaScript来操纵用户界面的网站和应用程序。 Scrapy只加载HTML。它没有任何设施能够执行网站可以使用来定制用户体验JavaScript。
安装
我们使用Virtualenv来安装scrapy。这使我们能够安装scrapy而不影响其他系统安装的模块。
现在创建一个工作目录并在该目录中初始化一个虚拟环境。
现在安装Scrapy
检查它正在工作。以下代码显示将scrapy的版本显示为1.4.0。
编写一个Spider
Scrapy的工作原理是加载一个叫做spider的Python模块,它是一个从scrapy.Spider继承而来的类。
让我们来写一个简单的spider类来加载Reddit的顶部帖子。
首先,创建一个名为redditspider.py的文件,并添加以下内容。这是一个完整的spider类,尽管对我们没有任何帮助。一个spider类至少要求如下:
一个name来识别这个spider类
一个start_urls列表变量,包含从哪个URL开始爬行。
一个parse()方法,它可以是无操作的,如图所示
这个类现在可以执行如下:
关闭日志记录
正如你所看到的,这个Spider运行并打印一大堆消息,这对调试很有用。但是,由于它掩盖了out程序的输出,现在让我们关闭它。
将这几行添加到文件的开头:
现在,当我们运行Spider,我们不应该看到令人的混淆信息。
解析响应
现在我们来分析一下scraper的反应。这是在parse()方法中完成的。在此方法中,我们使用response.css()方法在HTML上执行CSS样式选择并提取所需的元素。
为了确定要提取的CSS选择,我们使用Chrome的DOM Inspector工具来选取元素。在reddit的首页,我们看到每个帖子都被包装在<div class =“thing”> ... </ div>中。
因此,我们从页面中选择所有的div.thing,并使用它进一步工作。
我们还在Spider类中实现了下面的辅助方法来提取所需的文本。
以下方法从元素中提取所有文本为列表,用空格连接元素,并从结果中去除前导和后面的空白。
这个方法从第一个元素中提取文本并返回。
提取所需的元素
一旦这些辅助方法到位,让我们从每个Reddit帖子中提取标题。在div.thing内,标题在div.entry> p.title> a.title :: text里是能被利用的。如前所述,可以从任何浏览器的DOM Inspector中确定所需元素的CSS选择。
结果使用python的yield语句返回给调用者。 yield的工作方式如下 - 执行一个包含yield语句的函数将返回一个生成器给调用者。调用者重复执行该生成器,并接收执行结果直到生成器终止。
在我们的例子中,parse()方法在每个调用中返回一个字典对象,其中包含一个键(标题)给调用者,返回直到div.thing列表结束。
运行Spider并收集输出。
现在让我们再次运行Spider。显示了丰富输出的一部分(在重新设置日志语句之后)。
很难看到真正的产出。让我们将输出重定向到一个文件(posts.json)
这里是posts.json的一部分
提取所有必需的信息
我们还要提取每个帖子的subreddit名称和投票数。为此,我们只更新yield语句返回的结果。
生成的posts.json:
总结
本文提供了如何从使用Scrapy的网站中提取信息的基本视图。要使用scrapy,我们需要编写一个Spider模块,来指示scrapy抓取一个网站并从中提取结构化的信息。这些信息可以以JSON格式返回,供下游软件使用。