分佈式爬蟲概念:多臺機器上執行同一個爬蟲程序,實現網站數據的分佈爬取。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\"}" ......