之前用scrapy爬取了知乎用戶數(shù)據(jù)庄敛,由于數(shù)據(jù)量很大搀擂,便考慮采取分布式提升爬取效率,便有的此文。爬蟲(chóng)源碼為https://pan.baidu.com/s/1mCK8mosshkkb1Vx9sVDEGg桌粉,讀者自行下載,接下來(lái)進(jìn)入主題:
前期準(zhǔn)備:我們分別需要在主機(jī)和從機(jī)上配置好環(huán)境和所需要的軟件及安裝包衙四,具體如下:
?一铃肯、在主機(jī)上我們需要安裝好python,redis传蹈,mongodb押逼,VMware,Xshell惦界。
1挑格、其中VMware與Xshell是為搭建虛擬機(jī)服務(wù)的.
2、python需要安裝好scrapy沾歪,scrapy_redis漂彤,pymongo,scrapy_client灾搏,盡量安裝最新版本的挫望。
3、為了遠(yuǎn)程連接redis和mongodb狂窑,需要對(duì)redis和mongodb分別進(jìn)行設(shè)置媳板,由于在源碼中我把MongoPipeline關(guān)掉了,用不到mgogodb數(shù)據(jù)庫(kù)了泉哈,這里就以redis為例:找到redis安裝目錄下的redis.windows.conf 配置文件(如圖1)蛉幸,選擇相應(yīng)的工具打開(kāi),redis默認(rèn)bind localhost,找到bind 并修改為0.0.0.0(如圖2)。
當(dāng)你的電腦作為主機(jī)時(shí)需要時(shí)刻開(kāi)著redis服務(wù)旨巷,下面是打開(kāi)redis服務(wù)的配置
4巨缘、打開(kāi)cmd命令行 進(jìn)入redis的安裝目錄,輸入redis-server.exe redis.windows.conf 回車(chē)采呐。
如果出現(xiàn)bind:no error (在redis目錄下輸入redis-cli 回車(chē) 輸入shutdown 回車(chē) 輸入 exit退出)然后再重新輸入輸入redis-server.exe redis.windows.conf運(yùn)行服務(wù),出現(xiàn)圖3即證明運(yùn)行成功搁骑。
5斧吐、主機(jī)開(kāi)啟redis服務(wù)之后,不要斷開(kāi)仲器,切記C郝省!乏冀! 進(jìn)入redis安裝目錄蝶糯,輸入:redis-cli.exe -h 主機(jī)(或者別人的)ip地址(-p 端口號(hào)6379(可以不用寫(xiě)))用來(lái)測(cè)試是否可以遠(yuǎn)程連接redis(如果回車(chē)之后沒(méi)有出現(xiàn)如圖4效果,檢查自己的bind是否修改以及redis服務(wù)是否被自己關(guān)閉)出現(xiàn)如下表示可以遠(yuǎn)程連接redis辆沦。注意這里需要另開(kāi)一個(gè)cmd命令窗口昼捍。
mongdb的配置可以自行百度识虚,至此主機(jī)的配置算是初步完成。
二妒茬、虛擬機(jī)即從機(jī),我們需要安裝好python3担锤,scrapy,scrapyd
1乍钻、借助VMware軟件我在D盤(pán)建立了一個(gè)linux系統(tǒng)肛循,linux系統(tǒng)默認(rèn)安裝了python2,不滿足我的要求银择,于是手動(dòng)安裝python3多糠,這里需要注意不要?jiǎng)觩ython2,避免引起不必要的麻煩浩考。linux系統(tǒng)下安裝python3具體步驟如下:
(1)?安裝依賴(lài)環(huán)境
#yum install -y gcc
#yum install -y zlib*
#yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel
(2)下載Python3
# wget https://www.python.org/ftp/python/3.6.3/Python-3.6.3.tgz
注意這一步需要先安裝wget工具夹孔,命令如下 yum -y install wget
(3)解壓下載好的Python-3.x.x.tgz包
# tar -zxvf Python-3.6.3.tgz
(4)進(jìn)入解壓后的目錄,配置文件
# cd Python-3.6.3
# ./configure --prefix=/usr/local/python36 這里指定安裝目錄
(5)編譯與安裝
#make && make install
(6)創(chuàng)建新版本的軟連接怀挠。
修改舊版本 #mv /usr/bin/python /usr/bin/python_bak
創(chuàng)建新的軟連接 # ln -s /usr/local/python36/bin/python3 /usr/bin/python
創(chuàng)建一下pip3的軟鏈接 # ln -s /usr/local/python3/bin/pip3 /usr/bin/pip3
注意這里要注意自己安裝python的路徑析蝴,可以which python查看
至此linux下python3安裝完畢,可以輸入python看看效果
2绿淋、接著安裝scrapy與scrapyd
完成以上安裝python3的步驟之后闷畸,就可以直接通過(guò)pip安裝scrapy與scrapyd,
命令如下:pip3 install scrapy吞滞,pip3 install scrapyd
命令行輸入scrapyd佑菩,查看效果,scrapyd默認(rèn)開(kāi)啟127.0.0.1端口裁赠,我們需要修改配置殿漠,首先找到啟動(dòng)配置文件:
vi /usr/local/python36/lib/python3.6/site-packages/scrapyd/default_scrapyd.conf
這里的路徑不是絕對(duì)的,具體的是看你把scrapyd安裝在哪里了佩捞,你用虛擬環(huán)境安裝的就在虛擬虛擬環(huán)境的python下面绞幌,不知道的which python可以查看,搞就完了一忱!
修改目的:
修改該啟動(dòng)配置文件的目的是可以遠(yuǎn)程訪問(wèn)莲蜘,scrapyd框架分為server端和client端,兩個(gè)的ip地址必須對(duì)的上才能通信帘营;
(1)client端需要將代碼上傳到server端
(2)可以瀏覽器訪問(wèn)server端的gui管理界面票渠,世界各地沒(méi)毛病,前提是具有公網(wǎng)ip芬迄;
配置:
默認(rèn)scrapyd啟動(dòng)bind綁定的ip地址是127.0.0.1端口是:6800问顷,
將ip地址設(shè)置為0.0.0.0
打開(kāi)配置文件不需要翻頁(yè)就能夠找到bind_address
bind_address = 0.0.0.0
修改完成之后再次執(zhí)行scrapyd,會(huì)出現(xiàn)下圖所示
至此準(zhǔn)備工作完畢,接下來(lái)進(jìn)入爬蟲(chóng)的配置和部署工作杜窄。
三肠骆、知乎爬蟲(chóng)的配置與部署
1、首先是scrapy分布式爬蟲(chóng)原理的介紹
(1)關(guān)于Scrapy工作流程
scrapy單機(jī)架構(gòu)
上圖的架構(gòu)其實(shí)就是一種單機(jī)架構(gòu)羞芍,只在本機(jī)維護(hù)一個(gè)爬取隊(duì)列哗戈,Scheduler進(jìn)行調(diào)度,而要實(shí)現(xiàn)多態(tài)服務(wù)器共同爬取數(shù)據(jù)關(guān)鍵就是共享爬取隊(duì)列荷科。
分布式架構(gòu)
我將上圖進(jìn)行再次更改
(2)這里重要的就是我的隊(duì)列通過(guò)什么維護(hù)唯咬?
這里一般我們通過(guò)Redis為維護(hù),Redis是非關(guān)系型數(shù)據(jù)庫(kù)畏浆,Key-Value形式存儲(chǔ)胆胰,結(jié)構(gòu)靈活。并且redis是內(nèi)存中的數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)系統(tǒng)刻获,處理速度快蜀涨,提供隊(duì)列集合等多種存儲(chǔ)結(jié)構(gòu),方便隊(duì)列維護(hù)
(3)如何去重蝎毡?
這里借助redis的集合厚柳,redis提供集合數(shù)據(jù)結(jié)構(gòu),在redis集合中存儲(chǔ)每個(gè)request的指紋沐兵,在向request隊(duì)列中加入Request前先驗(yàn)證這個(gè)Request的指紋是否已經(jīng)加入集合中别垮。如果已經(jīng)存在則不添加到request隊(duì)列中,如果不存在扎谎,則將request加入到隊(duì)列并將指紋加入集合
(4)如何防止中斷碳想?如果某個(gè)slave因?yàn)樘厥庠蝈礄C(jī),如何解決毁靶?
這里是做了啟動(dòng)判斷胧奔,在每臺(tái)slave的Scrapy啟動(dòng)的時(shí)候都會(huì)判斷當(dāng)前redis request隊(duì)列是否為空,如果不為空预吆,則從隊(duì)列中獲取下一個(gè)request執(zhí)行爬取龙填。如果為空則重新開(kāi)始爬取,第一臺(tái)叢集執(zhí)行爬取向隊(duì)列中添加request
(5)如何實(shí)現(xiàn)上述這種架構(gòu)拐叉?
這里有一個(gè)scrapy-redis的庫(kù)觅够,為我們提供了上述的這些功能,scrapy-redis改寫(xiě)了Scrapy的調(diào)度器巷嚣,隊(duì)列等組件,利用他可以方便的實(shí)現(xiàn)Scrapy分布式架構(gòu)钳吟。關(guān)于scrapy-redis的地址:https://github.com/rmax/scrapy-redis廷粒。
2、搭建分布式爬蟲(chóng)
參考官網(wǎng)地址:https://scrapy-redis.readthedocs.io/en/stable/
前提是要安裝scrapy_redis模塊:pip install scrapy_redis
這里的爬蟲(chóng)代碼是用的之前寫(xiě)過(guò)的爬取知乎用戶信息的爬蟲(chóng)
(1)修改該settings中的配置信息:
替換scrapy調(diào)度器
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
添加去重的class
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
添加pipeline
如果添加這行配置,每次爬取的數(shù)據(jù)也都會(huì)入到redis數(shù)據(jù)庫(kù)中坝茎,所以一般這里不做這個(gè)配置
ITEM_PIPELINES = {'scrapy_redis.pipelines.RedisPipeline': 300}
共享的爬取隊(duì)列涤姊,這里用需要redis的連接信息,這里的user:pass表示用戶名和密碼嗤放,如果沒(méi)有則為空就可以 #REDIS_URL = 'redis://user:pass@hostname:6379'思喊,我由于沒(méi)設(shè)置用戶名與賬號(hào),就采取如下設(shè)置REDIS_HOST='192.168.16.243'次酌,REDIS_PORT=6379
SCHEDULER_PERSIST = True設(shè)置為為T(mén)rue則不會(huì)清空redis里的dupefilter和requests隊(duì)列恨课,這樣設(shè)置后指紋和請(qǐng)求隊(duì)列則會(huì)一直保存在redis數(shù)據(jù)庫(kù)中,默認(rèn)為False岳服,一般不進(jìn)行設(shè)置
SCHEDULER_FLUSH_ON_START=True設(shè)置重啟爬蟲(chóng)時(shí)是否清空爬取隊(duì)列剂公,這樣每次重啟爬蟲(chóng)都會(huì)清空指紋和請(qǐng)求隊(duì)列,一般設(shè)置為False
(2)Scrapy分布式部署
這個(gè)scrapyd的github地址:https://github.com/scrapy/scrapyd
當(dāng)在遠(yuǎn)程主機(jī)上安裝了scrapyd并啟動(dòng)之后,就會(huì)再遠(yuǎn)程主機(jī)上啟動(dòng)一個(gè)web服務(wù)吊宋,默認(rèn)是6800端口纲辽,這樣我們就可以通過(guò)http請(qǐng)求的方式,通過(guò)接口的方式管理我們scrapy項(xiàng)目璃搜,這樣就不需要在一個(gè)一個(gè)電腦連接拷貝過(guò)著通過(guò)git拖吼,關(guān)于scrapyd官方文檔地址http://scrapyd.readthedocs.io/en/stable/
這里我在linux虛擬機(jī)中已經(jīng)安裝scrapy以及scrapyd等包,保證所要運(yùn)行的爬蟲(chóng)需要的包都完成安裝这吻。
在這里有個(gè)小問(wèn)題需要注意吊档,默認(rèn)scrapyd啟動(dòng)是通過(guò)scrapyd就可以直接啟動(dòng),這里bind綁定的ip地址是127.0.0.1端口是:6800橘原,這里為了其他虛擬機(jī)訪問(wèn)講ip地址設(shè)置為0.0.0.0
scrapyd的配置文件:/usr/local/python36/lib/python3.6/sitepackages/scrapyd/default_scrapyd.conf
這樣我們就可以通過(guò)瀏覽器訪問(wèn):
3籍铁、關(guān)于部署
如何通過(guò)scrapyd部署項(xiàng)目,這里官方文檔提供一個(gè)地址:https://github.com/scrapy/scrapyd-client趾断,即通過(guò)scrapyd-client進(jìn)行操作
這里的scrapyd-client主要實(shí)現(xiàn)以下內(nèi)容:
把我們本地代碼打包生成egg文件
根據(jù)我們配置的url上傳到遠(yuǎn)程服務(wù)器上
我們將我們本地的scrapy項(xiàng)目中scrapy.cfg配置文件進(jìn)行配置:
我們其實(shí)還可以設(shè)置用戶名和密碼拒名,不過(guò)這里沒(méi)什么必要,只設(shè)置了url
這里設(shè)置url一定要注意:url = http://192.168.1.9:6800/addversion.json
最后的addversion.json不能少
已經(jīng)本地安裝好scrapy_client,直接執(zhí)行:scrapyd-deploy芋酌,得到如下表示即表明打包成功增显。
windows用戶需要注意,在windows上脐帝,pip install scrapyd-client 后同云。在cmd中運(yùn)行部署命令,scrapyd-deploy 如果提示:'scrapyd-deploy' 不是內(nèi)部或外部命令堵腹,也不是可運(yùn)行的程序或批處理文件炸站。可以通過(guò)如下步驟解決:
(1)進(jìn)到python安裝目錄下Scripts 文件里疚顷,創(chuàng)建兩個(gè)新文件:scrapy.bat旱易、scrapyd-deploy.bat禁偎,這里我的文件目錄為D:/python3.5.2/Scripts
(2)編輯兩個(gè)文件:
scrapy.bat文件中輸入以下內(nèi)容 :
@echo off
D:\Python3.5.2\python D:\Python3.5.2\Scripts\scrapy %*
scrapyd-deploy.bat 文件中輸入以下內(nèi)容:
@echo off
D:\Python33.5.2\python D:\Python3.5.2\Scripts\scrapyd-deploy %*
(3)保存退出,并確保你的 D:/python3.5.2和D:/python3.5.2/Scripts? 都在環(huán)境變量阀坏。這樣就可以正常運(yùn)行scrapy-deploy命令了如暖。
4、關(guān)于常用操作API
完成上述步驟忌堂,我們已經(jīng)虛擬機(jī)部署了一個(gè)爬蟲(chóng)項(xiàng)目盒至,現(xiàn)在要怎么操作呢?scrapy_client為我們提供了一個(gè)web接口用于調(diào)度爬蟲(chóng)項(xiàng)目士修,詳情可以查看scrapyd幫助文檔https://scrapyd.readthedocs.io/en/latest/api.html#cancel-json枷遂,這里簡(jiǎn)單舉個(gè)例子,如我們可以直接在pycharm的terminal端口直接執(zhí)行curl http://localhost:6800/listprojects.jsonlistprojects.json列出上傳的項(xiàng)目列表李命,本人在windows下直接運(yùn)行curl登淘,出現(xiàn)如下提示:
于是選擇在cmd命令端口中執(zhí)行curl命令,如圖所示
遠(yuǎn)程啟動(dòng)虛擬機(jī)上部署的爬蟲(chóng)封字,可以執(zhí)行以下命令
$ curl http://192.168.16.235:6800/schedule.json -d project=zhihuuser -d spider=zhihu黔州,其中project是項(xiàng)目名稱(chēng),spider是爬蟲(chóng)名稱(chēng)阔籽,執(zhí)行完畢返回下圖則說(shuō)明調(diào)度成功
我們可以通過(guò)查看scrapyd提供的web接口http://192.168.16.235:6800查看項(xiàng)目執(zhí)行情況
點(diǎn)擊上圖的log可以查看爬蟲(chóng)爬取情況流妻,再后面我們可以通過(guò)下面命令關(guān)閉爬蟲(chóng)任務(wù)。
curl http://192.168.16.235:6800/cancel.json -d project=zhihuuser -d job=b756ad6c006f11e984d3000c29f4ffc1,這里的job就是圖16里調(diào)度成功之后返回的jobid
執(zhí)行成功后同樣可以借助http://192.168.16.235:6800查看到任務(wù)已經(jīng)finish笆制。