一,scrapy和scrapy-redis的区别?
scrapy是一个爬虫通用框架,但不支持分布式,scrapy-redis是为了更方便的实现scrapy分布式爬虫,而提供了一些以redis为基础的组件
二,为什么scrapy框架不支持分布式?
因为scrcapy中的调度对列不支持共享,而scrapy-redis中,可以共享该对列
三,scrapy-redis工作原理?
1,爬虫程序把请求链接,发送给爬虫引擎,
2,爬虫引擎把请求链接传递到调度对列
3,调度sheduler会把链接存放到redis数据库中
4,redis数据库因为具有集合的性质,对去重有更好的体现,传进来的链接会生成一个指纹, redis会把 传进来的链接进行对比,相同的链接直接去重,把没有的链接加入到对列中,然后把链接再传递到调度对列中。
5,调度中的对列把链接发送到下载模块
6,下载模块,下载好数据后,把数据及下载的链接发送到爬虫程序
7,爬虫程序把数据及链接发送到redis数据库(如果此时自定义管道,则会把数据存放到自定义的数据库中)
8.,可以从redis数据库中把数据下载到本地
四,redis怎么去重的?
如果多台机器不仅往请求队列存,还同时从里面取,那么如何保证每台机子请求和存储的队列是不重复的呢?
借助redis集合
redis提供集合数据结构,我们知道集合里面的元素是不重复的
首先,在redis中存储每个request的指纹。
在向request队列中加入request前首先验证这个request的指纹是否已经加入到集合中。
如果已存在,则不添加requets到队列,
如果不存在,则将request添加入队列并将指纹加入集合。
五,分布式爬虫架构实际上就是:
由一台主机维护所有的爬取队列,每台从机的sheduler共享该队列,协同存储与提取。
分布式爬虫的多台协作的关键是共享爬取队列
六,队列用什么维护呢?
推荐redis队列
redis是非关系型数据库,用key-value形式存储,结构灵活,他不像关系型数据库必须要由一定的结构才能存储。
key-value可以是多种数据,非常灵活。
另外,redis是内存中的数据结构存储系统,处理速度快,性能好。
提供了队列,集合多种存储结构,方便队列维护和去重操作。
七,怎样防止中断?
在爬取的过程中,难免会有某台机子卡掉了,这时怎么办?
在每台从机scrapy启动时都会首先判断当前redis request队列是否为空。
如果不为空,则从队列中取得下一个request执行爬取。
如果为空,则重新开始开始爬取,第一台从机执行爬取想队列中添加request。
怎样实现该架构?
要做到:
维护request队列
对台从机调度reuqest
设置去重
链接redis
已经有了比较成熟的库scrapy-redis
scrapy-redis库实现了如上架构,改写了scrapy的调度器,队列等组件
利用它可以方便地实现scrapy分布式架构
https://github.com/rolando/scrapy-redis
八,步骤及代码
1,安装redis
启动redis服务:redis-server
启用shell客户端:redis-cli 可以输入指令 (在这里面启动指令)
2,修改配置文件redis.conf
把bind:127.0.0.1注释掉,可以让其他IP也可以访问,其他爬虫端才能连接到服务端的数据库
3,连接到服务端测试
linux下 sudo redis-cli -h 服务端的IP -h指定
如果-h没有指定,就会默认在本地
slave端无需启动radis-server,mster端启动即可,只要slave能读取到mster中的数据库就行了
代表可以实施分布式
4,自动构建一个scrapy框架 scrapy startproject 项目名(做修改)
5,关于settings中代码的修改
DOWNLOAD_DELAY =0.5 #下载延迟,就是从别人服务器上获取数据时,延迟时间
SCHEDULER ="scrapy_redis.scheduler.Scheduler" #任务调度,使用scrapy-redis里面的调度器组件,不使用scrapy默认的调度器
DUPEFILTER_CLASS ="scrapy_redis.dupefilter.RFPDupeFilter" #去重,用的是scrapy_redis里的去重组件,不适用scrapy默认的去重
SCHEDULER_PERSIST =True #是否开启,允许暂停,redis请求记录不丢失
SCHEDULER_QUEUE_CLASS ='scrapy_redis.queue.SpiderQueue' #调度策略:队列,默认是scrapy_redis请求,(按优先级顺序)队列形成 (有三种形式,只是一个先后顺序,影响不大)
#指定redis数据库的主机
REDIS_HOST ='127.0.0.1' #修改为Redis的实际IP地址
REDIS_PORT =6379 #修改为Redis的实际端口
6,爬虫程序的开发
导入需要的模块
# -*- coding: utf-8 -*-
import scrapy
from scrapy_redis.spidersimport RedisCrawlSpider
from scrapy.spidersimport CrawlSpider, Rule
from scrapy.linkextractorsimport LinkExtractor
from ..itemsimport ScrapyRedisExampleItem
继承类也是需要改变的:
class CountrySpider(RedisCrawlSpider):
name ='country'
redis_key ='start_urls' #指令,用来启动爬虫端程序的
7,开多个运行窗口进行采集,模拟分布式,在服务端输入指令
搭建分布式最合适:对硬件的要求,在不同网段里面,各自处理各自的请求,这样才能体会到分布式的精髓