VOOZH about

URL: https://read01.com/nx8oN.html

⇱ Python下用Scrapy和MongoDB構建爬蟲系統 - 壹讀


Sunday, Apr 12, 2026

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

2015/04/24 來源:Da資訊

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

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

開始

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

第一個方法是,擴展我們現有的網絡爬蟲,通過利用一個xpath表達式從」parse_item」方法裡的響應中提取每個下一頁連結,並通過回調同一個parse_item方法產生一個請求對象。利用這種方法,爬蟲會自動生成針對我們指定的連結的新請求,你可以在Scrapy文檔這裡找到更多有關該方法的信息。

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

CrawlSpider

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

創建樣板

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

$ scrapy genspider stack_crawler stackoverflow.com -t crawl
├── scrapy.cfg
└── stack
├── __init__.py
├── items.py
├── pipelines.py
├── settings.py
└── spiders
├── __init__.py
├── stack_crawler.py
└── stack_spider.py

stack_crawler.py文件內容如下:

fromscrapy.contrib.linkextractorsimportLinkExtractor
fromscrapy.contrib.spidersimportCrawlSpider, Rule
fromstack.itemsimportStackItem
StackCrawlerSpider(CrawlSpider):
allowed_domains=['stackoverflow.com']
start_urls=['http://www.stackoverflow.com/']
Rule(LinkExtractor(allow=r'Items/'), callback='parse_item', follow=True),
, response):
i=StackItem
#i['domain_id'] = response.xpath('//input[@id="sid"]/@value').extract
#i['name'] = response.xpath('//div[@id="name"]').extract
#i['description'] = response.xpath('//div[@id="description"]').extract
returni

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

更新「start_urls」列表

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

1
2
3
start_urls=[
'http://stackoverflow.com/questions?pagesize=50&sort=newest'
]

更新「rules」列表

接下來,我們需要添加一個正則表達式到「rules」屬性中,以此告訴爬蟲在哪裡可以找到下一個頁面連結:

1
2
3
4
rules=[
Rule(LinkExtractor(allow=r'questions?page=[0-9]&sort=newest'),
callback='parse_item', follow=True)
]

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

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

更新「parse_item」方法

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

questions:
item=StackItem
item['url']=question.xpath(
'a[@class="question-hyperlink"]/@href').extract[0]
item['title']=question.xpath(
'a[@class="question-hyperlink"]/text').extract[0]
yielditem

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

添加一個下載延遲

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

1
DOWNLOAD_DELAY=5

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

現在只剩下一件事要考慮—存儲數據。

MongoDB

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

修改我們前面定義的MongoDBPipeline:

data:
raiseDropItem("Missing data!")
self.collection.update({'url': item['url']},dict(item), upsert=True)
log.msg("Question added to MongoDB database!"
level=log.DEBUG, spider=spider)
returnitem

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

測試

啟動爬蟲!

1
$ scrapy crawl questions

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

結論

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

您可能感興趣
免責聲明:本文內容來源于Da資訊,文章觀點不代表壹讀立場,如若侵犯到您的權益,或涉不實謠言,敬請向我們提出檢舉
最新文章 / 服務條款 / 私隱保護 / DMCA / 聯絡我們

壹讀/READ01.COM