Python下用Scrapy和MongoDB構建爬蟲系統(2)

PyPer發表於2015-04-24

在上一篇中,我們實現了一個基本網路爬蟲,它可以從StackOverflow上下載最新的問題,並將它們儲存在MongoDB資料庫中。在本文中,我們將對其擴充套件,使它能夠爬取每個網頁底部的分頁連結,並從每一頁中下載問題(包含問題標題和URL)。

在你開始任何爬取工作之前,檢查目標網站的使用條款並遵守robots.txt檔案。同時,做爬取練習時遵守道德,不要在短時間內向某個網站發起大量請求。像對待自己的網站一樣對待任何你將爬取的網站。

開始

有兩種可能的方法來接著從上次我們停下的地方繼續進行。

第一個方法是,擴充套件我們現有的網路爬蟲,通過利用一個xpath表示式從”parse_item”方法裡的響應中提取每個下一頁連結,並通過回撥同一個parse_item方法產生一個請求物件。利用這種方法,爬蟲會自動生成針對我們指定的連結的新請求,你可以在Scrapy文件這裡找到更多有關該方法的資訊。

另一個更簡單的方法是,使用一個不同型別的爬蟲—CrawlSpider(連結)。這是基本Spider的一個擴充套件版本,它剛好滿足我們的要求。

CrawlSpider

我們將使用與上一篇教程中相同的爬蟲專案,所以如果你需要的話可以從repo上獲取這些程式碼。

建立樣板

在“stack”目錄中,首先由crawl模板生成爬蟲樣板。

Scrapy專案現在看起來應該像這樣:

stack_crawler.py檔案內容如下:

我們只需要對這個樣板做一些更新。

更新“start_urls”列表

首先,新增問題的第一個頁面連結到start_urls列表:

更新“rules”列表

接下來,我們需要新增一個正規表示式到“rules”屬性中,以此告訴爬蟲在哪裡可以找到下一個頁面連結:

現在爬蟲能根據那些連結自動請求新的頁面,並將響應傳遞給“parse_item”方法,以此來提取問題和對應的標題。

如果你仔細檢視的話,可以發現這個正規表示式限制了它只能爬取前9個網頁,因為在這個demo中,我們不想爬取所有的176234個網頁。

更新“parse_item”方法

現在我們只需編寫如何使用xpath解析網頁,這一點我們已經在上一篇教程中實現過了,所以直接複製過來。

這就是為爬蟲提供的解析程式碼,但是現在先不要啟動它。

新增一個下載延遲

我們需要通過在settings.py檔案中設定一個下載延遲來善待StackOverflow(和任何其他網站)。

這告訴爬蟲需要在每兩個發出的新請求之間等待5秒鐘。你也很有必要做這樣的限制,因為如果你不這麼做的話,StackOverflow將會限制你的訪問流量,如果你繼續不加限制地爬取該網站,那麼你的IP將會被禁止。所有,友好點—要像對待自己的網站一樣對待任何你爬取的網站。

現在只剩下一件事要考慮—儲存資料。

MongoDB

上次我們僅僅下載了50個問題,但是因為這次我們要爬取更多的資料,所有我們希望避免向資料庫中新增重複的問題。為了實現這一點,我們可以使用一個MongoDB的 upsert方法,它意味著如果一個問題已經存在資料庫中,我們將更新它的標題;否則我們將新問題插入資料庫中。

修改我們前面定義的MongoDBPipeline:

為簡單起見,我們沒有優化查詢,也沒有處理索引值,因為這不是一個生產環境。

測試

啟動爬蟲!

現在你可以坐下來,看著你的資料庫漸漸充滿資料。

結論

你可以從Github庫下載整個原始碼,也可以在下面評論或提問。

相關文章