celery是一個基於分佈式消息傳輸的異步任務隊列,它專一於實時處理,同時也支持任務調度。關於celery的更多介紹及例子,筆者能夠參考文章Python之celery的簡介與使用。
本文將介紹如何使用celery來加速爬蟲。
本文爬蟲的例子來自文章:Python爬蟲的N種姿式。這裏再也不過多介紹,咱們的項目結構以下:php
其中,app_test.py爲主程序,其代碼以下:html
from celery import Celery app = Celery('proj', include=['proj.tasks']) app.config_from_object('proj.celeryconfig') if __name__ == '__main__': app.start()
tasks.py爲任務函數,代碼以下:python
import re import requests from celery import group from proj.app_test import app @app.task(trail=True) # 並行調用任務 def get_content(urls): return group(C.s(url) for url in urls)() @app.task(trail=True) def C(url): return parser.delay(url) @app.task(trail=True) # 獲取每一個網頁的name和description def parser(url): req = requests.get(url) html = req.text try: name = re.findall(r'<span class="wikibase-title-label">(.+?)</span>', html)[0] desc = re.findall(r'<span class="wikibase-descriptionview-text">(.+?)</span>', html)[0] if name is not None and desc is not None: return name, desc except Exception as err: return '', ''
celeryconfig.py爲celery的配置文件,代碼以下:web
BROKER_URL = 'redis://localhost' # 使用Redis做爲消息代理 CELERY_RESULT_BACKEND = 'redis://localhost:6379/0' # 把任務結果存在了Redis CELERY_TASK_SERIALIZER = 'msgpack' # 任務序列化和反序列化使用msgpack方案 CELERY_RESULT_SERIALIZER = 'json' # 讀取任務結果通常性能要求不高,因此使用了可讀性更好的JSON CELERY_TASK_RESULT_EXPIRES = 60 * 60 * 24 # 任務過時時間 CELERY_ACCEPT_CONTENT = ['json', 'msgpack'] # 指定接受的內容類型
最後是咱們的爬蟲文件,scrapy.py,代碼以下:redis
import time import requests from bs4 import BeautifulSoup from proj.tasks import get_content t1 = time.time() url = "http://www.wikidata.org/w/index.php?title=Special:WhatLinksHere/Q5&limit=500&from=0" # 請求頭部 headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, \ like Gecko) Chrome/67.0.3396.87 Safari/537.36'} # 發送HTTP請求 req = requests.get(url, headers=headers) # 解析網頁 soup = BeautifulSoup(req.text, "lxml") # 找到name和Description所在的記錄 human_list = soup.find(id='mw-whatlinkshere-list')('li') urls = [] # 獲取網址 for human in human_list: url = human.find('a')['href'] urls.append('https://www.wikidata.org'+url) #print(urls) # 調用get_content函數,並獲取爬蟲結果 result = get_content.delay(urls) res = [v for v in result.collect()] for r in res: if isinstance(r[1], list) and isinstance(r[1][0], str): print(r[1]) t2 = time.time() # 結束時間 print('耗時:%s' % (t2 - t1))
在後臺啓動redis,並切換至proj項目所在目錄,運行命令:算法
celery -A proj.app_test worker -l info
輸出結果以下(只顯示最後幾行的輸出):json
...... ['Antoine de Saint-Exupery', 'French writer and aviator'] ['', ''] ['Sir John Barrow, 1st Baronet', 'English statesman'] ['Amy Johnson', 'pioneering English aviator'] ['Mike Oldfield', 'English musician, multi-instrumentalist'] ['Willoughby Newton', 'politician from Virginia, USA'] ['Mack Wilberg', 'American conductor'] 耗時:80.05160284042358
在rdm中查看數據,以下:微信
在文章Python爬蟲的N種姿式中,咱們已經知道,若是用通常的方法來實現這個爬蟲,耗時大約爲725秒,而咱們使用celery,一共耗時約80秒,大概至關於通常方法的九分之一。雖然沒有scrapy這個爬蟲框架和異步框架aiohttp, asyncio來的快,但這也能夠做爲一種爬蟲的思路。
本次分享到此結束,感謝閱讀~
注意:本人現已開通微信公衆號: Python爬蟲與算法(微信號爲:easy_web_scrape), 歡迎你們關注哦~~app