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),建立任務程式也比較簡單,只有簡單的四步:
-
建立一個類似的QueueManager物件,使用QueueManager註冊用於獲取queue的方法名稱,任務程式只能通過名稱來在網路上獲取queue,所以這裡一定要注意服務端和任務端的名稱要相同。
-
連結伺服器,埠和指令一定要與服務端相同
-
從網路上獲取queue,並且將其本地化。
-
從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君