十分鐘搞懂分散式爬蟲

python開發發表於2019-08-11

1.預備知識

今天我們們來扯一扯分散式程式爬蟲,對爬蟲有所瞭解的都知道分散式爬蟲這個東東,今天我們來搞懂一下分散式這個概念,從字面上看就是分開來佈置,確實如此它是可以分開來運作的。

分散式程式就是將程式分佈到多臺機器上去,充分利用每一臺機器來完成我們的爬蟲任務。分散式程式需要用到multiprocessing模板,multiprocessing模板不但支援多程式,它的managers子模組還支援把多程式分佈到多臺機器上。

我們可以寫一個服務程式作為排程者,然後將我們的爬蟲任務分佈給其他的多個程式當中去,我們依靠網路通訊來管理這些程式。

2.模擬一個分散式程式爬蟲

我們來模擬進行一個分散式程式的爬蟲吧,就比如我們需要抓取某個圖片網站的所有圖片,如果用我們的分散式程式的思想,我們會建立一個程式負責抓取圖片的連結地址,然後將這些連結地址存放到Queue中,另外的程式負責從Queue中讀取連結進行圖片的下載或者進行其他操作(存在本地).

其實我們的Queue是暴露在網路中的,通過分散式就是將其進行了封裝,其實也就是所謂的本地佇列的網路化。

接下來,我們來分析一下如何去建立一個分散式的服務程式,總體可以分為六步:

首先我們需要建立一個佇列queue,這個主要用作程式之間的通訊。總體來說就是兩種程式,一種是服務程式,一種是任務程式。服務程式建立任務佇列task_queue,用作傳遞任務給任務程式的通道。服務程式又建立result_queue,作為任務程式完成任務後回覆服務程式的通道。在分散式程式的環境下,我們需要通過Queuemanager 獲得的Queue介面來新增任務。

把我們在第一步中佇列在網路上進行註冊,暴露給其他的程式或者主機,註冊後獲得網路佇列,相當於本地佇列的映像。

建立Queuemanager的物件,並且例項化,繫結埠和口令

啟動第三步中建立的例項,即啟動管理manager,監管資訊通道

通過管理例項的方法獲取到通過網路訪問的queue物件,也就是把網路物件實體化成本地的一個佇列。

建立任務到“本地”佇列中,自動上傳任務到網路佇列中,分配給任務程式進行處理。

我們就來寫一下服務程式的程式碼 taskManager.py:

import queue

from multiprocessing.managers import BaseManager

from multiprocessing import freeze_support

任務個數

task_num = 500

定義收發佇列

task_queue = queue.Queue(task_num)

result_queue = queue.Queue(task_num)

def get_task():

return task_queue

def get_result():

return result_queue

建立類似的QueueManager

class QueueManager(BaseManager):

pass

def run():

Windows下繫結呼叫介面不能使用lambda,所以只能先定義函式再繫結

QueueManager.register('get_task_queue', callable = get_task)

QueueManager.register('get_result_queue', callable=get_result)

#繫結埠並設定驗證口令,windows下需要填寫ip地址,Linux中不填預設為本地

manager = QueueManager(address=('127.0.0.1', 8001), authkey='jap'.encode('utf-8'))

啟動

manager.start()

try:

通過網路獲取任務佇列和結果佇列

task = manager.get_task_queue()

result = manager.get_result_queue()

新增任務

for url in ["JAP君url:"+str(i) for i in range(500)]:

print("新增任務 %s" %url)

task.put(url)

print("正在獲取結果...")

for i in range(500):

print("result is %s" %result.get(timeout=10))

except:

print('Manager error')

finally:

一定要關閉,否則會報管道未關閉的錯

manager.shutdown()

if name == 'main':

windows下多程式可能會出現問題,新增這句話可以解決

freeze_support()

run()

上面就是我們的服務程式,我把解析都寫在了裡面,大家可以仔細看一下,接下來我們來寫任務程式(taskWorker),建立任務程式也比較簡單,只有簡單的四步:

  1. 建立一個類似的QueueManager物件,使用QueueManager註冊用於獲取queue的方法名稱,任務程式只能通過名稱來在網路上獲取queue,所以這裡一定要注意服務端和任務端的名稱要相同。

  2. 連結伺服器,埠和指令一定要與服務端相同

  3. 從網路上獲取queue,並且將其本地化。

  4. 從task對列中獲取任務,並且把結果寫入result對列。

import time

from multiprocessing.managers import BaseManager

建立類似的QueueManager

class QueueManager(BaseManager):

pass

第一步:使用QueueManager註冊用於獲取Queue的方法名稱

QueueManager.register('get_task_queue')

QueueManager.register('get_result_queue')

第二步:連結到伺服器

server_addr = '127.0.0.1'

print('Connect to server %s' %server_addr)

埠和驗證的口令一定要保證相同

m = QueueManager(address = (server_addr, 8001), authkey='jap'.encode('utf-8'))

從網路連線:

m.connect()

第三步:獲取queue的物件

task = m.get_task_queue()

result = m.get_result_queue()

第四步:從task佇列中獲取任務,並把結果寫入result佇列

while(not task.empty()):

url = task.get(True, timeout = 5)

print("run task download %s" %url)

time.sleep(1)

將結果寫入result佇列

result.put("%s --->success" %url)

print("exit")

詳細的步驟也寫在裡面了,當然這個任務佇列,我們是可以建立多個的,每個任務程式都會完成自己的事,而不會干擾其他的任務程式,這也就讓我們的url不會重複的去爬取,從而完美的實現了多個程式來爬取我們的任務。

以上就是一個非常簡單的分散式程式的爬蟲小案例,大家可以通過這種方式去實戰自己的一個小專案,在這裡還說一下,我們是可以將我們的任務分佈到多臺機器上的,這樣我們就實現了大規模的爬取。

以上就是小編今天為大家帶來的一些Python常用的爬蟲程式碼。

在學習中有迷茫不知如何學習的朋友小編推薦一個學Python的學習q u n 315 -346- 913可以來了解一起進步一起學習!免費分享視訊資料

轉自JAP君

相關文章