Scrapy初步认识

Scrapy模块安装

首先,我们需要先搭建好Scrapy的环境

利用conda创建一个名为Scrapy_work的虚拟环境并且进入该环境

1
2
conda create -n "Scrapy_work"
conda activate Scrapy_work

然后使用pip安装Scrapy模块

1
pip install Scrapy

为了确认Scrapy模块已经安装成功,可以在Python当中测试一下能否导入Scrapy模块

1
2
import scrapy
scrapy.version_info

如果正确安装的话,终端会显示Scrapy的版本

编写Scrapy爬虫

Scrapy框架结构及其工作原理

上图为Scrapy框架是组成结构

Scrapy框架中的各个组件的介绍如下所示

组件 描述 类型
ENGINE 引擎,框架的核心,其他所有组件在其控制下协同工作 内部组件
SCHEDULER 调度器,负责对SPIDER提交的下载请求进行调度 内部组件
DOWNLOADER 下载器,负责下载页面(发送HTTP请求和接收HTTP响应) 内部组件
SPIDER 爬虫,负责提取页面中的数据,并产生对新页面的下载请求 用户实现
MIDDLEWARE 中间件,负责对Request对象和Response对象进行处理 可选组件
ITEM PIPELINE 数据管道,负责对爬取到的数据进行处理 可选组件

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

接下来是框架中的数据流

对象
REQUEST Scrapy的HTTP请求对象
RESPONSE Scrapy的HTTP响应对象
ITEM 从页面中爬取的一项数据

数据的流动过程简述如下:

  1. SPIDER要爬取某URL地址的页面时,需要使用该URL构造一个Request对象,提交给ENGINE
  2. Request对象随后进入SCHEDULER按某种算法进行排队,之后的某个时刻SCHEDULER将其出队,送往DOWNLOADER
  3. DOWNLOADER根据Request对象中的URL地址发送一次HTTP请求到网站的服务器,之后用服务器返回的HTTP响应构造出一个Response对象,其中包含页面的HTML文本
  4. Response对象最终会被送到SPIDER的页面解析函数处进行处理,页面解析函数可以从页面中提取数据,并且封装为ITEM之后提交给ENGINE,之后被送往ITEM PIPELINE进行处理,最后由EXPORTER以某种数据格式写入文件;除此之外,页面解析函数还可以从页面中提取链接,构造出一个新的Request对象提交给ENGINE

Request和Response对象

Request对象
1
class scrapy.http.Request(url[, callback, method='GET', headers, body, cookies, meta, encoding='utf-8', priority=0, dont_filter=False, errback, flags])
  • url:请求页面的url地址
  • callback:页面解析函数,Request对象请求的页面在下载完成之后,由该参数指定的页面解析函数被调用,如果未传递该参数,则默认调用Spider的parse方法
  • method:HTTP请求的方法,默认为GET
  • headers:HTTP请求的头部字典,dict类型
  • body:HTTP请求的正文
  • cookies:Cookies信息字典,dict类型
  • meta:Request的元数据字典,用于给框架中其他组件传递信息
  • encoding:url和body参数的编码默认为UTF-8,如果传入的参数是str类型,则使用该参数进行编码
  • priority:请求的优先级默认值为0,优先级高的请求优先下载
  • dont_filter:如果对同一个url地址多次提交下载请求,后面的请求会被屏蔽,将此参数设置为True可以避免请求被过滤,强制下载
  • errback:请求出现异常或者出现HTTP错误时的回调函数
  • flag:一个Request请求的标记,一般用于log记录
Response对象

Response对象是用来描述一个HTTP响应的,Response只是一个基类,根据响应内容的不同有如下子类:

  • TextResponse
  • HtmlResponse
  • XmlResponse

当一个页面下载完成后,下载器就依据HTTP响应头部中的Content-Type信息创建某个Response的子类对象

1
class scrapy.http.Response(url[, status=200, headers=None, body=b'', flags=None, request=None])
  • url:HTTP响应的url地址
  • status:HTTP响应的状态码
  • headers:HTTP响应的头部,类字典类型,可以用getgetlist方法进行访问,例如:
1
response.headers.get('Content-Type')
  • body:HTTP响应正文
  • text:文本形式的HTTP响应正文
  • encoding:HTTP响应正文的编码
  • request:产生该HTTP响应的Request对象
  • meta:即response.request.meta
  • selector:用于在Response中提取数据
  • xpath:使用XPath选择器在Response中提取数据
  • css:使用CSS选择器在Response中提取数据
  • urljoin:用于构造绝对url

Spider开发流程

一般而言,实现一个Spider只需要以下几个步骤:

  1. 继承scrapy.Spider
  2. Spider取名
  3. 设置起始的爬取点
  4. 实现页面解析函数

使用Selector提取数据

我们要从页面中提取数据需要进行HTTP文本解析,一般用以下模块进行处理:

  • BeautifulSoup
  • lxml

Scrapy综合以上两者的优点实现了Selector

在Scrapy中使用Selector对象提取页面中的数据,使用前先通过选择器选中页面中需要提取的数据,然后进行提取

Selector对象

Selector类的实现位于scrapy.selector模块

创建对象

我们可以将页面的HTML文档字符串传递给Selector构造器方法的text参数

也可以使用一个Response对象构造Selector对象,将其传递给Selector构造器方法的response参数

选中数据

调用Selector对象的XPath方法或CSS方法,可以选中文档中的某个或某些部分

XPath方法和CSS方法返回一个SelectorList对象,其中包含每个被选中部分对应的Selector对象

SelectorList对象也有XPath和CSS方法,但是不同的是这里的方法是调用SelectorList对象当中的每一个Selector对象的XPath和CSS方法,并将结果收集到一个新的SelectorList对象当中,然后返回给用户

提取数据

调用SelectorSelectorList对象的以下方法可以将选中的内容提取出来

  • extract()
  • re()
  • extract_first()SelectorList对象专有,提取第一个Selector对象的数据)
  • re_first()SelectorList对象专有,对第一个Selector对象进行正则匹配)

Response内置Selector

在我们实际的开发中,一般不需要手动创建Selector对象

因为在第一次访问一个Response对象的selector属性时,Response对象内部会以自身为参数自动创建Selector对象,并将该对象缓存,以便下次使用

为了方便,Response对象还内置了XPath和CSS方法,它们会在内部调用内置Selector对象的XPath和CSS方法

Xpath

Xpath即XML路径语言,它是一种用来确定XML文档中某部分位置的语言

XML文档的节点有多种类型,其中最常用的有以下几种:

  • 根节点(整个文档树的根)
  • 元素节点(html,body,div,p,a)
  • 属性节点(href)
  • 文本节点(正文)

节点之间的关系有以下几种:

  • 父子
  • 兄弟
  • 祖先/后裔

基础语法

下表列出了XPath常用的基本语法

表达式 描述
/ 选中文档的根
. 选中当前节点
选中当前节点的父节点
ELEMENT 选中子节点中所有的ELEMENT元素节点
//ELEMENT 选中后代节点中所有ELEMENT元素节点
* 选中所有元素子节点
text() 选中所有文本子节点
@ATTR 选中名为ATTR的属性节点
@* 选中所有属性节点
[谓语] 谓语用来查找某个特定的节点或者包含某个特定值的节点

常用函数

XPath还提供许多函数,如数字,字符串,时间,日期,统计等等,例如:

  • position() 选中指定位置
  • last() 选中最后一个
  • string() 返回参数的字符串值
  • contains(str1,str2) 判断str1中是否包含str2,返回bool值

CSS选择器

基础语法

表达式 描述 例子
* 选中所有元素 *
E 选中E元素 p
E1,E2 选中E1和E2元素 div,pre
E1 E2 选中E1后代元素中的E2元素 div p
E1>E2 选中E1子元素中的E2元素 div>p
E1+E2 选中E1兄弟元素中的E2元素 p+strong
.CLASS 选中CLASS属性包含CLASS的元素 .info
#ID 选中id属性为ID的元素 #main
[ATTR] 选中包含ATTR属性的元素 [href]
[ATTR=VALUE] 选中包含ATTR属性且值为VALUE的元素 [method=post]
[ATTR~=VALUE] 选中包含ATTR属性且值包含VALUE的元素 [class~=clearfix]
E:nth-child(n)
E:nth-last-child(n)
选中E元素,且该元素必须是其父元素的(倒数)第n个子元素 a:nth-child(1)
E:first-child
E:last-child
选中E元素,且该元素必须是其父元素的(倒数)第一个子元素 a:first-child
E:empty 选中没有子元素的E元素 div:empty
E::text 选中E元素的文本节点 p::text

使用Item封装数据

我们在存储数据的时候,经常会使用字典进行存储,但是字典会有以下的缺点:

  1. 无法一目了然地了解数据当中的字段,影响代码可读性
  2. 缺乏对字段名字的检测,容易因为笔误而出错
  3. 不便于携带元数据(传递给其他组件的信息)

Item和Field

Scrapy定义了两个类,用户可以用它们自定义数据类,封装爬取到的信息:

  • Item基类:自定义数据类的基类
  • Field类:用来描述自定义数据类型包含哪些字段(如name,price等)
1
2
3
4
5
6
from scrapy import Item,Field
class BookItem(Item):
name = Field()
price = Field()

book1 = BookItem(name='Needful Things',price=45.0)

拓展Item子类

有时候如果需要对已经自定义的数据类进行拓展的话,可以直接继承之前的类,然后在定义中加入新的Field

使用Item Pipeline处理数据

Item Pipeline是负责处理数据的组件,在一个项目中可以同时启用多个Item Pipeline,按照指定次序级联起来,形成一条数据流水线

以下是几种典型应用:

  • 清洗数据
  • 验证数据的有效性
  • 过滤掉重复的数据
  • 将数据存入数据库

Item Pipeline

在创建一个Scrapy项目时,会自动生成一个pipelines.py文件,它用来存放用户自定义的Item Pipeline

Item Pipeline不需要继承特定的基类,只需要实现特定的方法即可

一个Item Pipeline必须实现一个process_item(item,spider)方法

其中item是爬取到的一项数据,Spider是爬取到此数据的Spider对象

如果process_item(item,spider)在处理某项item时返回了一项数据,返回的数据会递送给下一级Item Pipeline继续处理

如果process_item(item,spider)在处理某项item时抛出了一个DropItem异常,则该项item会被抛弃,不再递送给后面的Item Pipeline进行处理

除了必须实现的process_item(item,spider)之外,还有3个比较常用的方法:

  • open_spider(self,spider) 在Spider打开时回调该方法,常用于初始化,如连接数据库
  • close_spider(self,spider) 在Spider关闭时回调该方法,常用于处理完所有数据之后的清理工作,如关闭数据库
  • from_crawler(cls,crawler) 创建Item Pipeline时回调该方法,通常通过crawler.settings读取配置,根据配置创建Item Pipeline对象

在Scrapy中,Item Pipeline是可选的组件,想要启用的时候需要在settings.py中进行配置

使用LinkExtractor提取链接

一般而言,提取链接有两种方法:

  • 使用Selector
  • 使用LinkExtractor

当需要提取大量链接或提取的规则比较复杂时,使用LinkExtractor更加方便

使用LinkExtractor

一般使用LinkExtractor模块的流程如下:

  1. 导入LinkExtractor模块
  2. 创建一个LinkExtractor对象,使用一个或多个构造器参数描述提取规则
  3. 调用LinkExtractor对象的extract_links方法,并传入一个Response对象,该方法会依据创建对象时的提取规则去从Response对象包含的页面中提取链接,并返回一个由绝对url构成的列表,可以用其直接构造Request对象

描述提取规则

1
classscrapy.linkextractors.lxmlhtml.LxmlLinkExtractor(allow=(), deny=(), allow_domains=(), deny_domains=(), deny_extensions=None, restrict_xpaths=(), restrict_css=(), tags=('a', 'area'), attrs=('href', ), canonicalize=False, unique=True, process_value=None, strip=True)

在Scrapy早期的版本中也有其他的LinkExtractor类,但是现在它们被弃用了

  • allow 接收一个正则表达式或者正则表达式列表,用于提取绝对url,如果该参数为空则提取全部链接
  • deny 接收一个正则表达式或者正则表达式列表,用于排除匹配的url
  • allow_domains 接收一个域名或者域名列表,提取到指定域的链接
  • deny_domains 接收一个域名或者域名列表,排除到指定域的链接
  • deny_extensions 在接收时需要忽略的扩展名
  • restrict_xpaths 接收一个XPath表达式或表达式列表,提取XPath表达式选中区域下的链接
  • restrict_css 接收一个CSS选择器或选择器列表,提取CSS选择器选中区域下的链接
  • tag 接收一个标签或标签列表,提取指定标签内的链接
  • attrs 接收一个属性或一个属性列表,提取指定属性内的链接
  • canonicalize 对提取的url进行规范化处理,常设置为False
  • unique 是否应对提取的链接进行重复过滤
  • process_value 接收一个形如func(value)的回调函数,LinkExtractor将会调用该回调函数对提取的每一个链接进行处理
  • strip 是否从提取的属性中去除空格,因为LinkExtractor会自动去除空格

使用Exporter导出数据

在Scrapy中,负责导出数据的组件被称为Exporter

Scrapy实现了多个Exporter,每个Exporter支持一种数据格式的导出,支持的数据格式如下所示:

  • JSON
  • JSON lines
  • CSV
  • XML
  • Pickle
  • Marshal

如果需要导出为其他数据,则需要自己实现Exporter

指定导出数据

在导出数据时,需要向爬虫提供以下信息:

  • 导出文件的路径
  • 导出的数据格式

在配置文件中,经常用到以下几个选项:

  • FEED_URL 导出文件的路径
  • FEED_FORMAT 导出的数据格式
  • FEED_EXPORT_ENCODING 导出文件编码

默认情况下JSON文件使用数字编码,其他使用UTF-8编码

  • FEED_EXPORT_FIELDS 导出数据包含的字段(默认导出所有字段),并指定次序
  • FEED_EXPORTERS 用户定义新的Exporter字典,添加新的导出数据格式的时候使用

用户自定义的导出数据格式的代码编写此处不赘述,略

下载文件和图片

下载文件也是爬虫很常用的一种需求,例如图片,视频,文档,压缩包等等

Scrapy框架内置了两个Item Pipeline专门用于下载文件和图片

  • FilesPipeline
  • ImagesPipeline

FilesPipeline的使用

FilesPipeline的使用步骤一般如下所示:

  1. 在配置文件settings.py中启用FilesPipeline,通常是将其置于其他的Item Pipeline之前
  2. 在配置settings.py时,使用FILES_STORE指定文件的下载目录
  3. 在Spider解析一个包含文件下载链接的页面时,将所有需要下载文件的url地址收集到一个列表中,然后赋值给itemfile_urls字段(item[‘file_urls’])
    FilesPipeline在处理每一项item时都会进行读取,然后对其中的每一个url进行下载

当FilesPipeline下载完所有的文件后,就会将下载的结果信息存储到另一个列表中去,下载的结果包含以下内容:

  • 文件下载到本地的路径
  • Checksum文件的校验和
  • url文件的url地址

ImagesPipeline的使用

图片的本质也是文佳,ImagesPipeline是FilesPipeline的子类,使用上大同小异,只是配置的选项上有细微的差别

FilesPipeline ImagesPipeline
导入路径 scrapy.pipelines.files.FilesPipeline scrapy.pipelines.images.ImagesPipeline
Item字段 file_urls,files image_urls,images
下载目录 FILES_STORE IMAGES_STORE

ImagesPipeline在FilesPipeline的基础上针对图片增加了一些特有的功能

  • 为下载的图片生成缩略图

要开启此功能,只需要在配置文件settings.py中设置IMAGES_THUMBS,例如:

1
2
3
4
IMAGES_THUMBS = {
'small':(50,50),
'big':(270,270),
}
  • 过滤掉尺寸较小的图片

开启该功能需要在配置文件settings.py中设置IMAGES_MIN_WIDTHIMAGES_MIN_HEIGHT,它们分别指定最小尺寸的图片的宽和高,例如:

1
2
IMAGES_MIN_WIDTH = 110
IMAGES_MIN_HEIGHT = 110

模拟登录

目前,大部分网站都需要登录才能获取资源,所以有时候爬虫需要先模仿用户登录,再去爬取内容

登录的实质就是向服务器发送含有登录表单数据的HTTP请求(通常是POST),Scrapy提供了一个FormRequest类,专门用于构造含有表单数据的请求

Scrapy的登录模块

FormRequest的构造器方法有一个formdata参数,接收字典形式的表单数据

我们还可以直接调用FormRequestfrom_response方法,调用时需要传入一个Response对象作为一个参数,该方法会解析Response对象中所包含页面中的<form>元素,帮助用户创建FormRequest对象,并自动填入表单数据,我们只需要通过formdata参数将账号和密码填入即可

识别验证码

目前很多网站为了防止爬虫爬取,登录的时候需要用户输入验证码,一般有以下几种方法去识别验证码:

  • OCR识别

我们可以使用Python的第三方库进行识别(例如tesseract-ocr

  • 网络平台API

也可以去验证码识别平台购买相关服务套餐,接入API

  • 人工识别

在其他方法不管用的时候,我们也可以等Scrapy下载完验证码图片后,调用Image.show方法来显示图片,然后再调用Python内置的input函数来捕获用户的输入

Cookie登录

我们不需要去研究各个浏览器将Cookie以何种形式存储在何处,只需要调用第三方库browsercookie即可获得Chorme和Firefox浏览器中的Cookie

爬取动态页面

我们之前讨论的都是静态页面的信息爬取,但是在实际应用中,大多数页面都是动态页面,页面中的部分内容是需要运行页面中的JavaScript脚本动态生成的,爬取相对困难

实际中更常见的是JavaScript通过HTTP请求跟网页动态交互获取数据(Ajax),然后使用数据去更新HTML页面

爬取此类网站需要先执行页面中的JavaScript代码去渲染页面,然后再进行爬取

Splash渲染引擎

Splash是Scrapy官方推荐的JavaScript渲染引擎,提供基于HTTP端口的JavaScript渲染服务,支持以下的功能:

  • 为用户返回经过渲染的HTML页面或者页面截图
  • 并发渲染多个页面
  • 关闭图片加载,加速渲染
  • 在页面中执行用户自定义的JavaScript代码
  • 执行用户自定义的渲染脚本(lua)

Splash的功能丰富,包含了多个服务端点,此处仅介绍两个最常用的端点:

  • render.html 提供JavaScript页面渲染服务
  • execute 执行用户自定义的渲染脚本(lua),利用该端点可以在页面中执行JavaScript代码

render.html端点

服务端点 render.html
请求地址 http://localhost:8050/render.html
请求方式 GET / POST
返回类型 HTML

render.html端点支持的参数如下表所示(仅列出常用的参数)

参数 是否必选 类型 描述
url 必选 string 需要渲染的页面的url
timeout 可选 float 渲染页面的超时时间
proxy 可选 string 代理服务器地址
wait 可选 float 等待页面渲染的时间
images 可选 integer 是否下载图片,默认为1
js_source 可选 string 用户自定义的JavaScript代码,在页面渲染前执行

execute端点

在爬取一些页面的时候,我们想在页面中执行一些用户自定义的JavaScript代码,可以通过利用Splash的execute端点来实现

服务端点 execute
请求地址 http://localhost:8050/execute
请求方式 POST
返回类型 HTML

execute支持的参数如下表所示

参数 是否必选 类型 描述
lua_source 必选 string 用户自定义的lua脚本
timeout 可选 float 渲染页面的超时时间
proxy 可选 string 代理服务器地址

我们可以将execute端点的服务看作是一个可以用lua语言编程的浏览器,使用时需要传递一个用户自定义的lua脚本给Splash,该lua脚本中包含用户想要模拟的浏览器行为,例如:

  • 打开某url地址的页面
  • 等待页面加载或渲染
  • 执行JavaScript代码
  • 获取HTTP响应头部
  • 获取Cookie

用户自定义的lua脚本中必须包含一个main函数作为程序的入口,main函数被调用的时候会传入一个Splash对象(lua中的对象),用户可以调用该对象上的方法操纵Splash

在Scrapy中使用Splash

如果我们需要在Scrapy中调用Splash服务,Python的scrapy-splash库是非常好的选择

我们在安装好Python包之后,需要在settings.py中对其进行配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 渲染服务的url
SPLASH_URL = 'http://127.0.0.1:8050'
# 下载器中间件
DOWNLOADER_MIDDLEWARES = {
'scrapy_splash.SplashCookiesMiddleware': 723,
'scrapy_splash.SplashMiddleware': 725,
'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 810,
}
# 去重过滤器
DUPEFILTER_CLASS = 'scrapy_splash.SplashAwareDupeFilter'
# 使用Splash的Http缓存
HTTPCACHE_STORAGE = 'scrapy_splash.SplashAwareFSCacheStorage'

# Obey robots.txt rules
ROBOTSTXT_OBEY = False

然后再编写代码爬取网页(以百度知道为例)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import scrapy
from scrapy_splash import SplashRequest # 使用scrapy_splash包提供的request对象

class WithSplashSpider(scrapy.Spider):
name = 'with_splash'
allowed_domains = ['baidu.com']
start_urls = ['https://www.baidu.com/s?wd=13161933309']

def start_requests(self):
yield SplashRequest(self.start_urls[0],
callback=self.parse_splash,
args={'wait': 10}, # 最大超时时间,单位:秒
endpoint='render.html') # 使用splash服务的固定参数

def parse_splash(self, response):
with open('with_splash.html', 'w') as f:
f.write(response.body.decode())

存入数据库

我们在爬取到数据之后,有些时候需要将其存储到数据库中

SQLite

SQLite是一个轻量级数据库,在数据量很小的情况下,它的处理速度很快,使用它足够了

SQLite数据库的文件创建和表创建在此不做赘述

在Python中,可以使用Python标准库的sqlite3模块去访问SQLite数据库

在配置文件settings.py时,我们需要指定所要使用的SQLite数据库,并启用和SQLite相关的Pipeline

1
SQLITE_DB_NAME = 'scrapy.db'

MySQL

MySQL的应用极其广泛,它是开源免费的,可以支持大型数据库,是个人用户和中小企业的技术首选

此次仍然不赘述MySQL数据库的创建和表的创建

Python可以使用mysqlclient模块访问MySQL数据库

在配置文件settings.py时,我们需要指定所要使用的MySQL数据库,并启用和MySQL相关的Pipeline

1
2
3
4
MYSQL_DB_NAME = 'scrapy_db'
MYSQL_HOST = 'localhost'
MYSQL_USER = 'Edwards'
MYSQL_PASSWORD = '12345678'

MongoDB

MongoDB是一个面向文档的非关系型数据库,近年来得到了广泛应用

Python可以使用pymongo模块访问MongoDB数据库

在配置文件settings.py时,我们需要指定所要使用的MongoDB数据库,并启用和MongoDB相关的Pipeline

1
2
MONGODB_URL = 'mongodb://localhost:27017'
MONGODB_DB_NAME = 'scrapy_db'

Redis

Redis是一个使用ANSI C编写的高性能Key-Value数据库,使用内存作为主存储

在Python中可以使用redis-py访问Redis数据库

在配置文件settings.py时,我们需要指定所要使用的Redis数据库,并启用和Redis相关的Pipeline

1
2
3
REDIS_HOST = 'localhost'
REDIS_PORT = 6379
REDIS_DB_INDEX = 0

使用HTTP代理

HTTP的代理服务器可以比作客户端和服务器之间的一个信息中转站,客户端发送的HTTP请求和Web返回的HTTP响应通过代理服务器转发给对方

HttpProxyMiddleWare

Scrapy内部提供了一个下载的中间件HttpProxyMiddleWare,专门用于给Scrapy爬虫设置代理

默认情况下,HttpProxyMiddleWare是启用的,它会在系统的环境变量中搜索当前的系统代理(名字格式为xxx_proxy的环境变量)作为Scrapy爬虫所使用的代理

多个代理

当利用HttpProxyMiddleWare进行代理的时候,对于一种协议(HTTP或HTTPS)的所有请求只能使用一个代理,如果想使用多个代理,可以在构造每一个Request对象时,通过meta参数的proxy字段手动设置

随机代理

某些网站为了反爬虫,经常会监测IP的访问量,如果同一IP在短时间内大量访问的话,服务器会将其封禁

爬虫可以使用多个代理对此类网站进行爬取,此时的访问量会被多个代理所分摊,从而避免封禁IP

我们只需要在middlewares.py中实现随机使用代理的算法即可

分布式爬虫

由于受到计算能力和网络带宽的限制,单个计算机上运行的爬虫在爬取的数据量较大的情况下,需要耗费较多的时间

scrapy-redis库为Scrapy拓展了分布式爬取的功能,可以让网络中的多台计算机上同时运行爬虫程序