python爬蟲學習筆記(二十九)-Scrapy 框架-分散式
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.分散式爬蟲的實現
-
使用三臺機器,一臺是win10,兩臺是centos6,分別在兩臺機器上部署scrapy來進行分散式抓取一個網站
-
win10的ip地址為192.168.31.245,用來作為redis的master端,centos的機器作為slave
-
master的爬蟲執行時會把提取到的url封裝成request放到redis中的資料庫:“dmoz:requests”,並且從該資料庫中提取request後下載網頁,再把網頁的內容存放到redis的另一個數據庫中“dmoz:items”
-
slave從master的redis中取出待抓取的request,下載完網頁之後就把網頁的內容傳送回master的redis
-
重複上面的3和4,直到master的redis中的“dmoz:requests”資料庫為空,再把master的redis中的“dmoz:items”資料庫寫入到mongodb中
-
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' #master IP
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)