Scrapy框架之分佈式操做

1、分佈式爬蟲介紹

  分佈式爬蟲概念:多臺機器上執行同一個爬蟲程序,實現網站數據的分佈爬取。html

一、原生的Scrapy沒法實現分佈式爬蟲的緣由?

  • 調度器沒法在多臺機器間共享:由於多臺機器上部署的scrapy會各自擁有各自的調度器,這樣就使得多臺機器沒法分配start_urls列表中的url。
  • 管道沒法給多臺機器共享:多臺機器爬取到的數據沒法經過同一個管道對數據進行統一的數據持久出存儲。

二、scrapy-redis組件

  scrapy-redis是專門爲scrapy框架開發的一套組件。該組件能夠解決上述兩個問題,讓Scrapy實現分佈式。
  組件安裝:python

$ pip3 intall scrapy-redis

2、基於RedisCrawlSpider的分佈式爬取

一、redis配置和啓動

(1)對redis配置文件redis.conf進行配置

  • 註釋該行:bind 127.0.0.1,表示可讓其餘ip訪問redis
  • 將yes該爲no:protected-mode no,表示可讓其餘ip操做redis
# 不註釋時,只容許本機的客戶端鏈接
# bind 127.0.0.1

# yes改成no,關閉redis的保護模式,客戶端能夠對服務器進行讀寫操做
protected-mode  no

(2)基於配置文件開啓redis服務器

# 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

(1)引入scrapy-redis中的模塊

  在爬蟲文件中要導入RedisCrawlSpider類,而後將爬蟲文件修改爲基於該類的源文件。redis

from scrapy_redis.spiders import RedisCrawlSpider

# class QiubaiSpider(CrawlSpider):
class QiubaiSpider(RedisCrawlSpider):

(2)聲明redis_key屬性

  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同樣

(3)連接提取器和規則解析器定義

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),
    )

(4)items.py編寫和爬蟲引入調用

import scrapy

class RedisproItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    img_url =scrapy.Field()

四、settings.py配置修改

(1)使用scrapy-redis組件中封裝好的管道

  使用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,
}

(2)使用scrapy-redis組件中封裝好的調度器

  使用scrapy-redis組件中封裝好的調度器,將全部的url存儲到該指定的調度器中,從而實現了多臺機器的調度器共享。
  如下代碼可在settings.py中任意位置粘貼:瀏覽器

# 使用scrapy-redis組件的去重隊列
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
# 使用scrapy-redis組件本身的調度器
SCHEDULER = "scrapy_redis.scheduler.Scheduler"   # 核心配置
# 是否容許暫停
SCHEDULER_PERSIST = True   # 值爲True表示:宕機恢復服務時,從宕機的那個地方開始爬取,不用從頭開始

(3)爬蟲程序不在redis本機時,指定redis地址

  管道默認會鏈接且將數據存儲到本機的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'}

(4)修改ua和關閉robots協議

# 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\"}"
   ......
相關文章
相關標籤/搜索