記得n年前項目需要一個靈活的爬蟲工具,就組織了一個小團(tuán)隊用Java實現(xiàn)了一個爬蟲框架,可以根據(jù)目標(biāo)網(wǎng)站的結(jié)構(gòu)、地址和需要的內(nèi)容,做簡單的配置開發(fā),即可實現(xiàn)特定網(wǎng)站的爬蟲功能。因為要考慮到各種特殊情形,開發(fā)還耗了不少人力。后來發(fā)現(xiàn)了Python下有這個Scrapy工具,瞬間覺得之前做的事情都白費了。對于一個普通的網(wǎng)絡(luò)爬蟲功能,Scrapy完全勝任,并把很多復(fù)雜的編程都包裝好了。本文會介紹如何Scrapy構(gòu)建一個簡單的網(wǎng)絡(luò)爬蟲。
一個基本的爬蟲工具,它應(yīng)該具備以下幾個功能:
通過HTTP(S)請求,下載網(wǎng)頁信息
解析網(wǎng)頁,抓取需要的內(nèi)容
保存內(nèi)容
從現(xiàn)有頁面中找到有效鏈接,從而繼續(xù)抓取下一個網(wǎng)頁

我們來看下Scrapy怎么做到這些功能的。首先準(zhǔn)備Scrapy環(huán)境,你需要安裝Python(本文使用v2.7)和pip,然后用pip來安裝lxml和scrapy。個人強烈建議使用virtualenv來安裝環(huán)境,這樣不同的項目之間不會沖突。詳細(xì)步驟這里就不贅述了。對于Mac用戶要注意,當(dāng)使用pip安裝lxml時,會出現(xiàn)類似于的下面錯誤:
Error: #include “xml/xmlversion.h” not found
解決這個問題,你需要先安裝Xcode的command line tools,具體的方法是在命令行執(zhí)行下面的命令即可。
1
$xcode-select--install
環(huán)境安裝好之后,我們來用Scrapy實現(xiàn)一個簡單的爬蟲,抓取本博客網(wǎng)站的文章標(biāo)題,地址和摘要。
創(chuàng)建工程
1
$scrapystartprojectmy_crawler
該命令會在當(dāng)前目錄下創(chuàng)建一個名為”my_crawler”的工程,工程的目錄結(jié)構(gòu)如下
8my_crawler
|-my_crawler
||-spiders
|||-__init__.py
||-items.py
||-pipelines.py
||-setting.py
|-scrapy.cfg
設(shè)置待抓取內(nèi)容的字段,本例中就是文章的標(biāo)題,地址和摘要
修改”items.py”文件,在”MyCrawlerItem”類中加上如下代碼:
Python
8# -*- coding: utf-8 -*-
importscrapy
classMyCrawlerItem(scrapy.Item):
title=scrapy.Field()# 文章標(biāo)題
url=scrapy.Field()# 文章地址
summary=scrapy.Field()# 文章摘要
pass
編寫網(wǎng)頁解析代碼
在”my_crawler/spiders”目錄下,創(chuàng)建一個名為”crawl_spider.py”文件(文件名可以任意?。4a如下
Python
31# -*- coding: utf-8 -*-
importscrapy
fromscrapy.linkextractorsimportLinkExtractor
fromscrapy.spidersimportCrawlSpider,Rule
frommy_crawler.itemsimportMyCrawlerItem
classMyCrawlSpider(CrawlSpider):
name='my_crawler'# Spider名,必須唯一,執(zhí)行爬蟲命令時使用
allowed_domains=['bjhee.com']# 限定允許爬的域名,可設(shè)置多個
start_urls=[
# 種子URL,可設(shè)置多個
]
rules=(# 對應(yīng)特定URL,設(shè)置解析函數(shù),可設(shè)置多個
Rule(LinkExtractor(allow=r'/page/[0-9]+'),# 指定允許繼續(xù)爬取的URL格式,支持正則
callback='parse_item',# 用于解析網(wǎng)頁的回調(diào)函數(shù)名
follow=True
),
)
defparse_item(self,response):
# 通過XPath獲取Dom元素
articles=response.xpath('//*[@id="main"]/ul/li')
forarticleinarticles:
item=MyCrawlerItem()
item['title']=article.xpath('h3[@class="entry-title"]/a/text()').extract()[0]
item['url']=article.xpath('h3[@class="entry-title"]/a/@href').extract()[0]
item['summary']=article.xpath('div[2]/p/text()').extract()[0]
yielditem
對于XPath不熟悉的朋友,可以通過Chrome的debug工具獲取元素的XPath。

讓我們測試下爬蟲的效果
在命令行中輸入:
1
$scrapycrawlmy_crawler
注意,這里的”my_crawler”就是你在”crawl_spider.py”文件中起的Spider名。
沒過幾秒鐘,你就會看到要抓取的字段內(nèi)容打印在控制臺上了。就是這么神奇!Scrapy將HTTP(S)請求,內(nèi)容下載,待抓取和已抓取的URL隊列的管理都封裝好了。你的主要工作基本上就是設(shè)置URL規(guī)則及編寫解析的方法。
我們將抓取的內(nèi)容保存為JSON文件:
1
$scrapycrawlmy_crawler-omy_crawler.json-tjson
你可以在當(dāng)前目錄下,找到文件”my_crawler.json”,里面保存的就是我們要抓取的字段信息。(參數(shù)”-t json”可以省去)
將結(jié)果保存到數(shù)據(jù)庫
這里我們采用MongoDB,你需要先安裝Python的MongoDB庫”pymongo”。編輯”my_crawler”目錄下的”pipelines.py”文件,在”MyCrawlerPipeline”類中加上如下代碼:
Python
29# -*- coding: utf-8 -*-
importpymongo
fromscrapy.confimportsettings
fromscrapy.exceptionsimportDropItem
classMyCrawlerPipeline(object):
def__init__(self):
# 設(shè)置MongoDB連接
connection=pymongo.Connection(
settings['MONGO_SERVER'],
settings['MONGO_PORT']
)
db=connection[settings['MONGO_DB']]
self.collection=db[settings['MONGO_COLLECTION']]
# 處理每個被抓取的MyCrawlerItem項
defprocess_item(self,item,spider):
valid=True
fordatainitem:
ifnotdata:# 過濾掉存在空字段的項
valid=False
raiseDropItem("Missing {0}!".format(data))
ifvalid:
# 也可以用self.collection.insert(dict(item)),使用upsert可以防止重復(fù)項
self.collection.update({'url':item['url']},dict(item),upsert=True)
returnitem
再打開”my_crawler”目錄下的”settings.py”文件,在文件末尾加上pipeline的設(shè)置:
Python
11ITEM_PIPELINES={
'my_crawler.pipelines.MyCrawlerPipeline':300,# 設(shè)置Pipeline,可以多個,值為執(zhí)行優(yōu)先級
}
# MongoDB連接信息
MONGO_SERVER='localhost'
MONGO_PORT=27017
MONGO_DB='bjhee'
MONGO_COLLECTION='articles'
DOWNLOAD_DELAY=2# 如果網(wǎng)絡(luò)慢,可以適當(dāng)加些延遲,單位是秒
執(zhí)行爬蟲
1
$scrapycrawlmy_crawler
別忘了啟動MongoDB并創(chuàng)建”bjhee”數(shù)據(jù)庫哦?,F(xiàn)在你可以在MongoDB里查詢到記錄了。

總結(jié)下,使用Scrapy來構(gòu)建一個網(wǎng)絡(luò)爬蟲,你需要做的就是:
“items.py”中定義爬取字段
在”spiders”目錄下創(chuàng)建你的爬蟲,編寫解析函數(shù)和規(guī)則
“pipelines.py”中對爬取后的結(jié)果做處理
“settings.py”設(shè)置必要的參數(shù)
其他的事情,Scrapy都幫你做了。下圖就是Scrapy具體工作的流程。怎么樣?開始寫一個自己的爬蟲吧。

。
學(xué)習(xí)是對自己最好的投資,而機會屬于有準(zhǔn)備的人,這是一個看臉的時代,但最終拼的是實力。人和人之間的差距不在于智商,而在于如何利用業(yè)余時間,所以沒有等出來的輝煌,只有干出來的精彩。其實只要你想學(xué)習(xí),什么時候開始都不晚,不要擔(dān)心這擔(dān)心那,你只需努力,剩下的交給時間,而你之所以還沒有變強,只因你還不夠努力,要記得付出不亞于任何人的努力。