我们知道scrapy大致的原理是这样,首先会在start_requests 这个方法里发出一些请求url,然后在parse里进行解析,解析的item抛给pipeline进行处理. parse 如果又解析到url,抛出,先看下是否要过滤这个url,是否重复了,如果没有重复,发一个新请求这个url,再调用别的parse进行处理。直到待请求的url都为空,就停止爬虫。
import scrapy
from tutorial.items import TutorialItem
class QuotesSpider(scrapy.Spider):
name = "quotes"
def start_requests(self):
url = 'http://quotes.toscrape.com/tag/humor/'
yield scrapy.Request(url)
def parse(self, response):
item = TutorialItem()
for quote in response.css('div.quote'):
item['body'] = quote.css('span.text::text').extract_first()
item['author'] = quote.css('small.author::text').extract_first()
yield item
next_page = response.css('li.next a::attr("href")').extract_first()
if next_page is not None:
yield response.follow(next_page, self.parse)
默认的scrapy也支持暂停爬虫,保存到本地,下一次再进行爬。但是这样就没法支持分布式啊。
scrapy-redis 就是为了支持分布式做的。它做了什么呢?把这些数据保存到redis中,让每个爬虫来对redis中的url进行解析。有个dupefilter来过滤重复的请求,item用来存储所有的item,request 是待爬队列。request如果爬了的,就会pop,删除,所以完整爬完request就没有数据了。就是用了redis数据库来实现了分布式。
我的是Mac环境。
sudo pip3 install scrapy-redis
brew install redis
如果没有brew,要先安装brew
如果在终端中输入 redis-server,看下下面的画面就表示启动成功了。
https://redisdesktop.com/ 去这个地址来安装,很烦,下载的版本要付费,免费的要自己编译,它有教你如何编译的。要下载qt来编译。我下载qt编译了,但是不知道如何发布,所以也没法给下载地址。
import scrapy
from scrapy_redis.spiders import RedisSpider
from tutorial.items import TutorialItem
class QuotesSpider(RedisSpider):
name = "quotes"
redis_key = 'quotes:start_urls'
# __init__方法必须按规定写,使用时只需要修改super()里的类名参数即可
def __init__(self, *args, **kwargs):
# 修改这里的类名为当前类名
super(QuotesSpider, self).__init__(*args, **kwargs)
def parse(self, response):
item = TutorialItem()
for quote in response.css('div.quote'):
item['body'] = quote.css('span.text::text').extract_first()
item['author'] = quote.css('small.author::text').extract_first()
yield item
next_page = response.css('li.next a::attr("href")').extract_first()
if next_page is not None:
yield response.follow(next_page, self.parse)
首先是改成继承RedisSpider,然后增加一个redis_key是爬虫名字加冒号加start_urls,这个等下会通过命令行手动push到redis数据库中的。去掉了start_requests,因为所有的爬虫都是从redis来获取url,所以没有开始请求的地址了。第一个启动的爬虫是通过命令的方式来push url进去的。
# Enables scheduling storing requests queue in redis.
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
# Ensure all spiders share same duplicates filter through redis.
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
SCHEDULER_PERSIST = True
FEED_EXPORT_ENCODING = 'utf-8'
ITEM_PIPELINES = {
'scrapy_redis.pipelines.RedisPipeline': 300,
}
REDIS_HOST = 'localhost'
REDIS_PARAMS = {
'password': '123456',
}
REDIS_PORT = 6379
过滤的改成scrapy-redis 中的过滤类,还有scheduler也是。然后修改编码,再是pipeline也改成用redispipeline, 接下来如果是host的爬虫,就是主爬虫,要写REDIS_HOST的地址,下面的是密码和端口。注意下这里加上了密码,这样可以让其他的爬虫来连接安全些,不然又会提示其他的很烦。用密码的方式来启动redis的方法是:新建一个文件redis.conf,里面写
protected-mode no
requirepass 123456
123456就是redis的密码
然后用这样的方式来启动redis就是要密码了,
redis-server ./redis.conf
命令带上配置文本
REDIS_URL = 'redis://root:[email protected]:6379'
REDIS_PORT = 6379
除了主爬虫外,其他的爬虫设置,其中redis filter pipeline等是和主爬虫一样,除了地址这个,是要访问主机的redis,所以要加用户名,密码,地址的方式.而不是REDIS_HOST了,用REDIS_URL的方式作为通信地址.
首先是主爬虫还是一样
scrapy crawl quotes
quotes 就是爬虫的名字,启动完了后,它是不会立即去抓的,因为还没有start_urls,再打开一个终端,输入
redis-cli auth 123456 lpush quotes:start_urls http://quotes.toscrape.com/tag/humor/
这样就OK了。 redis-cli表示启动redis客户端, auth后面的是redis密码。lpush是redis list的操作方式,往quotes:start_urls里面插入数据。爬虫会以这个作为启动url,然后爬完会删除,所以你通过redis可视化工具也不是马上能看到,因为它很快就删除了。
scrapy crawl quotes
子爬虫就什么都不需要做了,它会连接上主机的redis,对那里的url进行处理。它自己爬到item也会插入到主机中的redis数据库中。
http://www.waitingfy.com/archives/2027