接下来,咱们会利用Scrapy-Redis来实现分布式的对接。
html
请确保已经成功实现了Scrapy新浪微博爬虫,Scrapy-Redis库已经正确安装。
git
要实现分布式部署,多台主机须要共享爬取队列和去重集合,而这两部份内容都是存于Redis数据库中的,咱们须要搭建一个可公网访问的Redis服务器。
github
推荐使用Linux服务器,能够购买阿里云、腾讯云、Azure等提供的云主机,通常都会配有公网IP,具体的搭建方式能够参考第1章中Redis数据库的安装方式。redis
Redis安装完成以后就能够远程链接了,注意部分商家(如阿里云、腾讯云)的服务器须要配置安全组放通Redis运行端口才能够远程访问。若是遇到不能远程链接的问题,能够排查安全组的设置。mongodb
须要记录Redis的运行IP、端口、地址,供后面配置分布式爬虫使用。当前配置好的Redis的IP为服务器的IP 120.27.34.25,端口为默认的6379,密码为foobared。数据库
新浪微博项目须要用到代理池和Cookies池,而以前咱们的代理池和Cookies池都是在本地运行的。因此咱们须要将两者放到能够被公网访问的服务器上运行,将代码上传到服务器,修改Redis的链接信息配置,用一样的方式运行代理池和Cookies池。
安全
远程访问代理池和Cookies池提供的接口,来获取随机代理和Cookies。若是不能远程访问,先确保其在0.0.0.0这个Host上运行,再检查安全组的配置。bash
如我当前配置好的代理池和Cookies池的运行IP都是服务器的IP,120.27.34.25,端口分别为5555和5556,以下图所示。服务器
接下来咱们要修改Scrapy新浪微博项目中的访问连接,以下所示:微信
PROXY_URL = 'http://120.27.34.25:5555/random'
COOKIES_URL = 'http://120.27.34.25:5556/weibo/random'复制代码
具体的修改方式根据实际配置的IP和端口作相应调整。
配置Scrapy-Redis很是简单,只须要修改一下settings.py配置文件便可。
首先最主要的是,须要将调度器的类和去重的类替换为Scrapy-Redis提供的类,在settings.py里面添加以下配置便可:
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"复制代码
接下来配置Redis的链接信息,这里有两种配置方式。
第一种方式是经过链接字符串配置。咱们能够用Redis的地址、端口、密码来构造一个Redis链接字符串,支持的链接形式以下所示:
redis://[:password]@host:port/db
rediss://[:password]@host:port/db
unix://[:password]@/path/to/socket.sock?db=db复制代码
password
是密码,好比要以冒号开头,中括号表明此选项无关紧要,host
是Redis的地址,port
是运行端口,db
是数据库代号,其值默认是0。
根据上文中提到个人Redis链接信息,构造这个Redis的链接字符串以下所示:
redis://:foobared@120.27.34.25:6379复制代码
直接在settings.py里面配置为REDIS_URL
变量便可:
REDIS_URL = 'redis://:foobared@120.27.34.25:6379'复制代码
第二种配置方式是分项单独配置。这个配置就更加直观明了,如根据个人Redis链接信息,能够在settings.py中配置以下代码:
REDIS_HOST = '120.27.34.25'
REDIS_PORT = 6379
REDIS_PASSWORD = 'foobared'复制代码
这段代码分开配置了Redis的地址、端口和密码。
注意,若是配置了REDIS_URL
,那么Scrapy-Redis将优先使用REDIS_URL
链接,会覆盖上面的三项配置。若是想要分项单独配置的话,请不要配置REDIS_URL
。
在本项目中,我选择的是配置REDIS_URL
。
此项配置是可选的,默认使用PriorityQueue
。若是想要更改配置,能够配置SCHEDULER_QUEUE_CLASS
变量,以下所示:
SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.PriorityQueue'
SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.FifoQueue'
SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.LifoQueue'复制代码
以上三行任选其一配置,便可切换爬取队列的存储方式。
在本项目中不进行任何配置,咱们使用默认配置。
此配置是可选的,默认是False
。Scrapy-Redis默认会在爬取所有完成后清空爬取队列和去重指纹集合。
若是不想自动清空爬取队列和去重指纹集合,能够增长以下配置:
SCHEDULER_PERSIST = True复制代码
将SCHEDULER_PERSIST
设置为True
以后,爬取队列和去重指纹集合不会在爬取完成后自动清空,若是不配置,默认是False
,即自动清空。
值得注意的是,若是强制中断爬虫的运行,爬取队列和去重指纹集合是不会自动清空的。
在本项目中不进行任何配置,咱们使用默认配置。
此配置是可选的,默认是False
。若是配置了持久化或者强制中断了爬虫,那么爬取队列和指纹集合不会被清空,爬虫从新启动以后就会接着上次爬取。若是想从新爬取,咱们能够配置重爬的选项:
SCHEDULER_FLUSH_ON_START = True复制代码
这样将SCHEDULER_FLUSH_ON_START
设置为True
以后,爬虫每次启动时,爬取队列和指纹集合都会清空。因此要作分布式爬取,咱们必须保证只能清空一次,不然每一个爬虫任务在启动时都清空一次,就会把以前的爬取队列清空,势必会影响分布式爬取。
注意,此配置在单机爬取的时候比较方便,分布式爬取不经常使用此配置。
在本项目中不进行任何配置,咱们使用默认配置。
此配置是可选的,默认不启动Pipeline。Scrapy-Redis实现了一个存储到Redis的Item Pipeline,启用了这个Pipeline的话,爬虫会把生成的Item存储到Redis数据库中。在数据量比较大的状况下,咱们通常不会这么作。由于Redis是基于内存的,咱们利用的是它处理速度快的特性,用它来作存储未免太浪费了,配置以下:
ITEM_PIPELINES = {
'scrapy_redis.pipelines.RedisPipeline': 300
}复制代码
本项目不进行任何配置,即不启动Pipeline。
到此为止,Scrapy-Redis的配置就完成了。有的选项咱们没有配置,可是这些配置在其余Scrapy项目中可能用到,要根据具体状况而定。
以前Scrapy新浪微博爬虫项目使用的存储是MongoDB,并且MongoDB是本地运行的,即链接的是localhost。可是,当爬虫程序分发到各台主机运行的时候,爬虫就会链接各自的的MongoDB。因此咱们须要在各台主机上都安装MongoDB,这样有两个缺点:一是搭建MongoDB环境比较繁琐;二是这样各台主机的爬虫会把爬取结果分散存到各自主机上,不方便统一管理。
因此咱们最好将存储目标存到同一个地方,例如都存到同一个MongoDB数据库中。咱们能够在服务器上搭建一个MongoDB服务,或者直接购买MongoDB数据存储服务。
这里使用的就是服务器上搭建的的MongoDB服务,IP仍然为120.27.34.25,用户名为admin,密码为admin123。
修改配置MONGO_URI
为以下:
MONGO_URI = 'mongodb://admin:admin123@120.27.34.25:27017'复制代码
到此为止,咱们就成功完成了Scrapy分布式爬虫的配置。
接下来将代码部署到各台主机上,记得每台主机都须要配好对应的Python环境。
每台主机上都执行以下命令,便可启动爬取:
scrapy crawl weibocn复制代码
每台主机启动了此命令以后,就会从配置的Redis数据库中调度Request,作到爬取队列共享和指纹集合共享。同时每台主机占用各自的带宽和处理器,不会互相影响,爬取效率成倍提升。
一段时间后,咱们能够用RedisDesktop观察远程Redis数据库的信息。这里会出现两个Key:一个叫做weibocn:dupefilter,用来储存指纹;另外一个叫做weibocn:requests,即爬取队列,以下图所示。
随着时间的推移,指纹集合会不断增加,爬取队列会动态变化,爬取的数据也会被储存到MongoDB数据库中。
本节代码地址为:https://github.com/Python3WebSpider/Weibo/tree/distributed,注意这里是distributed分支。
本节经过对接Scrapy-Redis成功实现了分布式爬虫,可是部署仍是有不少不方便的地方。另外,若是爬取量特别大的话,Redis的内存也是个问题。在后文咱们会继续了解相关优化方案。
本资源首发于崔庆才的我的博客静觅: Python3网络爬虫开发实战教程 | 静觅
如想了解更多爬虫资讯,请关注个人我的微信公众号:进击的Coder
weixin.qq.com/r/5zsjOyvEZ… (二维码自动识别)