分布式爬虫概念:多台机器上执行同一个爬虫程序,实现网站数据的分布爬取。html
scrapy-redis是专门为scrapy框架开发的一套组件。该组件能够解决上述两个问题,让Scrapy实现分布式。
组件安装:python
$ pip3 intall scrapy-redis
# 不注释时,只容许本机的客户端链接 # bind 127.0.0.1 # yes改成no,关闭redis的保护模式,客户端能够对服务器进行读写操做 protected-mode no
# MAC/Linux $ pwd /Users/hqs/redis-5.0.2 $ src/redis-server redis.conf # windows $ redis-server.exe redis-windows.conf
$ scrapy startproject redisPro $ cd redisPro/ $ scrapy genspider -t crawl qiubai www.qiushibaike.com/pic/
这里运用CrawlSpider建立爬虫文件爬取全站图片数据。web
import scrapy from scrapy.linkextractors import LinkExtractor from scrapy.spiders import CrawlSpider, Rule from scrapy_redis.spiders import RedisCrawlSpider from redisPro.items import RedisproItem # 引入items类 class QiubaiSpider(RedisCrawlSpider): name = 'qiubai' # allowed_domains = ['www.qiushibaike.com/pic/'] # start_urls = ['http://www.qiushibaike.com/pic/'] # redis_key表示调度器中的队列(将要爬取的页面数据对应的url都须要放置到调度器队列中) redis_key = 'qiubaispider' # 自定义调度器队列的名称,该行代码表示的含义和start_urls同样 # 连接提取器 # 从页面提取连接页码的url:/pic/page/2?s=5147462 # s后对应的参数值会在浏览器刷新时动态变化, 正则忽略s参数的变化进行提取 link = LinkExtractor(allow=r'/pic/page/\d+') # 规则解析器 rules = ( Rule(link, callback='parse_item', follow=True), ) def parse_item(self, response): """解析操做:提取图片连接""" div_list = response.xpath('//div[@id="content-left"]/div') # 获取divz列表 for div in div_list: # 遍历div列表 # 解析提取div中图片url,保存在img标签的src属性下 img_url = "https:" + div.xpath('.//div[@class="thumb"]/a/img/@src').extract_first() # 实例化items对象 item = RedisproItem() item['img_url'] = img_url # 封装items yield item
在爬虫文件中要导入RedisCrawlSpider类,而后将爬虫文件修改为基于该类的源文件。redis
from scrapy_redis.spiders import RedisCrawlSpider # class QiubaiSpider(CrawlSpider): class QiubaiSpider(RedisCrawlSpider):
redis_key表示调度器中的队列(将要爬取的页面数据对应的url都须要放置到调度器队列中)。
redis_key自定义调度器队列的名称,表示的含义和start_urls同样,所以须要将原来的start_url注释掉。数据库
class QiubaiSpider(RedisCrawlSpider): name = 'qiubai' # allowed_domains = ['www.qiushibaike.com/pic/'] # start_urls = ['http://www.qiushibaike.com/pic//'] # redis_key表示调度器中的队列(将要爬取的页面数据对应的url都须要放置到调度器队列中) redis_key = 'qiubaispider' # 自定义调度器队列的名称,该行代码表示的含义和start_urls同样
class QiubaiSpider(RedisCrawlSpider) """代码省略""" # 连接提取器 # 从页面提取连接页码的url:/pic/page/2?s=5147462 # s后对应的参数值会在浏览器刷新时动态变化, 正则忽略s参数的变化进行提取 link = LinkExtractor(allow=r'/pic/page/\d+') # 规则解析器 rules = ( Rule(link, callback='parse_item', follow=True), )
import scrapy class RedisproItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() img_url =scrapy.Field()
使用scrapy-redis组件中封装好的能够被共享的管道。
能够将每台机器爬取到的数据存储经过该管道存储到redis数据库中,从而实现了多台机器的管道共享。windows
# Configure item pipelines # See https://doc.scrapy.org/en/latest/topics/item-pipeline.html ITEM_PIPELINES = { # 'redisPro.pipelines.RedisproPipeline': 300, 'scrapy_redis.pipelines.RedisPipeline': 400, }
使用scrapy-redis组件中封装好的调度器,将全部的url存储到该指定的调度器中,从而实现了多台机器的调度器共享。
如下代码可在settings.py中任意位置粘贴:浏览器
# 使用scrapy-redis组件的去重队列 DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter" # 使用scrapy-redis组件本身的调度器 SCHEDULER = "scrapy_redis.scheduler.Scheduler" # 核心配置 # 是否容许暂停 SCHEDULER_PERSIST = True # 值为True表示:宕机恢复服务时,从宕机的那个地方开始爬取,不用从头开始
管道默认会链接且将数据存储到本机的redis服务中,若是想要链接存储到其余redis服务中须要在settings.py中进行以下配置bash
# 若是redis服务器不在本身本机,则须要作以下配置 REDIS_HOST = '192.168.31.31' # redis服务的ip地址 REDIS_PORT = 6379 # 可选配置 # REDIS_ENCODING = 'utf-8' # REDIS_PARAMS = {'password':'123456'}
# Crawl responsibly by identifying yourself (and your website) on the user-agent USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36' # 假装请求载体身份 # Obey robots.txt rules ROBOTSTXT_OBEY = False # 不听从门户网站robots协议,避免某些信息爬取不到
执行爬虫程序的方式与以前不一样。
格式:lpush 队列名称(redis-key) 起始url服务器
$ pwd /Users/hqs/ScrapyProjects/redisPro/redisPro/spiders $ scrapy runspider qiubai.py ....... 2018-12-08 12:04:34 [scrapy.extensions.telnet] DEBUG: Telnet console listening on 127.0.0.1:6023
而后须要在redis客户端中,将起始url扔到调度器队列中:框架
$ src/redis-cli 127.0.0.1:6379> lpush qiubaispider https://www.qiushibaike.com/pic/ # 将url扔入队列 (integer) 1
查看reids中保存的爬取数据:
127.0.0.1:6379> keys * 1) "qiubai:items" 2) "data" 3) "name" 4) "qiubai:dupefilter" 127.0.0.1:6379> lrange qiubai:items 0 -1 1) "{\"img_url\": \"https://pic.qiushibaike.com/system/pictures/12132/121326116/medium/FO4Z7Q83NXSOPYTL.jpg\"}" ......