運用 Redis 構建分散式爬蟲,抓妹子圖
(點擊
上方公眾號
,可快速關注)
來源: Python開發者 - 路易十四
http://python.jobbole.com/86328/
當你能夠針對一個url進行請求,獲取數據,繼續請求的時候,說明你的爬蟲已經可以自給自足的爬起來。但是這樣的爬蟲其效率將會嚴重限制在單進程效率極限之下,時間的主要消耗還是在請求返回的等待時間,如果想進一步提高效率那麼多進程以及分散式就會你提高效率的最好手段。而且分散式並不意味著你一定要很多台電腦,只要你在本機測試通過一樣可以方便遷移。構建分散式爬蟲主要是構建分散式環境,至於寫爬蟲並不複雜。咱們一步步來。
小怪獸鎮樓
目錄:
redis簡介
安裝測試
多機測試
scrapy_redis
簡單應用測試
多機協作的redis
1.redis簡介:
redis是一個key-value存儲系統,速度很快因為將數據存放在內存,在必要時可以轉到硬碟。支持數據類型有string,lists,sets,zsets。這些數據類型都支持push/pop,add/remove以及取交集並集差集等操作,對這些操作都是原子性的,redis還支持各種不同的排序能力。
redis本身屬於一個資料庫類型的系統,不過在分散式中反而是他的隊列性特別好用,就被開發成分散式的基石。所以今天我們測試的內容就是在多台機器上安裝redis,然後讓一台作為伺服器別的機器開啟客戶端共享隊列。
2.安裝測試:
我就不搬磚了。下面的鏈接非常詳細(重點博文):
http://blog.fens.me/linux-redis-install/
還有redis有大量的命令,詳細可以查詢此處
http://www.3fwork.com/b902/001557MYM005172/
還有修改配置打開遠程訪問之類的
http://www.ttlsa.com/redis/install-redis-on-ubuntu/
3.多機測試:
使用你的伺服器(有遠程伺服器最好,沒有的話也可以在自己本機安裝),按照上面安裝好環境後,先去除保護的開啟伺服器端(未來長久使用要改配置)
如果報錯,請直接改配值,將127.0.0.1注釋掉(系統的防火牆要關)
redis-server --protected-mode no
然後先再開一個終端鏈接到伺服器,在伺服器本機的環境也開一個客戶端,(只是因為機器不多)
redis-cli -h ip地址 -p 6379
回車之後會看到進入一個交互命令行界面。
首先增加一個key對應的value
set key1 lala
其次查看這個值
get key1
然後返回你的個人電腦,也通過客戶端鏈接過去然後查看這個值
get key1
如果出現同樣的lala。那麼說明分散式的環境已經搭建好了。
4.scrapy_redis
這個是如何運行的請看這裡:
https://www.zhihu.com/question/32302268/answer/55724369
本次的測試項目就是運用了一個共享隊列而已,還沒有增加別的多種功能。
因為scrapy——redis使用起來需要環境配置的比較麻煩,還得改寫其中中間件,想進一步學習在scrapy中用redis可以再找文章。
5.簡單應用測試,分散式抓妹子圖網
一般而言分散式至少需要兩個程序:完整代碼我放在github上:https://github.com/luyishisi/WebCrawlers/tree/master/request
一個用於捕捉待爬隊列,並且加入到隊列。如果待爬隊列可以通過一定的規律算出來則可以輕鬆直接push到隊列中
另外一個則是讀取待爬隊列進行新一輪的爬取工作
要實現捕捉待爬隊列並且加入見下代碼:
1:頭文件:
requets用於發請求,re正則匹配,time控制速度,redis分散式。headers用於簡單的反反爬
import
requests
import
re
import
time
from
redis
import
Redis
headers
=
{
"User-Agent"
:
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36"
}
2:加任務隊列
計算並發送請求獲取根頁面的html從中匹配到img的地址發送到本地redis中。
def
push_redis_list
()
:
r
=
Redis
()
r
.
keys
(
"*"
)
for
i
in
range
(
100
)
:
num
=
5100
+
i
;
#抓取的取件僅在5100--5200之間
url
=
"http://www.meizitu.com/a/"
+
str
(
num
)
+
".html"
img_url
=
requests
.
get
(
url
,
timeout
=
30
)
#print img_url.text
#time.sleep(10)
img_url_list
=
re
.
findall
(
"http://pic.meizitu.com/wp-content/uploads/201.*.jpg"
,
img_url
.
text
)
img_url
_
list
for
temp_img_url
in
img_url_list
:
l
=
len
(
re
.
findall
(
"limg"
,
temp_img_url
))
#print l
if
(
l
==
0
)
:
"url: "
,
temp_img
_
url
r
.
lpush
(
"meizitu"
,
temp_img_url
)
r
.
llen
(
"meizitu"
)
return
0
3:讀任務隊列
def
get_big_img_url
()
:
r
=
Redis
()
r
.
keys
(
"*"
)
while
(
1
)
:
try
:
url
=
r
.
lpop
(
"meizitu"
)
download
(
url
)
time
.
sleep
(
1
)
url
except
:
"請求求發送失敗重試"
time
.
sleep
(
10
)
continue
return
0
4:download函數用於下載
def
download
(
url
)
:
try
:
r
=
requests
.
get
(
url
,
headers
=
headers
,
timeout
=
50
)
name
=
int
(
time
.
time
())
f
=
open
(
"./pic/"
+
str
(
name
)
+
".jpg"
,
"wb"
)
f
.
write
(
r
.
content
)
f
.
close
()
except
Exception
,
e
:
Exception
,
":"
,
e
5:main
開一個客戶端運行push_redis_list 函數,別的可以開啟任意多個客戶端運行get_big_img_url 函數,則簡單的分散式就構建完成
if
__name__
==
"__main__"
:
url
=
"http://www.meizitu.com/a/list_1_"
"begin"
#push_redis_list(5100)#開啟則加任務隊列.其中的值請限制在5400以內。不過是用於計算頁碼的
#get_big_img_url(//img.ifuun.com/getimg.php?url=)#開啟則運行爬取任務
運行的過程中你可以看一下該文件夾下是否有一個pic的文件夾,所有圖片存儲其中。
運行截圖:圖一加入任務隊列
圖二:單個客戶端進行讀取任務隊列進行爬取
圖三:截個圖,比較模糊應該不會查水表吧。
6:多機協作的redis
要開啟多機合作的redis分散式,也並不困難,最好將redis伺服器放置在某伺服器上,有固定ip。同時設定好安全密碼或者固定的ip白名單,redis直接開放很容易被黑了。
然後修改代碼建立redis連接的部分,。如下:
r=Redis(host=REDIS_HOST, port=REDIS_PORT,password=PASSWORD)
然後便是依舊一樣的使用。
看完本文有收穫?請轉
發分享給更多人
關注「P
ython開發者」,提升Python技能
※一篇文章教你如何用 Python 記錄日誌
※恭喜 Python,基本是各年齡段開發者的最愛!
TAG:Python開發者 |