- Python數(shù)據(jù)分析從入門到精通
- 李梓萌編著
- 3231字
- 2020-09-18 18:05:49
3.3 使用爬蟲框架Scrapy

因為爬蟲應用程序的需求日益高漲,所以在市面中誕生了很多第三方開源爬蟲框架,其中Scrapy是一個為了爬取網(wǎng)站數(shù)據(jù)、提取結構性數(shù)據(jù)而編寫的專業(yè)框架。Scrapy框架的用途十分廣泛,可以用于數(shù)據(jù)挖掘、數(shù)據(jù)監(jiān)測和自動化測試等工作。本節(jié)將簡要講解爬蟲框架Scrapy的基本用法。
3.3.1 Scrapy框架基礎
框架Scrapy使用了Twisted異步網(wǎng)絡庫來處理網(wǎng)絡通信,其整體架構大致如圖3-9所示。

圖3-9 框架Scrapy的架構
在Scrapy框架中,主要包括如下所示的組件。
● 引擎(Scrapy Engine):來處理整個系統(tǒng)的數(shù)據(jù)流,會觸發(fā)框架核心事務。
● 調度器(Scheduler):用來獲取Scrapy發(fā)送過來的請求,然后將請求傳入隊列中,并在引擎再次請求的時候返回。調度器的功能是設置下一個要抓取的網(wǎng)址,并刪除重復的網(wǎng)址。
● 下載器(Downloader):建立在高效的異步模型Twisted之上,下載目標網(wǎng)址中的網(wǎng)頁內容,并將網(wǎng)頁內容返回給Scrapy Engine。
● 爬蟲(Spiders):功能是從特定的網(wǎng)頁中提取指定的信息,這些信息在爬蟲領域中被稱為實體(Item)。
● 項目管道(Pipeline):處理從網(wǎng)頁中提取的爬蟲實體。當使用爬蟲解析一個頁面后,會將實體發(fā)送到項目管道中進行處理,然后驗證實體的有效性,并將不需要的信息刪除。
● 下載器中間件(Downloader Middlewares):此模塊位于Scrapy引擎和Downloader之間,為Scrapy引擎與下載器之間的請求及響應建立橋梁。
● 爬蟲中間件(Spider Middlewares):此模塊在Scrapy引擎和Spiders之間,功能是處理爬蟲的響應輸入和請求輸出。
● 調度中間件(Scheduler Middewares):在Scrapy引擎和Scheduler之間,表示從Scrapy引擎發(fā)送到調度的請求和響應。
在使用Scrapy框架后,下面是大多數(shù)爬蟲程序的運行流程。
1)Scrapy Engine從調度器中取出一個URL鏈接,這個鏈接作為下一個要抓取的目標。
2)Scrapy Engine將目標URL封裝成一個Request請求并傳遞給下載器,下載器在下載URL資源后,將資源封裝成Response應答包。
3)使用爬蟲解析Response應答包,如果解析出Item實體,則將結果交給實體管道進行進一步的處理。如果是URL鏈接,則把URL交給Scheduler等待下一步的抓取操作。
3.3.2 搭建Scrapy環(huán)境
在本地計算機安裝Python后,可以使用pip命令或easy_install命令來安裝Scrapy,具體命令格式如下所示。

另外,需要確保已安裝了“win32api”模塊,同時必須安裝與本地Python版本相對應的版本和位數(shù)(32位或64位)。讀者可以登錄http://www.lfd.uci.edu/~gohlke/pythonlibs/找到需要的版本,如圖3-10所示。

圖3-10 下載“win32api”模塊
下載后將得到一個“.whl”格式的文件,定位到此文件的目錄,然后通過如下命令安裝“win32api”模塊。

注意:如果遇到“ImportError: DLL load failed: 找不到指定的模塊。”錯誤,需要將“Python\Python35\Lib\site-packages\win32”目錄中的如下文件保存到本地系統(tǒng)盤中的“Windows\System32”目錄下。
● pythoncom36.dll。
● pywintypes36.dll。
3.3.3 創(chuàng)建第一個Scrapy項目
下面的實例代碼演示了創(chuàng)建第一個Scrapy項目的過程。
源碼路徑:daima\3\3-5\
(1)創(chuàng)建項目
在開始爬取數(shù)據(jù)之前,必須先創(chuàng)建一個新的Scrapy項目。進入準備存儲代碼的目錄中,然后運行如下所示的命令。

上述命令的功能是創(chuàng)建一個包含下列內容的“tutorial”目錄。

對上述文件的具體說明如下所示。
● scrapy.cfg:項目的配置文件。
● tutorial/:該項目的python模塊,之后在此加入代碼。
● tutorial/items.py:項目中的item文件。
● tutorial/pipelines.py:項目中的pipelines文件。
● tutorial/settings.py:項目的設置文件。
● tutorial/spiders/:放置spider代碼的目錄。
(2)定義Item
Item是保存爬取到的數(shù)據(jù)的容器,使用方法與Python字典類似,并且提供額外保護機制,避免拼寫錯誤導致未定義的字段錯誤。在實際應用中可以創(chuàng)建一個scrapy.Item類,并且定義類型為scrapy.Field。
首先需要從dmoz.org獲取數(shù)據(jù)對item進行建模。需要從dmoz中獲取名稱、url以及網(wǎng)站的描述。對此,在Item中定義相應的字段。編輯“tutorial”目錄中的文件items.py,具體實現(xiàn)代碼如下所示。

通過定義Item,可以很方便地使用Scrapy中的其他方法。而這些方法需要知道Item的定義。
(3)編寫第一個爬蟲(Spider)
Spider是用戶編寫用于從單個網(wǎng)站(或者一些網(wǎng)站)爬取數(shù)據(jù)的類,其中包含一個用于下載的初始URL,如何跟進網(wǎng)頁中的鏈接和如何分析頁面中的內容以及提取生成Item的方法。為了創(chuàng)建一個Spider,必須繼承類scrapy.Spider,且定義如下所示的三個屬性。
● name:用于區(qū)別Spider。該名稱必須是唯一的,因此不可以為不同的Spider設定相同的名稱。
● start_urls:包含了Spider在啟動時進行爬取的url列表。因此,第一個被獲取到的頁面將是其中之一。后續(xù)的URL則從初始的URL獲取到的數(shù)據(jù)中提取。
● parse():spider的一個方法。被調用時,每個初始URL完成下載后生成的Response對象將會作為唯一的參數(shù)傳遞給該方法。它負責解析返回的數(shù)據(jù)(response data),提取數(shù)據(jù)(生成Item)以及生成需要進一步處理的URL的Request對象。
下面是我們編寫的第一個Spider代碼,保存在tutorial/spiders目錄下的文件dmoz_spider.py中,具體實現(xiàn)代碼如下所示。

(4)爬取
進入項目的根目錄,執(zhí)行下列命令啟動spider。

crawl dmoz是負責啟動用于爬取dmoz.org網(wǎng)站的Spider,之后得到如下所示的輸出。

查看包含dmoz的輸出,可以看到在輸出的log中包含定義在start_urls的初始URL,并且與spider一一對應。在log中可以看到它沒有指向其他頁面(referer:None)。同時創(chuàng)建兩個包含url所對應的內容的文件:Book和Resources。
由此可見,Scrapy為Spider的start_urls屬性中的每個URL創(chuàng)建了scrapy.Request對象,并將Parse方法作為回調函數(shù)(callback)賦值給Request。Request對象經(jīng)過調度,執(zhí)行生成scrapy.http.Response對象并送回給spider parse()方法。
(5)提取Item
有很多種從網(wǎng)頁中提取數(shù)據(jù)的方法,Scrapy使用了一種基于XPath和CSS表達式機制:Scrapy Selectors。關于Selector和其他提取機制的信息,建議讀者參考Selector的官方文檔。下面給出XPath表達式的例子及對應的含義:
● /html/head/title:選擇HTML文檔中<head>標簽內的<title>元素。
● /html/head/title/text():選擇<title>元素的文字。
● //td:選擇所有的<td>元素。
● //div[@class="mine"]:選擇所有具有class="mine"屬性的div元素。
上面僅僅列出了幾個簡單的XPath例子,XPath的功能實際上要強大很多。為了配合XPath,Scrapy除了提供Selector之外,還提供了多個方法來避免每次從Response中提取數(shù)據(jù)時生成Selector的麻煩。
在Selector中有如下4個最基本的方法。
● xpath():用于選取指定的標簽內容,例如下面的代碼表示選取所有的book標簽。

● css():傳入CSS表達式,用于選取指定的CSS標簽內容。
● extract():返回選中內容的Unicode字符串,返回結果是列表。
● re():根據(jù)傳入的正則表達式提取數(shù)據(jù),返回Unicode字符串格式的列表。
● re_first():返回SelectorList對象中的第一個Selector對象調用的re方法。
使用內置的Scrapy shell,首先需要進入本實例項目的根目錄,然后執(zhí)行如下命令來啟動Shell。

此時shell將會輸出類似如下所示的內容。


載入Shell后得到一個包含Response數(shù)據(jù)的本地Response變量。輸入“response.body”命令后會輸出Response的包體,輸入“response.headers”后可以看到Response的包頭。更為重要的是,當輸入“response.selector”時,將獲取一個可以用于查詢返回數(shù)據(jù)的Selector(選擇器),以及映射到response.selector.xpath()、response.selector.css()的快捷方法(shortcut):response.xpath()和response.css()。同時,Shell根據(jù)Response提前初始化了變量sel。該Selector根據(jù)Response的類型自動選擇最合適的分析規(guī)則(XML vs HTML)。
(6)提取數(shù)據(jù)
接下來嘗試從這些頁面中提取有用數(shù)據(jù),只需在終端中輸入response.body來觀察HTML源碼并確定合適的XPath表達式。但這個任務非常無聊且不易,可以考慮使用Firefox的Firebug擴展來簡化工作。
查看網(wǎng)頁源碼后會發(fā)現(xiàn)網(wǎng)站的信息被包含在第二個<ul>元素中。可以通過下面的代碼選擇該頁面中網(wǎng)站列表里的所有<li>元素。

通過如下命令獲取對網(wǎng)站的描述。

通過如下命令獲取網(wǎng)站的標題。

3.3.4 抓取某電影網(wǎng)的熱門電影信息
本實例的功能是,使用Scrapy爬蟲抓取某電影網(wǎng)中熱門電影信息。
源碼路徑:daima\3\3-6\
1)在具體爬取數(shù)據(jù)之前,必須先創(chuàng)建一個新的Scrapy項目。首先進入準備保存項目代碼的目錄中,然后運行如下所示的命令。

2)編寫文件moviedouban.py設置要爬取的URL范圍和過濾規(guī)則,主要實現(xiàn)代碼如下所示。


3)編寫執(zhí)行腳本文件pyrequests_douban.py,功能是編寫功能函數(shù)獲取熱門電影的詳細信息,包括電影名、URL鏈接地址、導演信息、主演信息等。文件pyrequests_douban.py的主要實現(xiàn)代碼如下所示。




執(zhí)行后會輸出顯示爬取到的熱門電影信息,如圖3-11所示。

圖3-11 爬取到的熱門電影信息
3.3.5 抓取某網(wǎng)站中的照片并保存到本地
本實例的功能是使用Scrapy爬蟲抓取某網(wǎng)站中的照片信息,并將抓取到的照片保存到本地硬盤中。編寫文件art.py設置要爬取的URL范圍和抓取的內容元素,主要實現(xiàn)代碼如下所示。
源碼路徑:daima\3\3-7\

執(zhí)行后會顯示抓取目標網(wǎng)站圖片的過程,如圖3-12所示。

圖3-12 網(wǎng)站圖片抓取過程
將抓取到的照片保存到本地文件夾“download_images”中,如圖3-13所示。

圖3-13 在本地硬盤保存抓取到的圖片
3.3.6 抓取某網(wǎng)站中的主播照片并保存到本地
本實例的功能是使用Scrapy爬蟲抓取某網(wǎng)站中的主播照片,并將抓取到的主播照片保存到本地硬盤中。編寫文件douyu.py設置要爬取的URL范圍和抓取的內容元素,設置要抓取的Item(是主播昵稱和主播照片)。文件douyu.py的主要實現(xiàn)代碼如下所示。
源碼路徑:daima\3\3-8\


執(zhí)行后會將抓取到的主播照片保存到本地文件夾中,如圖3-14所示。

圖3-14 抓取到的主播照片