天天看點

scrapy-redis分布式爬蟲的搭建過程(理論篇)scrapy-redis分布式爬蟲的搭建過程(理論篇)

scrapy-redis分布式爬蟲的搭建過程(理論篇)

1. 背景

  • Scrapy 是一個通用的爬蟲架構,但是不支援分布式,Scrapy-redis是為了更友善地實作Scrapy分布式爬取,而提供了一些以redis為基礎的元件(僅有元件)。

2. 環境

  • 系統:win7
  • scrapy-redis
  • redis 3.0.5
  • python 3.6.1

3. 原理

3.1. 對比一下scrapy 和 Scrapy-redis 的架構圖。

  • scrapy架構圖:
    scrapy-redis分布式爬蟲的搭建過程(理論篇)scrapy-redis分布式爬蟲的搭建過程(理論篇)
  • scrapy-redis 架構圖:
    scrapy-redis分布式爬蟲的搭建過程(理論篇)scrapy-redis分布式爬蟲的搭建過程(理論篇)
    • 多了一個redis元件,主要影響兩個地方:第一個是排程器。第二個是資料的處理。

3.2. Scrapy-Redis分布式政策。

scrapy-redis分布式爬蟲的搭建過程(理論篇)scrapy-redis分布式爬蟲的搭建過程(理論篇)
  • 作為一個分布式爬蟲,是需要有一個Master端(核心伺服器)的,在Master端,會搭建一個Redis資料庫,用來存儲start_urls、request、items。Master的職責是負責url指紋判重,Request的配置設定,以及資料的存儲(一般在Master端會安裝一個mongodb用來存儲redis中的items)。出了Master之外,還有一個角色就是slaver(爬蟲程式執行端),它主要負責執行爬蟲程式爬取資料,并将爬取過程中新的Request送出到Master的redis資料庫中。
  • 如上圖,假設我們有四台電腦:A, B, C, D ,其中任意一台電腦都可以作為 Master端 或 Slaver端。整個流程是:
    • 首先Slaver端從Master端拿任務(Request、url)進行資料抓取,Slaver抓取資料的同時,産生新任務的Request便送出給 Master 處理;
    • Master端隻有一個Redis資料庫,負責将未處理的Request去重和任務配置設定,将處理後的Request加入待爬隊列,并且存儲爬取的資料。
scrapy-redis分布式爬蟲的搭建過程(理論篇)scrapy-redis分布式爬蟲的搭建過程(理論篇)
scrapy-redis分布式爬蟲的搭建過程(理論篇)scrapy-redis分布式爬蟲的搭建過程(理論篇)
  • Scrapy-Redis預設使用的就是這種政策,我們實作起來很簡單,因為任務排程等工作Scrapy-Redis都已經幫我們做好了,我們隻需要繼承RedisSpider、指定redis_key就行了。
  • 缺點是,Scrapy-Redis排程的任務是Request對象,裡面資訊量比較大(不僅包含url,還有callback函數、headers等資訊),可能導緻的結果就是會降低爬蟲速度、而且會占用Redis大量的存儲空間,是以如果要保證效率,那麼就需要一定硬體水準。

4. 運作流程

  • 第一步:在slaver端的爬蟲中,指定好 redis_key,并指定好redis資料庫的位址,比如:
class MySpider(RedisSpider):
    """Spider that reads urls from redis queue (myspider:start_urls)."""
    name = 'amazon'
    redis_key = 'amazonCategory:start_urls'
           
# 指定redis資料庫的連接配接參數
'REDIS_HOST': '172.16.1.99',
'REDIS_PORT': ,
           
  • 第二步:啟動slaver端的爬蟲,爬蟲進入等待狀态,等待 redis 中出現 redis_key ,Log如下:
2017-12-12 15:54:18 [scrapy.utils.log] INFO: Scrapy 1.4.0 started (bot: scrapybot)
2017-12-12 15:54:18 [scrapy.utils.log] INFO: Overridden settings: {'SPIDER_LOADER_WARN_ONLY': True}
2017-12-12 15:54:18 [scrapy.middleware] INFO: Enabled extensions:
['scrapy.extensions.corestats.CoreStats',
 'scrapy.extensions.telnet.TelnetConsole',
 'scrapy.extensions.logstats.LogStats']
2017-12-12 15:54:18 [myspider_redis] INFO: Reading start URLs from redis key 'myspider:start_urls' (batch size: , encoding: utf-
-- :: [scrapy.middleware] INFO: Enabled downloader middlewares:
['scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware',
 'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware',
 'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware',
 'redisClawerSlaver.middlewares.ProxiesMiddleware',
 'redisClawerSlaver.middlewares.HeadersMiddleware',
 'scrapy.downloadermiddlewares.retry.RetryMiddleware',
 'scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware',
 'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware',
 'scrapy.downloadermiddlewares.redirect.RedirectMiddleware',
 'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware',
 'scrapy.downloadermiddlewares.stats.DownloaderStats']
-- :: [scrapy.middleware] INFO: Enabled spider middlewares:
['scrapy.spidermiddlewares.httperror.HttpErrorMiddleware',
 'scrapy.spidermiddlewares.offsite.OffsiteMiddleware',
 'scrapy.spidermiddlewares.referer.RefererMiddleware',
 'scrapy.spidermiddlewares.urllength.UrlLengthMiddleware',
 'scrapy.spidermiddlewares.depth.DepthMiddleware']
-- :: [scrapy.middleware] INFO: Enabled item pipelines:
['redisClawerSlaver.pipelines.ExamplePipeline',
 'scrapy_redis.pipelines.RedisPipeline']
-- :: [scrapy.core.engine] INFO: Spider opened
-- :: [scrapy.extensions.logstats] INFO: Crawled  pages (at  pages/min), scraped  items (at  items/min)
-- :: [scrapy.extensions.logstats] INFO: Crawled  pages (at  pages/min), scraped  items (at  items/min)
-- :: [scrapy.extensions.logstats] INFO: Crawled  pages (at  pages/min), scraped  items (at  items/min)
           
  • 第三步:啟動腳本,往redis資料庫中填入redis_key(start_urls)
#!/usr/bin/env python
# -*- coding:utf-8 -*-

import redis

# 将start_url 存儲到redis中的redis_key中,讓爬蟲去爬取
redis_Host = "172.16.1.99"
redis_key = 'amazonCategory:start_urls'

# 建立redis資料庫連接配接
rediscli = redis.Redis(host = redis_Host, port = , db = "0")

# 先将redis中的requests全部清空
flushdbRes = rediscli.flushdb()
print(f"flushdbRes = {flushdbRes}")
rediscli.lpush(redis_key, "https://www.baidu.com")
           
scrapy-redis分布式爬蟲的搭建過程(理論篇)scrapy-redis分布式爬蟲的搭建過程(理論篇)
  • 第四步:slaver端的爬蟲開始爬取資料。Log如下:
-- :: [scrapy.extensions.logstats] INFO: Crawled  pages (at  pages/min), scraped  items (at  items/min)
parse url = https://www.baidu.com, status = , meta = {'download_timeout': , 'proxy': 'http://proxy.abuyun.com:9020', 'download_slot': 'www.baidu.com', 'download_latency': , 'depth': }
parse url = https://www.baidu.com, status = , meta = {'download_timeout': , 'proxy': 'http://proxy.abuyun.com:9020', 'download_slot': 'www.baidu.com', 'download_latency': , 'depth': }
-- :: [scrapy.extensions.logstats] INFO: Crawled  pages (at  pages/min), scraped  items (at  items/min)
           
  • 第五步:啟動腳本,将redis中的items,轉儲到mongodb中。
這部分代碼,請參照:scrapy-redis分布式爬蟲的搭建過程(代碼篇)
           

5. 環境安裝以及代碼編寫

5.1. scrapy-redis環境安裝

pip install scrapy-redis
           
scrapy-redis分布式爬蟲的搭建過程(理論篇)scrapy-redis分布式爬蟲的搭建過程(理論篇)
scrapy-redis分布式爬蟲的搭建過程(理論篇)scrapy-redis分布式爬蟲的搭建過程(理論篇)
  • 代碼位置:後面可以進行修改定制。
    scrapy-redis分布式爬蟲的搭建過程(理論篇)scrapy-redis分布式爬蟲的搭建過程(理論篇)

5.2. scrapy-redis分布式爬蟲編寫

  • 第一步,下載下傳官網的示例代碼,位址:https://github.com/rmax/scrapy-redis (需要安裝過git)
scrapy-redis分布式爬蟲的搭建過程(理論篇)scrapy-redis分布式爬蟲的搭建過程(理論篇)
  • 官網提供了兩種示例代碼,分别繼承自 Spider + redis 和 CrawlSpider + redis
    scrapy-redis分布式爬蟲的搭建過程(理論篇)scrapy-redis分布式爬蟲的搭建過程(理論篇)
  • 第二步,根據官網提供的示例代碼進行修改。

繼續閱讀