1. 程式人生 > >python 爬蟲分布式 scrapy-redis

python 爬蟲分布式 scrapy-redis

-s ber 環境 redis-cli 一個數 proc 哈希函數 問題 安裝

使用CentOS6 標準版系統(Linux系統下安裝)

因為CentOS默認是python2

  1. 安裝 python3

    1. 安裝裝python3的環境

      yum install -y gcc,zlib*,openssl*
      
    2. 解壓壓縮包 tar -xf python3.6.1.tar

      (參考Linux安裝python3)

  2. 安裝scrapy

    1. 安裝裝scrapy的環境
        yum install -y wget
        wget https://twistedmatrix.com/Releases/Twisted/17.1/Twisted-17.1.0.tar.bz2
        
        tar -jxvf Twisted-17.1.0.tar.bz2  
        cd Twisted-17.1.0  
        python3 setup.py install
        
    
    1. 安裝scrapy
    pip3.6 install scrapy
    
  3. 安裝 scrapy-redis

    pip3.6 install scrapy-redis

1. 介紹scrapy-redis框架

scrapy-redis

一個三方的基於redis的分布式爬蟲框架,配合scrapy使用,讓爬蟲具有了分布式爬取的功能。

github地址: https://github.com/darkrho/scrapy-redis

2. 分布式原理

scrapy-redis實現分布式,其實從原理上來說很簡單,這裏為描述方便,我們把自己的核心服務器稱為master,而把用於跑爬蟲程序的機器稱為slave

我們知道,采用scrapy框架抓取網頁,我們需要首先給定它一些start_urls,爬蟲首先訪問start_urls裏面的url,再根據我們的具體邏輯,對裏面的元素、或者是其他的二級、三級頁面進行抓取。而要實現分布式,我們只需要在這個starts_urls裏面做文章就行了

我們在master上搭建一個redis數據庫`(註意這個數據庫只用作url的存儲),並對每一個需要爬取的網站類型,都開辟一個單獨的列表字段。通過設置slave上scrapy-redis獲取url的地址為master地址。這樣的結果就是,盡管有多個slave,然而大家獲取url的地方只有一個,那就是服務器master上的redis數據庫

並且,由於scrapy-redis自身的隊列機制,slave獲取的鏈接不會相互沖突。這樣各個slave在完成抓取任務之後,再把獲取的結果匯總到服務器上

好處

程序移植性強,只要處理好路徑問題,把slave上的程序移植到另一臺機器上運行,基本上就是復制粘貼的事情

3.分布式爬蟲的實現

  1. 使用三臺機器,一臺是win10,兩臺是centos6,分別在兩臺機器上部署scrapy來進行分布式抓取一個網站

  2. win10的ip地址為192.168.31.245,用來作為redis的master端,centos的機器作為slave

  3. master的爬蟲運行時會把提取到的url封裝成request放到redis中的數據庫:“dmoz:requests”,並且從該數據庫中提取request後下載網頁,再把網頁的內容存放到redis的另一個數據庫中“dmoz:items”

  4. slave從master的redis中取出待抓取的request,下載完網頁之後就把網頁的內容發送回master的redis

  5. 重復上面的3和4,直到master的redis中的“dmoz:requests”數據庫為空,再把master的redis中的“dmoz:items”數據庫寫入到mongodb中

  6. master裏的reids還有一個數據“dmoz:dupefilter”是用來存儲抓取過的url的指紋(使用哈希函數將url運算後的結果),是防止重復抓取的

4. scrapy-redis框架的安裝

pip install scrapy-redis

5. 部署scrapy-redis

5.1 slave端

在windows上的settings.py文件的最後增加如下一行

REDIS_HOST = ‘localhost‘

REDIS_PORT = 6379

配置好了遠程的redis地址後啟動兩個爬蟲(啟動爬蟲沒有順序限制)

6 給爬蟲增加配置信息

DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
SCHEDULER_PERSIST = True
#SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderPriorityQueue"
#SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderQueue"
#SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderStack"

ITEM_PIPELINES = {
    ‘example.pipelines.ExamplePipeline‘: 300,
    ‘scrapy_redis.pipelines.RedisPipeline‘: 400,
}

7 運行程序

7.1 運行slave

scrapy runspider 文件名.py

開起沒有先後順序

7.2 運行master

lpush (redis_key)  url #括號不用寫

說明

  • 這個命令是在redis-cli中運行
  • redis_key 是 spider.py文件中的redis_key的值
  • url 開始爬取地址,不加雙引號

8 數據導入到mongodb中

等到爬蟲結束後,如果要把數據存儲到mongodb中,就應該修改master端process_items.py文件,如下

import redis

import pymongo

def main():

    r = redis.Redis(host=‘192.168.31.245‘,port=6379,db=0)

    client = pymongo.MongoClient(host=‘localhost‘, port=27017)

    db = client.dmoz

    sheet = db.sheet

    while True:


        source, data = r.blpop(["dmoz:items"])

        item = json.loads(data)

        sheet.insert(item)

if __name__ == ‘__main__‘:

    main()

9 數據導入到MySQL中

等到爬蟲結束後,如果要把數據存儲到mongodb中,就應該修改master端process_items.py文件,如下

import redis
import pymysql
import json
def process_item():
    r_client = redis.Redis(host="127.0.0.1",port=6379,db =0)
    m_client = pymysql.connect(host="127.0.0.1",port=3306,user="root",passowrd="123456",db="lianjia")
    source,data =r_client.blpop("lianjia:item")
    item = json.loads(data)

    cursor = m_client.cursor()
    values = []
    cursor.execute(sql,values)

python 爬蟲分布式 scrapy-redis