【Python3爬蟲】學習分佈式爬蟲第一步--Redis分佈式爬蟲初體驗

1、寫在前面

  以前寫的爬蟲都是單機爬蟲,尚未嘗試過度布式爬蟲,此次就是一個分佈式爬蟲的初體驗。所謂分佈式爬蟲,就是要用多臺電腦同時爬取數據,相比於單機爬蟲,分佈式爬蟲的爬取速度更快,也能更好地應對IP的檢測。本文介紹的是利用Redis數據庫實現的分佈式爬蟲,Redis是一種經常使用的菲關係型數據庫,經常使用數據類型包括String、Hash、Set、List和Sorted Set,重要的是Redis支持主從複製,主機能將數據同步到從機,也就可以實現讀寫分離。所以咱們能夠利用Redis的特性,藉助requests模塊發送請求,再解析網頁和提取數據,實現一個簡單的分佈式爬蟲。html

 

2、基本環境

  Python版本:Python3git

  Redis版本:5.0github

  IDE: Pycharmredis

 

3、環境配置

因爲Windows下的安裝配置比較簡單,因此這裏只說Linux環境下安裝和配置Redis(以Ubuntu爲例)。數據庫

1.安裝Redis

1)apt安裝:dom

$ sudo apt-get install redis-server分佈式

2)編譯安裝:ide

$ wget http://download.redis.io/releases/redis-5.0.0.tar.gz網站

$ tar -xzvf redis-5.0.0.tar.gzurl

$ cd redis-5.0.0

$ make

$ make install

 

2.配置Redis

  首先找到redis.conf文件,而後輸入命令sudo vi redis.conf,進行以下操做:

註釋掉bind 127.0.0.1 # 爲了遠程鏈接,這一步還能夠將bind 127.0.0.1改成bind 0.0.0.0

protected-mode yes 改成 protected-mode no 

daemonized no 改成 daemonized yes 

  若是6379端口被佔用,還須要改一下端口號。除此以外,要遠程鏈接還須要關閉防火牆。

chkconfig firewalld off  # 關閉防火牆

systemctl status firewalld  # 檢查防火牆狀態

3.遠程鏈接Redis

  使用的命令爲redis-cli -h <IP地址> -p <端口號>

  注:Windows查看IP地址用ipconfig,Linux查看IP地址用ifconfig。

 

4、基本思路

   此次我爬取的網站爲:http://www.shu800.com/,在這個網站的首頁裏有五大分類,分別是性感美女、清純可愛、明星模特、動漫美女和絲襪美腿,因此要作的第一件事就是獲取這幾個分類的URL。而後,對每一個分類下的網頁進行爬取,經過查看網頁元素能夠發現以下信息:

  能夠很明顯地看到每一頁的URL都是符合必定規律的,只要獲取到了尾頁的URL,將其中的頁數提取出來,也就能構造每一頁的URL了,這就比每次去獲取下一頁的URL簡單多了。而對於每個圖集下的圖片,也是用一樣的方法獲得每一頁圖片的URL。最後要作的就是從圖片網頁中將圖片的URL提取出來,而後下載保存到本地。

  此次分佈式爬蟲我使用了兩臺電腦,一臺做爲主機master,另外一臺做爲從機slave。主機開啓Redis服務,爬取每一頁圖片的URL,並將爬取到的URL保存到Redis的集合中,從機遠程鏈接主機的Redis,監聽Redis中是否有URL,若是有URL則提取出來進行下載圖片,直至全部URL都被提取和下載。

 

5、主要代碼

 1.第一段代碼是爬取每一個頁面裏的美女圖集的URL,而且把這些URL保存到數據庫中,這裏使用的是Redis中的集合,經過使用集合可以達到URL去重的目的,代碼以下:

 1 def get_page(url):
 2     """
 3     爬取每一個頁面下的美女圖集的URL
 4     :param url: 頁面URL
 5     :return:
 6     """
 7     try: 8 r = Redis(host="localhost", port=6379, db=1) # 鏈接Redis 9  time.sleep(random.random()) 10 res = requests.get(url, headers=headers) 11 res.encoding = "utf-8" 12 et = etree.HTML(res.text) 13 href_list = et.xpath('/html/body/div[5]/div[1]/div[1]/div[2]/ul/li/a/@href') 14 for href in href_list: 15 href = "http://www.shu800.com" + href 16 r.sadd("href", href) # 保存到數據庫中 17 except requests.exceptions: 18 headers["User-Agent"] = ua.random 19 get_page(url)

2.第二段代碼是從機監聽Redis中是否有URL的代碼,若是沒有URL,等待五秒鐘再運行,由於若是不稍做等待就直接運行,很容易超過Python的遞歸深度,因此我設置了一個等待五秒鐘再運行。反之,若是有URL被添加到Redis中,就要將URL提取出來進行爬取,使用的方法是redis模塊裏的spop()方法,該方法會從Redis的集合中返回一個元素。須要注意的是,URL被提取出來後要先轉成str。

 1 def get_urls():
 2     """
 3     監聽Redis中是否有URL,若是沒有就一直運行,若是有就提取出來進行爬取
 4     :return: 
 5     """
 6     if b"href" in r.keys(): 7 while True: 8 try: 9 url = r.spop("href") 10 url = url.decode("utf-8") # unicode轉str 11 print("Crawling URL: ", url) 12  get_image(url) 13  get_img_page(url) 14 except: 15 if b"href" not in r.keys(): # 爬取結束,退出程序 16 break 17 else: 18 continue 19 else: 20 time.sleep(5) 21 get_urls()

 

 

6、運行結果

  下圖是在主機master上運行的截圖,這裏爬取到的圖集總共有9633個:

   從機slave會不斷地從Redis數據庫中提取URL來爬取,下圖是運行時的截圖:

  打開文件夾看看爬下來的圖片都有什麼(都是這種標題,有點難頂啊...):

 

完整代碼已上傳到GitHub

相關文章
相關標籤/搜索