Scrapy 示例 —— Web 爬蟲框架

發表於2016-01-26

在這個教材中,我們假定你已經安裝了Scrapy。假如你沒有安裝,你可以參考這個安裝指南

我們將會用開放目錄專案(dmoz)作為我們例子去抓取。

這個教材將會帶你走過下面這幾個方面:

  1. 創造一個新的Scrapy專案
  2. 定義您將提取的Item
  3. 編寫一個蜘蛛去抓取網站並提取Items
  4. 編寫一個Item Pipeline用來儲存提出出來的Items

Scrapy由Python寫成。假如你剛剛接觸Python這門語言,你可能想要了解這門語言起,怎麼最好的利用這門語言。假如你已經熟悉其它類似的語言,想要快速地學習Python,我們推薦這種深入方式學習Python。假如你是新手,想從開始使用Python學習,可以嘗試去看看非程式設計師Python資源列表

創造一個專案

在你要抓取之前,首先要建立一個新的Scrapy專案。然後進去你的存放程式碼目錄,執行如下命令。

它將會建立如下的嚮導目錄:

這是一些基本資訊:

  • scrapy.cfg: 專案的配置檔案。
  • tutorial/: 專案的python模組, 在這裡稍後你將會匯入你的程式碼。
  • tutorial/items.py: 專案items檔案。
  • tutorial/pipelines.py: 專案管道檔案。
  • tutorial/settings.py: 專案配置檔案。
  • tutorial/spiders/: 你將要放入你的spider到這個目錄中。

定義我們的Item

Items是裝載我們抓取資料的容器。它們工作像簡單的Python字典,它提供更多的保護,比如對未定義的欄位提供填充功能防止出錯。

它們通過建立scrapy.item.Item類來宣告並定義它們的屬性作為scrapy.item.Field 物件,就像是一個物件關係對映(假如你不熟悉ORMs,你將會看見它是一個簡單的任務).

我們將需要的item模組化,來控制從demoz.org網站獲取的資料,比如我們將要去抓取網站的名字,url和描述資訊。我們定義這三種屬性的域。我們編輯items.py檔案,它在嚮導目錄中。我們Item類看起來像這樣。

這個看起來複雜的,但是定義這些item能讓你用其他Scrapy元件的時候知道你的item到底是什麼

我們第一個Spider

Spiders是使用者寫的類,它用來去抓取一個網站的資訊(或者一組網站) 。
我們定義一個初始化的URLs列表去下載,如何跟蹤連結,如何去解析這些頁面的內容去提取 items.建立一個Spider,你必須是scrapy.spider.BaseSpider的子類, 並定義三個主要的,強制性的屬性。

  • 名字: Spider的標識. 它必須是唯一的, 那就是說,你不能在不同的Spiders中設定相同的名字。
  • 開始連結:Spider將會去爬這些URLs的列表。所以剛開始的下載頁面將要包含在這些列表中。其他子URL將會從這些起始URL中繼承性生成。
  • parse() 是spider的一個方法, 呼叫時候傳入從每一個URL傳回的Response物件作為引數。response是方法的唯一引數。

    這個方法負責解析response資料和提出抓取的資料(作為抓取的items),跟蹤URLs

    parse()方法負責處理response和返回抓取資料(作為Item物件) 和跟蹤更多的URLs(作為request的物件)

這是我們的第一個Spider的程式碼;它儲存moz/spiders資料夾中,被命名為dmoz_spider.py

為了使你的spider工作, 到專案的頂級目錄讓後執行:

crawl dmoz命令使spider去爬dmoz.org網站的資訊。你將會得到如下類似的資訊:

注意那些行包含[dmoz], 它和我們的spider相關。你能夠看見每行初始化的URL日誌資訊。因為這些URLs是起始頁面,所以他們沒有引用referrers。 所以在每行的末尾部門,你能看見(referer: <None>).

但是有趣的是,在我們的parse方法作用下,兩個檔案被建立: Books and Resources, 它保航兩個URLs的內容

剛剛發生了什麼事情?

Scrapy為每一個start_urls建立一個scrapy.http.Request物件,並將爬蟲的parse 方法指定為回撥函式。

這些Request首先被排程,然後被執行,之後通過parse()方法,將scrapy.http.Response物件被返回,結果也被反饋給爬蟲。

提取Items

選擇器介紹

我們有多種方式去提取網頁中資料。Scrapy 使用的是XPath表示式,通常叫做XPath selectors。如果想了解更多關於選擇器和提取資料的機制,可以看看如下教程XPath selectors documentation.

這裡有一些表示式的例子和它們相關的含義:

  • /html/head/title: 選擇<title>元素,在HTML文件的<head>元素裡
  • /html/head/title/text(): 選擇<title>元素裡面的文字
  • //td: 選擇所有的<td>元素
  • //div[@class=”mine”]: 選擇所有的div元素裡面class屬性為mine的

這裡有許多的例子關於怎麼使用XPath,可以說XPath表示式是非常強大的。如果你想要學習更多關於XPath,我們推薦如下教程this XPath tutorial.

為了更好使用XPaths, Scrapy提供了一個XPathSelector類,它有兩種方式, HtmlXPathSelector(HTML相關資料)和XmlXPathSelector(XML相關資料)。如果你想使用它們,你必須例項化一個Response物件.

你能夠把selectors作為物件,它代表檔案結構中的節點。所以,第1個例項的節點相當於root節點,或者稱為整個文件的節點。

選擇器有三種方法(點選方法你能夠看見完整的API文件)。

      • select(): 返回選擇器的列表,每一個select表示一個xpath表示式選擇的節點。
      • extract(): 返回一個unicode字串 ,該字串XPath選擇器返回的資料。
      • re(): 返回unicode字串列表,字串作為引數由正規表示式提取出來。

在Shell裡面使用選擇器

為了更加形象的使用選擇器,我們將會使用Scrapy shell,它同時需要你的系統安裝IPython (一個擴充套件的Python控制檯)。

如果使用shell,你必須到專案的頂級目錄上,讓後執行如下命令:

shell將會顯示如下的資訊

當shell裝載之後,你將會得到一個response的本地變數。所以你輸入reponse.body,你能夠看見response的body部分或者你能夠輸入response.headers,你能夠看見reponse.headers部分。

shell同樣例項化了兩個選擇器,一個是HTML(在hvx變數裡),一個是XML(在xxs變數裡)。所以我們嘗試怎麼使用它們:

提取資料Extracting the data

現在我們開始嘗試在這幾個頁面裡提取真正的資訊。

你能夠在控制檯裡面輸入response.body,檢查原始碼裡面的XPaths是否與預期相同。然而,檢查原始的HTML程式碼是一件非常枯燥乏味的事情。假如你想讓你的工作變的簡單,你使用Firefox擴充套件的外掛例如Firebug來做這項任務。更多關於介紹資訊請看Using Firebug for scrapingUsing Firefox for scraping

當你檢查了頁面原始碼之後,你將會發現頁面的資訊放在一個<ul>元素裡面,事實上,確切地說是第二個<ul>元素。

所以我們選擇每一個<li>元素使用如下的程式碼:

網站的描述資訊可以使用如下程式碼:

網站的標題:

網站的連結:

如前所述,每個select()呼叫返回一個selectors列表,所以我們可以結合select()去挖掘更深的節點。我們將會用到這些特性,所以:

Note

如果想了解更多的巢狀選擇器,可以參考Nesting selectorsWorking with relative XPaths相關Selectors文件
將程式碼新增到我們spider中:

現在我們再次抓取dmoz.org,你將看到站點在輸出中被列印 ,執行命令:

使用我們的 item

Item物件是自定義python字典;使用標準字典類似的語法,你能夠訪問它們的欄位(就是以前我們定義的屬性)

Spiders希望將抓取的資料放在
Item物件裡。所以,為了返回我們抓取的資料,最終的程式碼要如下這麼寫 :

Note

你能夠找到完整功能的spider在dirbot專案裡,同樣你可以訪問https://github.com/scrapy/dirbot

現在重新抓取dmoz.org網站:

儲存抓取的資料

最簡單的方式去儲存抓取的資料是使用Feed exports,使用如下的命令:

它將會產生一個items.json檔案,它包含所有抓取的items(序列化的JSON)。

在一些小的專案裡(例如我們的教程中),那就足夠啦。然而,假如你想要執行更多複雜的抓取items,你能夠寫一個 Item Pipeline。 因為在專案建立的時候,一個專門用於Item Pipelines的佔位符檔案已經隨著專案一起被建立,目錄在tutorial/pipelines.py。如果你只需要存取這些抓取後的items的話,就不需要去實現任何的條目管道。

相關文章