scrapy是一个通用的爬虫框架,但是不支持分布式,scrapy_redis是为了更方便的实现scrapy分布式爬取,而提供了一些以redis为基础的组件(仅有组件)。
Scheduler 调度器,scrapy本身不支持爬虫分布,scrapy_redis的解决是把这个scrapy queue换成redis数据库(也是指redis队列),从同一个redis-server存放要爬取的request,便能让多个spider去同一个数据库里读取。
Duplication Filter 指纹过滤器,scrapy用集合实现这个request去重功能,scrapy中把已经发送的request指纹放到一个集合中,把下一个request的指纹放到集合中比对,如果该指纹存在于集合中,说明这个request发送过了,如果没有则继续操作。
Item Pipeline 管道,引擎将(spider返回的)爬取到的item给Item Pipeline,scrapy_redis的Item Pipeline将爬取到的item存入redis的items pipeline。
Base Spider
分布式爬虫例子(爬取读书网的图书名称和封面图片链接,常规设置或者不需要修改的部分代码就没贴了):
# settings.py文件增加配置
# 去重类的引入
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
# redis调度器的引用
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
# redis是否本地化的开关
SCHEDULER_PERSIST = True
# 分布式爬虫需要配置要访问的redis的主机
REDIS_HOST = '10.11.56.63' # 主机ip
REDIS_PORT = 6379
ITEM_PIPELINES = {
'dushuProject.pipelines.DushuprojectPipeline': 300,
# 导入依赖
'scrapy_redis.pipelines.RedisPipeline':400,
}
# 延时1s(反爬虫)
DOWMLOAD_DELAY = 1
# items.py文件,即要爬取的数据字段
import scrapy
class DushuprojectItem(scrapy.Item):
title = scrapy.Field()
img_url = scrapy()
# pipelines.py文件,未作修改
class DushuprojectPipeline(object):
def process_item(self, item, spider):
return item
# read2.py文件(爬虫文件,读书网)
# -*- coding: utf-8 -*-
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import Rule
from scrapy_redis.spiders import RedisCrawlSpider # 导入RedisCrawlSpider
class Read2Spider(RedisCrawlSpider): # 继承的父类修改一下
name = 'read2' # 爬虫名字
# start_urls = ['https://www.dushu.com/book/1081.html'] # 初始url
# 键名称的一般规则 爬虫名字:start_urls
redis_key = 'read2:start_urls' # 由主机提供
# 指定了页面内,链接的提取规则,会被父类自动调用
rules = (
Rule(LinkExtractor(allow=r'/book/1081_\d+.html'), callback='parse_item', follow=False),
)
# 页面数据解析函数
# 可以自定义,只要保证callback的参数与这个函数名一致即可
def parse_item(self, response):
# 每页的图书列表
book_list = response.xpath('//div[@class="bookslist"]//li')
for each in book_list:
i = {}
i['title'] = each.xpath('.//h3//@title').extract_first()
i['img_url'] = each.xpath('.//img/@src').extract_first()
print(i)
yield i
# 执行分布式爬虫的步骤:
# 1. 本地运行以下命令
scrapy runspider read2.py
# 2. 主机端开启redis服务
# 另开窗口
redis-cli
lpush redis_key start_url # 推送start_url
# 例如 lpush read2:star_url "https://www.dushu.com/book/1081.html"
远程连接redis:
redis-cli -h ip -p 6379 -a password