开源 Python网络爬虫框架 Scrapy
?
開源 Python 網(wǎng)絡(luò)爬蟲框架 Scrapy:http://blog.csdn.net/zbyufei/article/details/7554322
?
?
介紹
?
所謂網(wǎng)絡(luò)爬蟲,就是一個在網(wǎng)上到處或定向抓取數(shù)據(jù)的程序,當(dāng)然,這種說法不夠?qū)I(yè),更專業(yè)的描述就是,抓取特定網(wǎng)站網(wǎng)頁的HTML數(shù)據(jù)。不過由于一個網(wǎng)站的網(wǎng)頁很多,而我們又不可能事先知道所有網(wǎng)頁的URL地址,所以,如何保證我們抓取到了網(wǎng)站的所有HTML頁面就是一個有待考究的問題了。
一般的方法是,定義一個入口頁面,然后一般一個頁面會有其他頁面的URL,于是從當(dāng)前頁面獲取到這些URL加入到爬蟲的抓取隊列中,然后進(jìn)入到新新頁面后再遞歸的進(jìn)行上述的操作,其實說來就跟深度遍歷或廣度遍歷一樣。
上面介紹的只是爬蟲的一些概念而非搜索引擎,實際上搜索引擎的話其系統(tǒng)是相當(dāng)復(fù)雜的,爬蟲只是搜索引擎的一個子系統(tǒng)而已。
?
下面介紹一個開源的爬蟲框架 Scrapy。
?
?
一、概述
?
Scrapy是一個用?Python?寫的 Crawler Framework ,簡單輕巧,并且非常方便,并且官網(wǎng)上說已經(jīng)在實際生產(chǎn)中在使用了,不過現(xiàn)在還沒有 Release 版本,可以直接使用他們的 Mercurial 倉庫里抓取源碼進(jìn)行安裝。
Scrapy 使用 Twisted 這個異步網(wǎng)絡(luò)庫來處理網(wǎng)絡(luò)通訊,架構(gòu)清晰,并且包含了各種中間件接口,可以靈活的完成各種需求。整體架構(gòu)如下圖所示:
綠線是數(shù)據(jù)流向,首先從初始 URL 開始,Scheduler 會將其交給 Downloader 進(jìn)行下載,下載之后會交給 Spider 進(jìn)行分析,Spider 分析出來的結(jié)果有兩種:一種是需要進(jìn)一步抓取的鏈接,例如之前分析的“下一頁”的鏈接,這些東西會被傳回 Scheduler ;另一種是需要保存的數(shù)據(jù),它們則被送到 Item Pipeline 那里,那是對數(shù)據(jù)進(jìn)行后期處理(詳細(xì)分析、過濾、存儲等)的地方。另外,在數(shù)據(jù)流動的通道里還可以安裝各種中間件,進(jìn)行必要的處理。
?
?
二、組件
?
scrapy 組件
- 1、Scrapy Engine(Scrapy引擎):Scrapy引擎是用來控制整個系統(tǒng)的數(shù)據(jù)處理流程,并進(jìn)行事務(wù)處理的觸發(fā)。更多的詳細(xì)內(nèi)容可以看下面的數(shù)據(jù)處理流程。
- 2、Scheduler(調(diào)度器):調(diào)度程序從Scrapy引擎接受請求并排序列入隊列,并在Scrapy引擎發(fā)出請求后返還給他們。
- 3、Downloader(下載器):下載器的主要職責(zé)是抓取網(wǎng)頁并將網(wǎng)頁內(nèi)容返還給蜘蛛( Spiders)。
- 4、Spiders(蜘蛛):蜘蛛是有Scrapy用戶自己定義用來解析網(wǎng)頁并抓取制定URL返回的內(nèi)容的類,每個蜘蛛都能處理一個域名或一組域名。換句話說就是用來定義特定網(wǎng)站的抓取和解析規(guī)則。
? ? ? ? ?Spiders ( 蜘蛛?)?的整個抓取流程(周期)是這樣的:
- 5、Item Pipeline(項目管道):項目管道的主要責(zé)任是負(fù)責(zé)處理有蜘蛛從網(wǎng)頁中抽取的項目,他的主要任務(wù)是清晰、驗證和存儲數(shù)據(jù)。當(dāng)頁面被蜘蛛解析后,將被發(fā)送到項目管道,并經(jīng)過幾個特定的次序處理數(shù)據(jù)。每個項目管道的組件都是有一個簡單的方法組成的Python類。他們獲取了項目并執(zhí)行他們的方法,同時他們還需要確定的是是否需要在項目管道中繼續(xù)執(zhí)行下一步或是直接丟棄掉不處理。
? ? ? ? 項目管道通常執(zhí)行的過程有:
- 6、Downloader middlewares(下載器中間件):?下載中間件是位于Scrapy引擎和下載器之間的鉤子框架,主要是處理Scrapy引擎與下載器之間的請求及響應(yīng)。它提供了一個自定義的代碼的方式來拓展Scrapy的功能。下載中間器是一個處理請求和響應(yīng)的鉤子框架。他是輕量級的,對Scrapy盡享全局控制的底層的系統(tǒng)。
- 7、Spider middlewares(蜘蛛中間件):蜘蛛中間件是介于Scrapy引擎和蜘蛛之間的鉤子框架,主要工作是處理蜘蛛的響應(yīng)輸入和請求輸出。它提供一個自定義代碼的方式來拓展Scrapy的功能。蛛中間件是一個掛接到Scrapy的蜘蛛處理機制的框架,你可以插入自定義的代碼來處理發(fā)送給蜘蛛的請求和返回蜘蛛獲取的響應(yīng)內(nèi)容和項目。
- 8、Scheduler middlewares(調(diào)度中間件):調(diào)度中間件是介于Scrapy引擎和調(diào)度之間的中間件,主要工作是處從Scrapy引擎發(fā)送到調(diào)度的請求和響應(yīng)。他提供了一個自定義的代碼來拓展Scrapy的功能。
?
?
三、數(shù)據(jù)處理流程
?
Scrapy的整個數(shù)據(jù)處理流程有Scrapy引擎進(jìn)行控制,其主要的運行方式為:
?
?
四、安裝:
?
Scrapy是一個快速,高層次的屏幕抓取和web抓取框架,用于抓取web站點并從頁面中提取結(jié)構(gòu)化的數(shù)據(jù)。Scrapy用途廣泛,可以用于數(shù)據(jù)挖掘、監(jiān)測和自動化測試。Scrapy吸引人的地方在于它是一個框架,任何人都可以根據(jù)需求方便的修改。它也提供了多種類型爬蟲的基類,如BaseSpider、sitemap爬蟲等,最新版本又提供了web2.0爬蟲的支持。
?
下面介紹Scrapy在windows下的安裝:
首先下載windows版:Scrapy-0.15.0.2842.win32.exe,直接安裝。
安裝之后不能直接運行scrapy提供的test,會提示錯誤,因為scrapy基于其他一些python庫,需要把這些庫都安裝才行。
Twisted:Twisted Matrix 是一種用來進(jìn)行網(wǎng)絡(luò)服務(wù)和應(yīng)用程序編程的純 Python 框架,雖然 Twisted Matrix 中有大量松散耦合的模塊化組件,但該框架的中心概念還是非阻塞異步服務(wù)器這一思想。Twisted的安裝也非常簡單,在這里直接下載windows平臺下的相應(yīng)版本即可:http://pypi.python.org/packages/2.7/T/Twisted/,
zope.interface:在這里下載http://pypi.python.org/pypi/zope.interface/3.8.0#downloads。zope.interface沒有提供windows平臺下的exe版,只提供了windows平臺下的egg包。
ez_setup:下載http://pypi.python.org/pypi/ez_setup,安裝。將egg文件放置在{python安裝目錄}\Scripts目錄下。
打開CMD并切換至scripts目錄,easy_install zope.interface-3.8.0-py2.6-win32.egg安裝。
w3lib:zope.interface問題解決之后還會提示缺少w3lib,下載http://pypi.python.org/pypi/w3lib后安裝即可
libxml2:使用scrapy的html解析功能時,會提示你缺少libxml2,所以我們先把這個也裝上,地址http://xmlsoft.org/sources/win32/python/,下載相應(yīng)的版本即可。
至此就可以使用Scrapy玩spider了,大家可以根據(jù)文檔寫一個簡單的爬蟲試試,實際上使用scrapy做一個簡易的爬蟲甚至只需要幾行代碼就可以了,以后有空再詳細(xì)說說使用方法,本文不做更多描述。
?
?
五、入門
?
本文參考Scrapy Tutorial里面的文檔,翻譯出來加上自己的理解,供大家學(xué)習(xí)。
在本文中,我們將學(xué)會如何使用Scrapy建立一個爬蟲程序,并爬取指定網(wǎng)站上的內(nèi)容,這一切在Scrapy框架內(nèi)實現(xiàn)將是很簡單輕松的事情。
本教程主要內(nèi)容包括一下四步:
- 1.?創(chuàng)建一個新的Scrapy Project
- 2.?定義你需要從網(wǎng)頁中提取的元素Item
- 3.?實現(xiàn)一個Spider類,通過接口完成爬取URL和提取Item的功能
- 4.?實現(xiàn)一個Item PipeLine類,完成Item的存儲功能
?
新建工程
首先,為我們的爬蟲新建一個工程,首先進(jìn)入一個目錄(任意一個我們用來保存代碼的目錄),執(zhí)行:
scrapy startproject Domz最后的Domz就是項目名稱。這個命令會在當(dāng)前目錄下創(chuàng)建一個新目錄Domz,結(jié)構(gòu)如下:
dmoz/ scrapy.cfg dmoz/ __init__.py items.py pipelines.py settings.py spiders/ __init__.pyscrapy.cfg: 項目配置文件
items.py: 需要提取的數(shù)據(jù)結(jié)構(gòu)定義文件
pipelines.py: 管道定義,用來對items里面提取的數(shù)據(jù)做進(jìn)一步處理,如保存等
settings.py: 爬蟲配置文件
spiders: 放置spider的目錄
?
定義Item
在items.py里面定義我們要抓取的數(shù)據(jù):
from scrapy.item import Item, Field class DmozItem(Item): title = Field() link = Field() desc = Field()這里我們需要獲取dmoz頁面上的標(biāo)題,鏈接,描述,所以定義一個對應(yīng)的items結(jié)構(gòu),不像Django里面models的定義有那么多種類的Field,這里只有一種就叫Field(),再復(fù)雜就是Field可以接受一個default值。
?
實現(xiàn)Spider
spider只是一個繼承字scrapy.spider.BaseSpider的Python類,有三個必需的定義的成員
name:?名字,這個spider的標(biāo)識
start_urls:?一個url列表,spider從這些網(wǎng)頁開始抓取
parse():?一個方法,當(dāng)start_urls里面的網(wǎng)頁抓取下來之后需要調(diào)用這個方法解析網(wǎng)頁內(nèi)容,同時需要返回下一個需要抓取的網(wǎng)頁,或者返回items列表
所以在spiders目錄下新建一個spider,dmoz_spider.py:
class DmozSpider(BaseSpider): name = "dmoz.org" start_urls = [ "http://www.dmoz.org/Computers/Programming/Languages/Python/Books/", "http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/" ] def parse(self, response): filename = response.url.split("/")[-2] open(filename, 'wb').write(response.body)?
提取Item
提取數(shù)據(jù)到Items里面,主要用到XPath提取網(wǎng)頁數(shù)據(jù):
scrapy有提供兩個XPath選擇器,HtmlXPathSelector和XmlXPathSelector,一個用于HTML,一個用于XML,XPath選擇器有三個方法
select(xpath): 返回一個相對于當(dāng)前選中節(jié)點的選擇器列表(一個XPath可能選到多個節(jié)點)
extract(): 返回選擇器(列表)對應(yīng)的節(jié)點的字符串(列表)
re(regex): 返回正則表達(dá)式匹配的字符串(分組匹配)列表
一種很好的方法是在Shell里面對XPath進(jìn)行測試:
現(xiàn)在修改parse()方法看看如何提取數(shù)據(jù)到items里面去:
def parse(self, response): hxs = HtmlXPathSelector(response) sites = hxs.select('//ul/li') items = [] for site in sites: item = DmozItem() item['title'] = site.select('a/text()').extract() item['link'] = site.select('a/@href').extract() item['desc'] = site.select('text()').extract() items.append(item) return items?
實現(xiàn)PipeLine
PipeLine用來對Spider返回的Item列表進(jìn)行保存操作,可以寫入到文件、或者數(shù)據(jù)庫等。
PipeLine只有一個需要實現(xiàn)的方法:process_item,例如我們將Item保存到一個文件中:
def __init__(self): self.file = open('jingdong.txt', 'wb') def process_item(self, item, spider): self.file.write(item['title'] + '\t'+ item['link'] + '\t' + item['desc']+'\n')到現(xiàn)在,我們就完成了一個基本的爬蟲的實現(xiàn),可以輸入下面的命令來啟動這個Spider:
scrapy crawl dmoz.org?
Scrapy之URL解析與遞歸爬取:
前面介紹了Scrapy如何實現(xiàn)一個最簡單的爬蟲,但是這個Demo里只是對一個頁面進(jìn)行了抓取。在實際應(yīng)用中,爬蟲一個重要功能是”發(fā)現(xiàn)新頁面”,然后遞歸的讓爬取操作進(jìn)行下去。
發(fā)現(xiàn)新頁面的方法很簡單,我們首先定義一個爬蟲的入口URL地址,比如Scrapy入門教程中的start_urls,爬蟲首先將這個頁面的內(nèi)容抓取之后,解析其內(nèi)容,將所有的鏈接地址提取出來。這個提取的過程是很簡單的,通過一個html解析庫,將這樣的節(jié)點內(nèi)容提取出來,href參數(shù)的值就是一個新頁面的URL。獲取這個URL值之后,將其加入到任務(wù)隊列中,爬蟲不斷的從隊列中取URL即可。這樣,只需要為爬蟲定義一個入口的URL,那么爬蟲就能夠自動的爬取到指定網(wǎng)站的絕大多數(shù)頁面。
當(dāng)然,在具體的實現(xiàn)中,我們還需要對提取的URL做進(jìn)一步處理:
1. 判斷URL指向網(wǎng)站的域名,如果指向的是外部網(wǎng)站,那么可以將其丟棄
2. URL去重,可以將所有爬取過的URL存入數(shù)據(jù)庫中,然后查詢新提取的URL在數(shù)據(jù)庫中是否存在,如果存在的話,當(dāng)然就無需再去爬取了。
下面介紹一下如何在Scrapy中完成上述這樣的功能。
我們只需要改寫spider的那個py文件即可,修改parse()方法代碼如下:
from scrapy.selector import HtmlXPathSelector def parse(self, response): hxs = HtmlXPathSelector(response) items = [] newurls = hxs.select('//a/@href').extract() validurls = [] for url in newurls: #判斷URL是否合法 if true: validurls.append(url) items.extend([self.make_requests_from_url(url).replace(callback=self.parse) for url in validurls]) sites = hxs.select('//ul/li') items = [] for site in sites: item = DmozItem() item['title'] = site.select('a/text()').extract() item['link'] = site.select('a/@href').extract() item['desc'] = site.select('text()').extract() items.append(item) return items?
?
?
?
?
總結(jié)
以上是生活随笔為你收集整理的开源 Python网络爬虫框架 Scrapy的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python 异步 IO 、协程、asy
- 下一篇: 用 Python 和 werobot 框