繼上篇我們談論了Celery的基本知識後,本篇繼續講解如何一步步使用Celery構建分散式爬蟲。這次我們抓取的物件定為celery官方文件。
首先,我們新建目錄distributedspider
,然後再在其中新建檔案workers.py
,裡面內容如下
1 2 3 4 5 6 7 8 9 10 |
from celery import Celery app = Celery('crawl_task', include=['tasks'], broker='redis://223.129.0.190:6379/1', backend='redis://223.129.0.190:6379/2') # 官方推薦使用json作為訊息序列化方式 app.conf.update( CELERY_TIMEZONE='Asia/Shanghai', CELERY_ENABLE_UTC=True, CELERY_ACCEPT_CONTENT=['json'], CELERY_TASK_SERIALIZER='json', CELERY_RESULT_SERIALIZER='json', ) |
上述程式碼主要是做Celery例項的初始化工作,include
是在初始化celery app的時候需要引入的內容,主要就是註冊為網路呼叫的函式所在的檔案。然後我們再編寫任務函式,新建檔案tasks.py
,內容如下
1 2 3 4 5 6 7 8 9 |
import requests from bs4 import BeautifulSoup from workers import app @app.task def crawl(url): print('正在抓取連結{}'.format(url)) resp_text = requests.get(url).text soup = BeautifulSoup(resp_text, 'html.parser') return soup.find('h1').text |
它的作用很簡單,就是抓取指定的url,並且把標籤為h1
的元素提取出來
最後,我們新建檔案task_dispatcher.py
,內容如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
from workers import app url_list = [ 'http://docs.celeryproject.org/en/latest/getting-started/introduction.html', 'http://docs.celeryproject.org/en/latest/getting-started/brokers/index.html', 'http://docs.celeryproject.org/en/latest/getting-started/first-steps-with-celery.html', 'http://docs.celeryproject.org/en/latest/getting-started/next-steps.html', 'http://docs.celeryproject.org/en/latest/getting-started/resources.html', 'http://docs.celeryproject.org/en/latest/userguide/application.html', 'http://docs.celeryproject.org/en/latest/userguide/tasks.html', 'http://docs.celeryproject.org/en/latest/userguide/canvas.html', 'http://docs.celeryproject.org/en/latest/userguide/workers.html', 'http://docs.celeryproject.org/en/latest/userguide/daemonizing.html', 'http://docs.celeryproject.org/en/latest/userguide/periodic-tasks.html' ] def manage_crawl_task(urls): for url in urls: app.send_task('tasks.crawl', args=(url,)) if __name__ == '__main__': manage_crawl_task(url_list) |
這段程式碼的作用主要就是給worker傳送任務,任務是tasks.crawl
,引數是url
(元祖的形式)
現在,讓我們在節點A(hostname為resolvewang的主機)上啟動worker
1 |
celery -A workers worker -c 2 -l info |
這裡 -c
指定了執行緒數為2, -l
表示日誌等級是info
。我們把程式碼拷貝到節點B(節點名為wpm的主機),同樣以相同命令啟動worker,便可以看到以下輸出
可以看到左邊節點(A)先是all alone
,表示只有一個節點;後來再節點B啟動後,它便和B同步了
1 |
sync with celery@wpm |
這個時候,我們執行給這兩個worker節點傳送抓取任務
1 |
python task_dispatcher.py |
可以看到如下輸出
可以看到兩個節點都在執行抓取任務,並且它們的任務不會重複。我們再在redis裡看看結果
可以看到一共有11條結果,說明 tasks.crawl
中返回的資料都在db2(backend)中了,並且以json的形式儲存了起來,除了返回的結果,還有執行是否成功等資訊。
到此,我們就實現了一個很基礎的分散式網路爬蟲,但是它還不具有很好的擴充套件性,而且貌似太簡單了…下一篇我將以微博資料採集為例來演示如何構建一個穩健的分散式網路爬蟲。
對微博大規模資料採集感興趣的同學可以關注一下分散式微博爬蟲,用用也是極好的