python 爬蟲分布式 scrapy-redis
使用CentOS6 標準版系統(Linux系統下安裝)
因為CentOS默認是python2
-
安裝 python3
-
安裝裝python3的環境
yum install -y gcc,zlib*,openssl*
-
解壓壓縮包 tar -xf python3.6.1.tar
(參考Linux安裝python3)
-
-
安裝scrapy
- 安裝裝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
- 安裝scrapy
pip3.6 install scrapy
-
安裝 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.分布式爬蟲的實現
-
使用三臺機器,一臺是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‘
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