接到一個爬蟲任務,項目比較巨大,原來想用 Requests 配合正則作爬蟲。後來得知了 pyspider 這個神器,才知道以前的想法 low 爆了。pyspider GitHubcss
按照 GitHub 上的安裝教程安裝好之後,咱們就能夠經過 pyspider 命令來啓動這個神器,而後在瀏覽器中打開 http://localhost:5000/ 就能夠看到界面了。首先是一個 Dashboard,咱們在這裏能夠建立爬蟲項目,點擊 Create 而後輸入項目名就能夠看到代碼了。html
關於項目的幫助能夠看文檔,在 GitHub 上能夠找到該項目的 Docs 連接,咱們如今上來直接看代碼,我用中文作下注釋。git
from pyspider.libs.base_handler import * # 引入 pyspider 的 base_handler,這個是用來當基類的。 # 如下就是咱們寫的類。 class Handler(BaseHandler): crawl_config = { } # 這個是做爲整個項目的全局參數的設置,好比 proxy。 @every(minutes=24 * 60) # 這句話是定時啓動的意思,這裏就是說每一天啓動一次。 # 如下爲爬蟲的入口 def on_start(self): # 抓 http://scrapy.org/ 的頁面,將返回的內容交給 index_page 函數來處理。 self.crawl('http://scrapy.org/', callback=self.index_page) @config(age=10 * 24 * 60 * 60) # 每十天重啓一次 def index_page(self, response): for each in response.doc('a[href^="http"]').items(): # 這裏將 on_start 抓取 scrapy 首頁的返回結果進行過濾,採用了 CSS 選擇器選擇了 href 的值爲 http 開頭的全部 a 標籤。 # 此處循環內的 each 即爲網頁中的 a 標籤。 self.crawl(each.attr.href, callback=self.detail_page) # 再次調用 crawl 函數,對 a 標籤的 href 中目標網址進行抓取,返回給 detail_page 函數來處理。 def detail_page(self, response): return { "url": response.url, # 返回 url 和網頁 title 組成的字典。 "title": response.doc('title').text(), }
做者本身寫的中文教程裏面已經把不少操做都講清楚了,我就不抄來了。github
對於 ajax 請求的內容能夠直接 crawl 那個 ajax 請求的 URL,返回的 response.json 就變成了一個 Python 的字典。ajax
當每一個函數 return 的時候,return 的內容被傳遞到了 BaseHandler 這個基類中的 on_result 函數,其代碼以下:數據庫
def on_result(self, result): """Receiving returns from other callback, override me.""" if not result: return assert self.task, "on_result can't outside a callback." if self.is_debugger(): # 當在瀏覽器中調試運行時: pprint(result) if self.__env__.get('result_queue'): # 當被看成任務執行時,即在 Dashboard 中設置爲 RUNNING 時, self.__env__['result_queue'].put((self.task, result))
而後咱們就能夠經過重寫 on_result 函數,來將全部函數的返回值進行處理,再輸出到 RabbitMQ 的隊列中。json
隊列的另外一端是數據庫寫入腳本,該腳本一條一條地從隊列中取出消息,而後一個字段一個字段地插入到數據庫,不用擔憂數據庫寫入時的衝突問題了。瀏覽器