爬虫框架Scrapy(1)Scrapy基础1

一. Scrapy框架简介

Scrapy是一个使用Python语言(基于Twisted框架)编写的开源网络爬虫框架,目前由 Scrapinghub Ltd 维护。Scrapy 简单易用、灵活易拓展、开发社区活跃,并且是跨平台的。在 Linux、MaxOS 以及 Windows 平台都可以使用。Scrapy 应用程序也使用 Python 进行开发,目前可以支持 Python 2.7 以及 Python 3.4 版本。

Scrapy 功能非常强大,爬取效率高,相关扩展组件多,可配置和可扩展程度非常高,它几乎可以应对所有反爬网站,是目前 Python 使用最广泛的爬虫框架。

1. Scrapy 框架介绍

首先我们看看 Scrapy 框架的架构:

它可以分为如下的几个部分:

模块 作用
Engine 引擎,处理整个系统的数据流处理、触发事务,是整个框架的核心
Item 项目,它定义了爬取结果的数据结构,爬取的数据会被赋值成该 Item 对象
Scheduler 调度器,接受引擎发过来的请求并将其加入列中,在引擎再次请求的时候将请求提供给引擎
Downloader 下载器,下载网页内容,并将网页内容返回给蜘蛛
Spiders 蜘蛛,其内定义了爬取的逻辑和网页解析规则,它主要负责解析响应并生成提取结果和新的请求
Item Pipeline 项目管道,负责处理由蜘蛛从网页中抽取的项目,它的主要任务是清洗、验证和存储数据
Downloader Middlewares 下载器中间件,位于引擎和下载器之间的钩子框架,主要处理引擎与下载器之间的请求及响应
Spide Middlewares 蜘蛛中间件,位于引擎和蜘蛛之间的钩子框架,主要处理蜘蛛输入的响应和输出的结果及新的请求

对于用户来说,Spider 是最核心的组件,Scrapy 爬虫开发是围绕实现 Spider 展开的。

2. 数据处理流程

Scrapy 中的数据流由引擎控制,数据流的过程如下:

  • Engine 首先打开一个网站,找到处理该网站的 Spider,并向该 Spider 请求第一个要爬取的 URL;

  • Engine 从 Spider 中获取到第一个要爬取的 URL,并通过 Scheduler 以 Request 的形式调度;

  • Engine 向 Scheduler 请求下一个要爬取的 URL;

  • Scheduler 返回下一个要爬取的 URL 给 Engine,Engine 将 URL 通过 Downloader Middlewares 转发给 Downloader Middlewares 下载;

  • 一旦页面下载完毕,Downloader 生成该页面的 Response,并将其通过 Downloader Middlewares 发送给 Engine;

  • Engine 从下载器中接收到 Response,并将其通过 Spider Middleware 发送给 Spider 处理;

  • Spider 处理 Response,并返回爬取到的 Item 及新的 Request 给 Engine;

  • Engine 将 Spider 返回的 Item给 Item Pipeline,将新 Request 给 Scheduler

  • 重复第 (2) 步到第 (8) 步,直到 Scheduler 中没有更多的 Request,Engine 关闭该网站,爬取结束。

通过多个组件的相互协作、不同组件完成工作的不同、组件对异步处理的支持,Scrap 最大限度地利用了网络带宽,大大提高了数据爬取和处理的效率。

如果把框架中的组件比作人体的各个器官,Request 和 Response 对象便是血液,Item 则是代谢产物。

二. Scrapy 及其依赖库的安装

在任意操作系统下,都可以使用 pip 安装 Scrapy,包括在虚拟机中。下面我们在远程终端进入相应的 env 通过如下命令下载 Scrapy 框架:

(pyspider) pyvip@VIP:~$ pip3 install scrapyLooking in indexes: https://pypi.douban.com/simple...Installing collected packages: scrapySuccessfully installed scrapy-2.4.1

为确认 Scrapy 已安装成功,在 shell 中测试能否执行 Scrapy 这条命令:

(pyspider) pyvip@VIP:~$ scrapyScrapy 2.4.1 - no active projectUsage:  scrapy <command> [options] [args]Available commands:  bench         Run quick benchmark test  commands        fetch         Fetch a URL using the Scrapy downloader  genspider     Generate new spider using pre-defined templates  runspider     Run a self-contained spider (without creating a project)  settings      Get settings values  shell         Interactive scraping console  startproject  Create new project  version       Print Scrapy version  view          Open URL in browser, as seen by Scrapy  [ more ]      More commands available when run from project directoryUse "scrapy <command> -h" to see more info about a command

通过以上检测,说明 Scrapy 安装成功了。如上所示,我们安装的是当前最新版本2.4.1。

除了上述 Scrapy 库,我们还需要安装其依赖的其他几个第三方库,例如 'lxml'、'Twisted'、'pyOpenSSL' 等。这些第三方库的安装方式可以参考 Scrapy 的安装方式。

除了上述的安装方式,我们可以直接在 Pycharm 的设置里面下载。

三. Scrapy 项目开发流程

首先我们来看看爬虫框架 Scrapy 的常用命令。

1. 常用命令

命令 作用
scrapy startproject <project_name> 在当前目录下创建一个名为<project_name>的项目
scrapy settings [options] 该命令将会输出 Scrapy 默认设定;如果你在项目中运行这个命令将会输出项目的设定值
scrapy runspider <spider_file.py> 在未创建项目的情况下,运行一个编写在 python 文件中的 spider
scrapy shell [url] 以给定的URL(如果给出)或者空(没有给出URL)启动 Scrapy shell
scrapy fetch <url> 使用 Scrapy 下载器 (downloader) 下载给定的URL,并将获取到的内容送到标准输出
scrapy view <url> 在你的默认浏览器中打开给定的 URL,并以Scrapy spider 获取到的形式展现
scrapy version [-v] 输出Scrapy版本
scrapy –help 查看帮助信息
scrapy bench scrapy 基准测试,用于检测 scrapy 安装环境是否完整
scrapy crawl <spider_name> 使用你项目中的 spider 进行爬取,即启动你的项目
crapy check [-l] <spider> 运行 contract 检查,检查你项目中的错误之处
scrapy list 列出当前项目中所有可用的 spider,每行输出一个 spider
scrapy genspider [-t template] <name> <domain> 在当前项目中创建 spider

2. 创建 Scrapy 项目

在安装完成 Scrapy框架之后,我们开始创建第一个 Scrapy 项目,通过这个示例,我们了解一下 Scrapy 框架的开发流程。

创建 Scrapy 框架的过程与 Django 框架中创建项目文件有些相似。初步流程如下:

  • Step1:创建虚拟环境,并创建项目工程文件

  • Step2:安装 Scrapy 框架

  • Step3:在本地文件夹中创建相应的工程文件,然后在 Pycharm 中连接远程工程文件

然后从Ubuntu 或者 Pycharm 中进入到终端,然后在对应的虚拟环境下进入到爬虫项目工程文件夹,然后运行下面的命令:

(pyspider) pyvip@VIP:~/project/Python_Spider/Spider_Project/Quote_Spider$ scrapy startproject tutorialNew Scrapy project 'tutorial', using template directory '/home/pyvip/.virtualenvs/pyspider/lib/python3.6/site-packages/scrapy/templates/project', created in:    /home/pyvip/project/Python_Spider/Spider_Project/Quote_Spider/tutorialYou can start your first spider with:    cd tutorial    scrapy genspider example example.com

创建好一个名为 first_scrapy 的项目后,可使用tree命令查看项目目录下的文件,显示如下:

tutorial├── tutorial│   ├── __init__.py│   ├── items.py│   ├── middlewares.py│   ├── pipelines.py│   ├── settings.py│   └── spiders│       └── __init__.py└── scrapy.cfg

这里各个文件的功能描述如下:

  • scrapy.cfg:它是 Scrapy 项目的配置文件,其内定义了项目的配置文件路径、部署相关信息等内容;

  • items.py:它定义 Item 数据结构,所有的 Item 的定义都可以放这里;

  • pipelines.py:它定义 Item Pipeline 的实现,所有的 Item Pipeline 的实现都可以放这里;

  • settings.py:它定义项目的全局配置;

  • middlewares.py:它定义 Spider Middlewares 和 Downloader Middlewares 的实现

  • spiders:其内包含一个个 Spider 的实现,每个 Spider 都有一个文件。

3. 创建 Spider

Spider 是需要自己定义的类, Scrapy 用它来从网页里抓取内容,并解析抓取的结果。不过这个类必须继承 Scrapy 提供的 Spider 类 scrapy.Spider,还要定义 Spider 的名称和起始请求,以及怎样处理爬取的结果的方法。spider 模块我们可以使用命令行来创建,例如我们要生成 Quotes 这个 Spider,可以执行如下命令:

(pyspider) pyvip@VIP:~/project/Python_Spider/Spider_Project/Quote_Spider$ cd tutorial/tutorial(pyspider) pyvip@VIP:~/project/Python_Spider/Spider_Project/Quote_Spider/tutorial/tutorial$ ls__init__.py  items.py  middlewares.py  pipelines.py  __pycache__  settings.py  spiders(pyspider) pyvip@VIP:~/project/Python_Spider/Spider_Project/Quote_Spider/tutorial/tutorial$ scrapy genspider quotes quotes.toscrape.comCreated spider 'quotes' using template 'basic' in module:  tutorial.spiders.quotes

执行完毕之后,spiders 文件夹中多了一个 quotes.py,它就是刚刚创建的 Spider,内容如下所示:

import scrapyclass QuotesSpider(scrapy.Spider):    name = 'quotes'    allowed_domains = ['quotes.toscrape.com']    start_urls = ['http://quotes.toscrape.com/']    def parse(self, response):        pass

这里有三个属性——'name'、'allowed_domains'、' start_urls' ,还有一个方法 parse

  • name:它是每个项目唯一的名字,用来区分不同的 Spider;

  • allowed domains:它是允许爬取的域名,如果初始或后续的请求链接不是这个域名下的,则请求链接会被过滤掉;

  • start_urls:它包含了 Spider 在启动时爬取的 url 列表,初始请求是由它来定义的,即 start_urls 属性用来设置一个爬虫的起始爬取点;

  • parse:它是 Spider 的一个方法。默认情况下,被调用时 start_urls 里面的链接构成的请求完成下载执行后,返回的响应就会作为唯一的参数传递给这个函数。该方法负责解析返回的响应、提取数据或者进一步生成要处理的请求。

4. 创建 Item

Item 是保存爬取数据的容器,它的使用方法和字典类似。不过,相比字典 Item 多了额外的保护机制,可以避免拼写错误或者定义字段错误。

创建 Item 需要继承 scrapy.Item 类,并且定义类型为 scrapy.Field 的字段。观察目标网站,我们可以获取到的内容有 'text'、'author'、'tags' 。定义 Item ,将 items.py 的内容修改如下:

import scrapyclass FirstScrapyItem(scrapy.Item):    text = scrapy . Field()     author = scrapy. Field()     tags = scrapy . Field()

5. 解析 Response

parse () 方法的参数 resposne 是 start_urls 里面的链接爬取后的结果,所以在 parse() 方法中,我们可以直接对 response 变量包含的内容进行解析,比如浏览请求结果的网页源代码,或者进一步分析源代码内容,或者找出结果中的链接而得到下一个请求。

在这里,我们使用 CSS 选择器进行选择,parse() 方法的改写内容如下:

def parse(self, response):    quotes = response.css('.quote')    for quote in quotes:        text = quote.css('.text::text').extract_first()        author = quote.css('.author::text').extract_first()        tags = quote.css('.tags .tag::text').extract()

6. 使用 Item

Item 可以理解为字典,不过在声明的时候需要实例化,然后依次用刚才解析的结果赋值 Item 的每一个字段, 最后将 Item 返回即可。QuotesSpider 的改写如下所示:

import scrapyfrom ..items import TutorialItemclass QuotesSpider(scrapy.Spider):    name = 'quotes'    allowed_domains = ['quotes.toscrape.com']    start_urls = ['http://quotes.toscrape.com/']    def parse(self, response):        quotes = response.css('.quote')        for quote in quotes:            item = TutorialItem()            item['text'] = quote.css('.text::text').extract_first()            item['author'] = quote.css('.author::text').extract_first()            item['tags'] = quote.css('.tags .tag::text').extract()            yield item

如此一来,首页的所有内容被解析出来,并被赋值成了一个个 QuoteItem

7. 后续 Request

上面的操作实现了从初始页面抓取内容。那么,下一页的内容该如何抓取?这就需要我们从当前页面中找到信息来生成下一个请求,然后在下一个请求的页面里找到信息再构造再下一个请求。这样循环往复迭代,从而实现整站的爬取。

由于 parse() 就是解析 'text'、'author'、'tags' 的方法,而下一页的结构和刚才已经解析的页面结构是一样的,所以我们可以再次使用 parse() 方法来做页面解析。接下来我们要做的就是利用选择器得到下一页链接并生成请求,在 parse() 方法后追加如下的代码:

import scrapyfrom ..items import TutorialItemclass QuotesSpider(scrapy.Spider):    name = 'quotes'    allowed_domains = ['quotes.toscrape.com']    start_urls = ['http://quotes.toscrape.com/']    def parse(self, response):        quotes = response.css('.quote')        for quote in quotes:            item = TutorialItem()            item['text'] = quote.css('.text::text').extract_first()            item['author'] = quote.css('.author::text').extract_first()            item['tags'] = quote.css('.tags .tag::text').extract()            yield item        next = response.css('.pager .next a::attr(href)').extract_first()        url = response.urljoin(next)        yield scrapy.Request(url=url, callback=self.parse)

在上述代码中,有四个关键步骤是爬虫的关键:

  • 01 继承scrapy.Spider;

  • 02 为Spider取名;

  • 03 设定起始爬取点;

  • 04 实现页面解析函数。

(1)继承 Scrapy.spider

Scrapy 框架提供了一个 Spider 基类,我们编写的 Spider 需要继承它:

import scrapyclass QuotesSpider(scrapy.Spider):

这个 Spider 基类实现了以下内容:

  • 供 Scrapy 引擎调用的接口,例如用来创建 Spider 实例的类方法 from_crawler;

  • 供用户使用的实用工具函数,例如可以调用 log 方法将调试信息输出到日志;

  • 供用户访问的属性,例如可以通过 settings 属性访问配置文件中的配置。

(2)为 Spider 命名

在一个 Scrapy 项目中可以实现多个 Spider,每个 Spider 需要有一个能够区分彼此的唯一标识,Spider 的类属性 name 便是这个唯一标识。例如,上述示例项目中的 Spider 名称是 quotes。执行 scrapy crawl XXX 命令时就用到了这个标识,告诉 Scrapy 使用哪个 Spider 进行爬取。

(3)设定起始爬取点

Spider 必然要从某个或某些页面开始爬取,我们称这些页面为起始爬取点,可以通过类属性 start_urls 来设定起始爬取点。start_urls 通常被实现成一个列表,其中放入所有起始爬取点的 url。看到这里,大家可能会产生疑问:我们仅定义了url列表,是谁暗中构造并提交了相应的Request对象呢?通过阅读 Spider 基类的源码可以找到答案,相关代码如下:

class Spider(object_ref):...def start_requests(self):for url in self.start_urls:yield self.make_requests_from_url(url)def make_requests_from_url(self, url):    return Request(url, dont_filter=True)         def parse(self, response):     raise NotImplementedError     ...

从代码中可以看出,Spider 基类的 start_requests 方法帮助我们构造并提交了 Request 对象,对其中的原理做如下解释:

  • 实际上,对于起始爬取点的下载请求是由 Scrapy 引擎调用 Spider 对象的 start_requests 方法提交的,由于 BooksSpider 类没有实现start_requests 方法,因此引擎会调用 Spider 基类的 start_requests 方法;

  • 在start_requests 方法中,self.start_urls 便是我们定义的起始爬取点列表(通过实例访问类属性),对其进行迭代,用迭代出的每个 url 作为参数调用 make_requests_from_url 方法;

  • 在 make_requests_from_url 方法中,我们找到了真正构造 Reqeust 对象的代码,仅使用 url 和 dont_filter 参数构造 Request 对象;

  • 由于构造 Request 对象时并没有传递 callback 参数来指定页面解析函数,因此默认将 parse 方法作为页面解析函数。此时 BooksSpider 必须实现 parse 方法,否则就会调用 Spider 基类的 parse 方法,从而抛出 NotImplementedError 异常(可以看作基类定义了一个抽象接口);

  • 起始爬取点可能有多个,start_requests 方法需要返回一个可迭代对象(列表、生成器等),其中每一个元素是一个 Request 对象。这里,start_requests 方法被实现成一个生成器函数(生成器对象是可迭代的),每次由 yield 语句返回一个 Request 对象。

由于起始爬取点的下载请求是由引擎调用 Spider 对象的 start_requests 方法产生的,因此我们也可以在 BooksSpider 中实现 start_requests 方法(覆盖基类 Spider 的 start_requests 方法),直接构造并提交起始爬取点的 Request 对象。在某些场景下使用这种方式更加灵活,例如有时想为 Request 添加特定的 HTTP 请求头部,或想为 Request 指定特定的页面解析函数。

以下是通过实现 start_requests 方法定义起始爬取点的示例代码(改写QuotesSpider):

import scrapyfrom ..items import TutorialItemclass QuotesSpider(scrapy.Spider):    name = 'quotes'    allowed_domains = ['quotes.toscrape.com']    def start_requests(self):        yield scrapy.Request('http://quotes.toscrape.com/',                             callback=self.parse_quote,                             headers={'User-Agent': 'Mozilla/5.0'},                             dont_filter=True)    def parse_quote(self, response):        quotes = response.css('.quote')        for quote in quotes:            item = TutorialItem()            item['text'] = quote.css('.text::text').extract_first()            item['author'] = quote.css('.author::text').extract_first()            item['tags'] = quote.css('.tags .tag::text').extract()            yield item        next = response.css('.pager .next a::attr(href)').extract_first()        url = response.urljoin(next)        yield scrapy.Request(url=url, callback=self.parse)

到此,我们介绍完了为爬虫设定起始爬取点的两种方式: 一、定义 start_urls 属性;二、实现 start_requests 方法。

(4)实现页面解析函数

页面解析函数也就是构造 Request 对象时通过 callback 参数指定的回调函数(或默认的 parse 方法)。页面解析函数是实现 Spider 中最核心的部分,它需要完成以下两项工作:

  • 使用选择器提取页面中的数据,将数据封装后(Item 或字典)提交给 Scrapy 引擎;

  • 使用选择器或 LinkExtractor 提取页面中的链接,用其构造 新的 Request 对象并提交给 Scrapy 引擎(下载链接页面)。

一个页面中可能包含多项数据以及多个链接,因此页面解析函数被要求返回一个可迭代对象(通常被实现成一个生成器函数),每次迭代返回一项数据(Item或字典)或一个 Request 对象。

8. 运行

接下来,进入目录,运行如下命令:

scrapy crawl quotes

Scrapy 运行结果如下所示:

(pyspider) pyvip@VIP:~/project/Python_Spider/Spider_Project/Quote_Spider$ cd tutorial(pyspider) pyvip@VIP:~/project/Python_Spider/Spider_Project/Quote_Spider/tutorial$ lsscrapy.cfg  tutorial(pyspider) pyvip@VIP:~/project/Python_Spider/Spider_Project/Quote_Spider/tutorial$ scrapy crawl quotes2021-03-15 11:51:18 [scrapy.utils.log] INFO: Scrapy 2.4.1 started (bot: tutorial)2021-03-15 11:51:18 [scrapy.utils.log] INFO: Versions: lxml 4.5.2.0, libxml2 2.9.10, cssselect 1.1.0, parsel 1.6.0, w3lib 1.22.0, Twisted 21.2.0, Python 3.6.9 (default, Jul 17 2020, 12:50:27) - [GCC 8.4.0], pyOpenSSL 20.0.1 (OpenSSL 1.1.1j  16 Feb 2021), cryptography 3.4.6, Platform Linux-4.15.0-136-generic-x86_64-with-Ubuntu-18.04-bionic2021-03-15 11:51:18 [scrapy.utils.log] DEBUG: Using reactor: twisted.internet.epollreactor.EPollReactor2021-03-15 11:51:18 [scrapy.crawler] INFO: Overridden settings:{'BOT_NAME': 'tutorial', 'NEWSPIDER_MODULE': 'tutorial.spiders', 'ROBOTSTXT_OBEY': True, 'SPIDER_MODULES': ['tutorial.spiders']}2021-03-15 11:51:18 [scrapy.extensions.telnet] INFO: Telnet Password: fdef5e4b01ff9fce2021-03-15 11:51:18 [scrapy.middleware] INFO: Enabled extensions:['scrapy.extensions.corestats.CoreStats', 'scrapy.extensions.telnet.TelnetConsole', 'scrapy.extensions.memusage.MemoryUsage', 'scrapy.extensions.logstats.LogStats']2021-03-15 11:51:18 [scrapy.middleware] INFO: Enabled downloader middlewares:['scrapy.downloadermiddlewares.robotstxt.RobotsTxtMiddleware', 'scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware', 'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware', 'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware', 'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware', 'scrapy.downloadermiddlewares.retry.RetryMiddleware', 'scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware', 'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware', 'scrapy.downloadermiddlewares.redirect.RedirectMiddleware', 'scrapy.downloadermiddlewares.cookies.CookiesMiddleware', 'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware', 'scrapy.downloadermiddlewares.stats.DownloaderStats']2021-03-15 11:51:29 [scrapy.dupefilters] DEBUG: Filtered duplicate request: <GET http://quotes.toscrape.com/page/10/> - no more duplicates will be shown (see DUPEFILTER_DEBUG to show all duplicates)2021-03-15 11:51:29 [scrapy.core.engine] INFO: Closing spider (finished)2021-03-15 11:51:29 [scrapy.statscollectors] INFO: Dumping Scrapy stats:{'downloader/request_bytes': 2881, 'downloader/request_count': 11, 'downloader/request_method_count/GET': 11, 'downloader/response_bytes': 23388, 'downloader/response_count': 11, 'downloader/response_status_count/200': 10, 'downloader/response_status_count/404': 1, 'dupefilter/filtered': 1, 'elapsed_time_seconds': 10.21772, 'finish_reason': 'finished', 'finish_time': datetime.datetime(2021, 3, 15, 3, 51, 29, 96046), 'item_scraped_count': 100, 'log_count/DEBUG': 112, 'log_count/INFO': 10, 'memusage/max': 56266752, 'memusage/startup': 56266752, 'request_depth_max': 10, 'response_received_count': 11, 'robotstxt/request_count': 1, 'robotstxt/response_count': 1, 'robotstxt/response_status_count/404': 1, 'scheduler/dequeued': 10, 'scheduler/dequeued/memory': 10, 'scheduler/enqueued': 10, 'scheduler/enqueued/memory': 10, 'start_time': datetime.datetime(2021, 3, 15, 3, 51, 18, 878326)}2021-03-15 11:51:29 [scrapy.core.engine] INFO: Spider closed (finished)

这里只是部分运行结果 ,中间一些抓取结果已省略。

首先,Scrapy 输出了当前的版本号以及正在启动的项目名称。接着输出了当前 settings.py 中一些重写后的配置。然后输出了当前所应用的 Middlewares 和 Pipelines 。Middlewares 默认是启用的 ,可以在 settings.py 中修改。Pipelines 默认是空 ,同样也可以在 settings py 中配置。

接下来就是输出各个页面的抓取结果了,可以看到爬虫一边解析,一边翻页,直至将所有内容抓取完毕,然后终止。

最后, Scrapy 输出了整个抓取过程的统计信息,如请求的字节数、请求次数、响应次数、完成原因等。

9. 保存到文件

运行完 Scrapy 后,我们只在控制台看到了输出结果,那如何保存输出结果呢?要完成这个任务其实不需要任何额外的代码,Scrapy 提供的 Feed Exports 可以轻松将抓取结果输出。例如,我们想将上面的结果保存成 JSON 文件,可以执行如下命令:

scrapy crawl quotes -o quotes.json

命令运行后,项目内多了一个 quotes.json 文件,文件包含了刚才抓取的所有内容,内容是 JSON 格式。如下图所示:

另外我们还可以每一个 Item 输出一行 JSON ,输出后缀为 jl,为 jsonline 的缩写,命令如下所示:

scrapy crawl quotes -o quotes.jl# 或者scrapy crawl quotes -o quotes.jsonlines

输出格式还支持很多种,例如:'csv'、'xml'、'pickle'、'marshal' 等,还支持 'ftp'、's3' 等远程输出,另外还可以通过自定义 ItemExporter来实现其他的输出。

通过 Scrapy 提供的 Feed Exports,我们可以轻松地输出抓取结果到文件。对于一些小型项目来说,这应该足够了。如果想要更复杂的输出,如输出到数据库等,我们可以使用 Item Pileline 来完成。

四. 实例——爬取书籍信息

1. 创建项目

在本地和远程服务器的相应文件夹中创建爬虫项目的文件夹,然后在 Pycharm 中打开本地文件夹,连接远程文件。

从Ubuntu 或者 Pycharm 中进入终端,然后在对应的虚拟环境下进入到爬虫项目工程文件夹,再运行下面的命令:

(pyspider) pyvip@VIP:~/project/Python_Spider/Spider_Project/Scrapy_Book$ scrapy startproject toscrapyNew Scrapy project 'toscrapy', using template directory '/home/pyvip/.virtualenvs/pyspider/lib/python3.6/site-packages/scrapy/templates/project', created in:    /home/pyvip/project/Python_Spider/Spider_Project/Scrapy_Book/toscrapyYou can start your first spider with:    cd toscrapy    scrapy genspider example example.com

2. 创建爬虫

从终端进入项目工程文件,运行如下命令:

(pyspider) pyvip@VIP:~/project/Python_Spider/Spider_Project/Scrapy_Book/toscrapy$ cd toscrapy(pyspider) pyvip@VIP:~/project/Python_Spider/Spider_Project/Scrapy_Book/toscrapy/toscrapy$ ls__init__.py  items.py  middlewares.py  pipelines.py  settings.py  spiders(pyspider) pyvip@VIP:~/project/Python_Spider/Spider_Project/Scrapy_Book/toscrapy/toscrapy$ scrapy genspider books books.toscrape.comCreated spider 'books' using template 'basic' in module:  toscrapy.spiders.books

3. 解析 Response

books.py 文件中修改 parse 函数,修改内容如下:

import scrapyclass BooksSpider(scrapy.Spider):    name = 'books'    allowed_domains = ['books.toscrape.com']    start_urls = ['http://books.toscrape.com/']    def parse(self, response):        # 提取数据        for book in response.css('article.product_pod'):            name = book.xpath('./h3/a/@title').extract_first()            price = book.css('p.price_color::text').extract_first()            yield {'name': name,                'price': price,            }        # 提取链接        next_url = response.css('ul.pager li.next a::attr(href)').extract_first()        if next_url:            next_url = response.urljoin(next_url)            yield scrapy.Request(next_url, callback=self.parse)

4. 运行爬虫并保存数据

从终端进入项目工程文件,运行如下命令:

(pyspider) pyvip@VIP:~/project/Python_Spider/Spider_Project/Scrapy_Book/toscrapy/toscrapy$ scrapy crawl books2021-03-15 18:09:09 [scrapy.utils.log] INFO: Scrapy 2.4.1 started (bot: toscrapy)2021-03-15 18:09:09 [scrapy.utils.log] INFO: Versions: lxml 4.5.2.0, libxml2 2.9.10, cssselect 1.1.0, parsel 1.6.0, w3lib 1.22.0, Twisted 21.2.0, Python 3.6.9 (default, Jul 17 2020, 12:50:27) - [GCC 8.4.0], pyOpenSSL 20.0.1 (OpenSSL 1.1.1j  16 Feb 2021), cryptography 3.4.6, Platform Linux-4.15.0-136-generic-x86_64-with-Ubuntu-18.04-bionic2021-03-15 18:09:09 [scrapy.utils.log] DEBUG: Using reactor: twisted.internet.epollreactor.EPollReactor2021-03-15 18:09:09 [scrapy.crawler] INFO: Overridden settings:{'BOT_NAME': 'toscrapy', 'NEWSPIDER_MODULE': 'toscrapy.spiders', 'ROBOTSTXT_OBEY': True, 'SPIDER_MODULES': ['toscrapy.spiders']}2021-03-15 18:09:09 [scrapy.extensions.telnet] INFO: Telnet Password: ee928a9f1bd414d42021-03-15 18:09:09 [scrapy.middleware] INFO: Enabled extensions:['scrapy.extensions.corestats.CoreStats', 'scrapy.extensions.telnet.TelnetConsole', 'scrapy.extensions.memusage.MemoryUsage', 'scrapy.extensions.logstats.LogStats']2021-03-15 18:09:09 [scrapy.middleware] INFO: Enabled downloader middlewares:['scrapy.downloadermiddlewares.robotstxt.RobotsTxtMiddleware', 'scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware', 'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware', 'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware', 'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware', 'scrapy.downloadermiddlewares.retry.RetryMiddleware', 'scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware', 'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware', 'scrapy.downloadermiddlewares.redirect.RedirectMiddleware', 'scrapy.downloadermiddlewares.cookies.CookiesMiddleware', 'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware', 'scrapy.downloadermiddlewares.stats.DownloaderStats']............2021-03-15 18:11:54 [scrapy.core.scraper] DEBUG: Scraped from <200 http://books.toscrape.com/catalogue/page-50.html>{'name': "A Spy's Devotion (The Regency Spies of London #1)", 'price': '£16.97'}2021-03-15 18:11:54 [scrapy.core.scraper] DEBUG: Scraped from <200 http://books.toscrape.com/catalogue/page-50.html>{'name': "1st to Die (Women's Murder Club #1)", 'price': '£53.98'}2021-03-15 18:11:54 [scrapy.core.scraper] DEBUG: Scraped from <200 http://books.toscrape.com/catalogue/page-50.html>{'name': '1,000 Places to See Before You Die', 'price': '£26.08'}2021-03-15 18:11:54 [scrapy.core.engine] INFO: Closing spider (finished)2021-03-15 18:11:54 [scrapy.statscollectors] INFO: Dumping Scrapy stats:{'downloader/exception_count': 3, 'downloader/exception_type_count/twisted.internet.error.DNSLookupError': 3, 'downloader/request_bytes': 15515, 'downloader/request_count': 53, 'downloader/request_method_count/GET': 53, 'downloader/response_bytes': 291473, 'downloader/response_count': 50, 'downloader/response_status_count/200': 50, 'elapsed_time_seconds': 164.723678, 'finish_reason': 'finished', 'finish_time': datetime.datetime(2021, 3, 15, 10, 11, 54, 716833), 'item_scraped_count': 1000, 'log_count/DEBUG': 1052, 'log_count/ERROR': 2, 'log_count/INFO': 12, 'memusage/max': 62898176, 'memusage/startup': 56143872, 'request_depth_max': 49, 'response_received_count': 50, 'retry/count': 2, 'retry/max_reached': 1, 'retry/reason_count/twisted.internet.error.DNSLookupError': 2, "robotstxt/exception_count/<class 'twisted.internet.error.DNSLookupError'>": 1, 'robotstxt/request_count': 1, 'scheduler/dequeued': 50, 'scheduler/dequeued/memory': 50, 'scheduler/enqueued': 50, 'scheduler/enqueued/memory': 50, 'start_time': datetime.datetime(2021, 3, 15, 10, 9, 9, 993155)}2021-03-15 18:11:54 [scrapy.core.engine] INFO: Spider closed (finished)

如果要将上述爬取的数据保存到文件,则需要运行如下命令:

scrapy crawl books -o books.csv

然后在项目工程文件夹下生成文件 books.csv ,在终端查看该文件内容如下:

(pyspider) pyvip@VIP:~/project/Python_Spider/Spider_Project/Scrapy_Book/toscrapy/toscrapy$ sed -n '2,$p' books.csv | cat -n 1 A Light in the Attic,£51.77  2 Tipping the Velvet,£53.74  3 Soumission,£50.10  4 Sharp Objects,£47.82  5 Sapiens: A Brief History of Humankind,£54.23  6 The Requiem Red,£22.65      7  The Dirty Little Secrets of Getting Your Dream Job,£33.34     8  "The Coming Woman: A Novel Based on the Life of the Infamous Feminist, Victoria Woodhull",£17.93     9  The Boys in the Boat: Nine Americans and Their Epic Quest for Gold at the 1936 Berlin Olympics,£22.60    10  The Black Maria,£52.15......

上述文章内容如有错误,欢迎各位朋友在评论区留言!

(0)

相关推荐

  • 万字长文带你入门Scrapy - Scrapy简明教程

    本文通过示例简要介绍一下使用Scrapy抓取网站内容的基本方法和流程. 继续阅读之前请确保已安装了scrapy. 基本安装方法为:pip install scrapy 我们已经在之前的文章中初步介绍了 ...

  • scrapy终端常用命令

    scrapy命令行 一.默认的scrapy项目结构 scrapy.cfgmyproject/    __init__.py    items.py    pipelines.py    setting ...

  • 以『B站』为实战案例!手把手教你掌握爬虫必备框架『Scrapy』

    以『B站』为实战案例!手把手教你掌握爬虫必备框架『Scrapy』

  • scrapy实践之翻页爬取

    在scrapy框架中,spider具有以下几个功能 1. 定义初始爬取的url 2. 定义爬取的行为,是否跟进链接 3. 从网页中提取结构化数据 所谓的跟进链接,其实就是自动爬取该页的所有链接,然后顺 ...

  • 初识scrapy

    Scrapy是一个用于爬取web站点并提取结构化数据的应用框架,通常我们称之为爬虫,一款优秀的python爬虫. scrapy爬取的数据可被用在数据挖掘.信息处理.历史数据归档等非常广泛的数据分析和处 ...

  • 【实战视频】使用scrapy写爬虫-爬知乎live

    我其实很喜欢造轮子,一直没用过爬虫框架写爬虫.虽然知道爬虫很简单,scrapy框架也不难,但是在舒适区呆久了,真的不想学新东西,用新知识写爬虫. 今天我不止用新框架scrapy写爬虫,而且我还要使用s ...

  • 【视频讲解】在scrapy框架中如何使用selenium?

    如何在scrapy中使用selenium 上一个文章已经分享了scrapy的settings.py.spider爬虫(spider文件夹中的爬虫).items.py.pipelines.py,但没有讲 ...

  • 干货!一文教会你 Scrapy 爬虫框架的基本使用

    原创 投稿君 Python数据之道 收录于话题 #读者投稿 28 #Python干货分享 2 #Python 11 #项目实战 20 出品:Python数据之道 (ID:PyDataLab) 作者:叶 ...

  • 第70天: Python Scrapy 爬虫框架及搭建

    Scrapy 框架实现爬虫的基本原理 Scrapy 就是封装好的框架,你可以专心编写爬虫的核心逻辑,无需自己编写与爬虫逻辑无关的代码,套用这个框架就可以实现以上功能--爬取到想要的数据.如果暂时理解不 ...

  • 初识scrapy爬虫框架

    框架是为了解决特定的业务场景而开发的一套高质量代码,通过框架避免了重复造轮子的低效模式,可以更加专注于具体业务相关的代码.在python中,scrapy就是一个主流的爬虫框架,可以通过如下方式进行安装 ...

  • 介绍一款能取代 Scrapy 的爬虫框架 - feapder

    介绍一款能取代 Scrapy 的爬虫框架 - feapder

  • python爬虫实战:利用scrapy,短短50行代码下载整站短视频

    近日,有朋友向我求助一件小事儿,他在一个短视频app上看到一个好玩儿的段子,想下载下来,可死活找不到下载的方法.这忙我得帮,少不得就抓包分析了一下这个app,找到了视频的下载链接,帮他解决了这个小问题 ...

  • Python爬虫框架有哪些?这几种最常见!

    Python之所以被称为"爬虫"的首选语言,主要原因是因为Python拥有很多爬虫框架,不仅功能齐全.优点多,而且可以帮助程序员以更少的代码实现更多的功能,让工作变得更加轻松便利. ...

  • 7款好用的Python爬虫框架!

    Python是网络爬虫的首选语言,在爬虫领域有着独特的优势和用途,而且Python还拥有很多爬虫框架,那么你知道哪个Python爬虫框架最高效吗?这几个你一定要知道. 1.Scrapy Scrapy是 ...

  • python接口自动化28-requests-html爬虫框架

    前言 requests库的好,只有用过的人才知道,最近这个库的作者又出了一个好用的爬虫框架requests-html.之前解析html页面用过了lxml和bs4, requests-html集成了一些 ...

  • 易车网实战 【保姆级】:Feapder爬虫框架入门教程

    大家好,我是辰哥! 今天辰哥带大家来看看一个爬虫框架:Feapder,看完本文之后,别再说你不会Feapder了.本文辰哥将带你了解什么是Feapder?.如何去创建一个Feapder入门项目(实战: ...