天天看點

帶你讀《從零開始學Scrapy網絡爬蟲》之三:Scrapy架構介紹第3章 Scrapy架構介紹

點選檢視第一章 點選檢視第二章

第3章 Scrapy架構介紹

  Scrapy是一個為了爬取網站資訊,提取結構性資料而編寫的應用架構。Scrapy用途廣泛,可用于資料挖掘、監測和自動化測試等。

3.1 網絡爬蟲原理

  網絡爬蟲的英文為Web Spider,又稱做網絡蜘蛛或網絡機器人。如果把網際網路比喻成一張巨大的蜘蛛網,資料便是存放于蜘蛛網中的各個節點,爬蟲就是網中爬行的蜘蛛,沿着網絡抓取自己的獵物(資料)。

  網絡爬蟲簡單來說就是一種按照一定規則,自動地抓取網際網路中資訊的程式或腳本。

3.1.1 爬蟲執行的流程

  我們知道,網絡爬蟲執行的基本流程是:模拟使用者使用浏覽器向網站發送請求,網站響應請求後将網頁文檔發送過來,爬蟲對網頁做資訊提取和存儲。具體流程如圖3-1所示。

帶你讀《從零開始學Scrapy網絡爬蟲》之三:Scrapy架構介紹第3章 Scrapy架構介紹

圖3-1 爬蟲執行流程

  圖3-1中的爬蟲執行流程,介紹如下:

  (1)發送請求。

  爬蟲設定一個URL,模拟浏覽器使用HTTP協定向網站伺服器發送通路請求。

  (2)擷取HTML文檔。

  伺服器接收到請求後,将HTML文檔(或者圖檔、視訊等其他資源)發送給爬蟲。

  (3)抽取資料。

  爬蟲使用XPath或BeautifulSoup從HTML文檔中抽取出有用的資料。

  (4)儲存資料。

  将抽取到的資料儲存到檔案(CSV、JSON、TXT等)或資料庫(MySQL、MongoDB等)中,實作資料的持久化存儲。

  上面流程中的每一步,看似簡單,但實作起來着實不易。如何僞裝成浏覽器?如何構造一個HTTP請求發送給網站伺服器?如何擷取網站伺服器發送的HTML文檔?如何抽取HTML資料?如何将每一個步驟關聯起來?種種問題,在學習Scrapy爬蟲架構後,都能輕松解決。還等什麼呢?下面開始我們的Scrapy學習之旅吧!

3.2 Scrapy架構結構及執行流程

  Scrapy架構結構和流程設計遵循網絡爬蟲的基本原理。通過元件封裝不同的功能子產品;通過請求和響應類封裝資料流;通過引擎指揮整個系統協調運作。

3.2.1 Scrapy架構結構

  了解了HTTP和爬蟲的基本原理,就不難了解Scrapy的架構結構了。如圖3-2所示為Scrapy的架構結構,包含了不同功能的元件、系統中發生的資料流及執行流程。

  1.元件

  下面簡單介紹一下Scrapy架構結構中包含的元件。

  • 引擎(Engine)

      引擎猶如總指揮,是整個系統的“大腦”,指揮其他元件協同工作。

  • 排程器(Scheduler)

      排程器接收引擎發過來的請求,按照先後順序,壓入隊列中,同時去除重複的請求。

  • 下載下傳器(Downloader)

      下載下傳器用于下載下傳網頁内容,并将網頁内容傳回給爬蟲(Scrapy下載下傳器是建立在twisted這個高效的異步模型上的)。

  • 爬蟲(Spiders)

      爬蟲作為最核心的元件,用于從特定的網頁中提取需要的資訊,即所謂的實體(Item)。使用者也可以從中提取對外連結接,讓Scrapy繼續抓取下一個頁面。

帶你讀《從零開始學Scrapy網絡爬蟲》之三:Scrapy架構介紹第3章 Scrapy架構介紹

圖3-2 Scrapy架構結構

  • 項目管道(Item Pipelines)

      項目管道負責處理爬蟲從網頁中抽取的實體。主要的功能是持久化實體、驗證明體的有效性、清除不需要的資訊等。

  • 下載下傳器中間件(Downloader Middlewares)

      下載下傳器中間件介于引擎和下載下傳器之間,主要處理Scrapy引擎與下載下傳器之間的請求及響應。

  • 爬蟲中間件(Spider Middlewares)

      爬蟲中間件介于引擎和爬蟲之間,主要工作是處理爬蟲的響應輸入和請求輸出。

  2.資料流

  Scrapy架構結構中傳遞和處理的資料主要有以下3種:

  • 向網站伺服器發送的請求資料(請求的内容見2.1.3節);
  • 網站伺服器傳回的響應資料(響應的内容見2.1.4節);
  • 解析後的結構資料(類似于字典)。

      Scrapy中定義的Request和Response類,用于儲存請求和響應資料;Item類儲存解析後的結構資料。它們分别對應于圖3-2中辨別的Requests、Response和Items。

3.2.2 Scrapy執行流程

  下面從資料流的角度介紹Scrapy架構的執行流程。

  圖3-2中第①、②、③、④步,執行的是HTTP請求,傳遞和處理的是向網站伺服器發送的請求資料。

  第①步:爬蟲(Spider)使用URL(要爬取頁面的網址)構造一個請求(Request)對象,送出給引擎(Engine)。如果請求要僞裝成浏覽器,或者設定代理IP,可以先在爬蟲中間件中設定,再發送給引擎。

  第②步:引擎将請求安排給排程器,排程器根據請求的優先級确定執行順序。

  第③步:引擎從排程器擷取即将要執行的請求。

  第④步:引擎通過下載下傳器中間件,将請求發送給下載下傳器下載下傳頁面。

  圖3-2中第⑤、⑥、⑦、⑧步,執行的是HTTP響應,傳遞和處理的是網站伺服器傳回的響應資料。

  第⑤步:頁面完成下載下傳後,下載下傳器會生成一個響應(Response)對象并将其發送給引擎。下載下傳後的資料會儲存于響應對象中。

  第⑥步:引擎接收來自下載下傳器的響應對象後,通過爬蟲中間件,将其發送給爬蟲(Spider)進行處理。

  第⑦步:爬蟲将抽取到的一條資料實體(Item)和新的請求(如下一頁的連結)發送給引擎。

  第⑧步:引擎将從爬蟲擷取到的Item發送給項目管道(Item Pipelines),項目管道實作資料持久化等功能。同時将新的請求發送給排程器,再從第②步開始重複執行,直到排程器中沒有更多的請求,引擎關閉該網站。

3.3 Scrapy安裝

  Scrapy作為一個強大的爬蟲架構,需要依賴于很多庫。幸運的是,前面我們安裝了Anaconda,它已經幫我們安裝好了Scrapy所有的依賴庫。是以,無論在哪個作業系統,安裝Scrapy就非常簡單了。

3.3.1 使用pip安裝Scrapy

  這裡還是使用pip安裝Scrapy架構,指令如下:

  

  >pip install scrapy

3.3.2 常見安裝錯誤

  因為系統環境的差異,在安裝Scrapy時,有時會出現各種意想不到的錯誤。例如,使用pip安裝Scrapy時遇到Microsoft Visual C++14.0 is required錯誤,如圖3-3所示。

帶你讀《從零開始學Scrapy網絡爬蟲》之三:Scrapy架構介紹第3章 Scrapy架構介紹

圖3-3 Scrapy安裝時出現的錯誤

  解決方法1

  如果使用pip安裝失敗,可以試着使用Conda安裝Scrapy,執行如下指令:

  >conda install -c scrapinghub scrapy

  安裝過程中,可能會有更新Conda的提示,根據提示選擇y就可以了,如圖3-4所示。

帶你讀《從零開始學Scrapy網絡爬蟲》之三:Scrapy架構介紹第3章 Scrapy架構介紹

圖3-4 使用Conda安裝Scrapy

  解決方法2

  根據提示可知,錯誤是由安裝Twisted導緻的,是以需要先安裝Twisted。Twisted的下載下傳位址為

http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted

,如圖3-5所示。根據Python和作業系統的版本,選擇對應的whl下載下傳檔案即可。其中,cp後面的數字是依賴的Python版本,amd64表示64位作業系統。下載下傳完後,定位到Twisted安裝包所在路徑,執行以下指令安裝Twisted。

  >pip install Twisted-19.2.0-cp35-cp35m-win_amd64.whl

帶你讀《從零開始學Scrapy網絡爬蟲》之三:Scrapy架構介紹第3章 Scrapy架構介紹

圖3-5 Twisted下載下傳頁

  成功安裝Twisted後,就可以使用pip指令安裝Scrapy了。

3.3.3 驗證安裝

  Scrapy安裝完成後,需要驗證安裝是否成功。在Python解釋器界面,輸入如下代碼:

  >import scrapy

  運作代碼後,如果沒有錯誤提示資訊,說明Scrapy已經安裝成功。

3.4 第一個網絡爬蟲

  正确安裝Scrapy架構後,就可以建立Scrapy項目,實作第一個網絡爬蟲了。

3.4.1 需求分析

  現要擷取起點中文網中小說熱銷榜的資料(網址為

https://www.qidian.com/rank/

hotsales?style=1&page=1),如圖3-6所示。每部小說提取内容為:小說名稱、作者、類型和形式。

帶你讀《從零開始學Scrapy網絡爬蟲》之三:Scrapy架構介紹第3章 Scrapy架構介紹

圖3-6 起點中文網中24小時熱銷榜

3.4.2 建立項目

  首先,建立一個爬取起點中文網小說熱銷榜的Scrapy項目步驟如下:

  (1)通過指令行定位到存放項目的目錄(如D盤的scrapyProject檔案夾)。

  >d:

  >cd d:scrapyProject

  (2)建立一個名為qidian_hot的項目,指令如下:

  >scrapy startproject qidian_hot

  回車,得到如圖3-7所示的建立成功資訊。

帶你讀《從零開始學Scrapy網絡爬蟲》之三:Scrapy架構介紹第3章 Scrapy架構介紹

圖3-7 生成Scrapy項目

  (3)檢視項目結構。

  在D盤的scrapyProject目錄下,自動生成了qidian_hot項目。使用PyCharm打開項目,如圖3-8所示為Scrapy項目的目錄結構,它對應于圖3-2中Scrapy的架構結構。

帶你讀《從零開始學Scrapy網絡爬蟲》之三:Scrapy架構介紹第3章 Scrapy架構介紹

圖3-8 Scrapy項目架構

  Scrapy中元件的本質是一個個Python源檔案,隻要在源檔案中實作各自的功能,爬蟲功能就能自動實作了。

3.4.3 分析頁面

  通過Chrome浏覽器的“開發者工具”,分析頁面的HTML代碼,确定資料解析的XPath方法步驟如下:

  (1)在Chrome浏覽器中,按F12鍵,顯示“開發者工具”欄。

  (2)輸入網址

https://www.qidian.com/rank/hotsales?style=1&page=1

,回車。

  (3)此時将顯示24小時熱銷榜頁面。選擇“開發者工具”欄,單擊最左邊的元素選擇按鈕,将光标移動到任一部小說内容上并選中,對應的HTML代碼

就會被高亮顯示,具體操作如圖3-9所示。

  (4)分析頁面結構。

  不難發現,每部小說都包裹在元素中,逐層展開,就能定位到小說名稱、作者、類型和形式。

  • 小說名稱:div(class=" book-mid-info ") → h4 → a → 文本。
  • 作者:div(class=" book-mid-info ") → p(第1個)→ a(第1個)→ 文本。
  • 類型:div(class=" book-mid-info ") → p(第1個)→ a(第2個)→ 文本。
  • 形式:div(class=" book-mid-info ") → p(第1個)→ span → 文本。

      使用XPath擷取小說内容,文法如下:

  • 小說名稱:div[@class=" book-mid-info "]/ h4/a/text()。
  • 作者:div[@class=" book-mid-info "]/ p[1]/a[1]/text()。
  • 類型:div[@class=" book-mid-info "]/ p[1]/a[2]/text()。
  • 形式:div[@class=" book-mid-info "]/ p[1]/span/text()。
    帶你讀《從零開始學Scrapy網絡爬蟲》之三:Scrapy架構介紹第3章 Scrapy架構介紹

圖3-9 擷取小說内容對應的HTML代碼

3.4.4 實作Spider爬蟲功能

  下面實作爬蟲功能。由圖3-8得知,爬蟲功能是在spiders目錄下實作的。實作的步驟如下:

  (1)在spiders目錄下建立爬蟲源檔案qidian_hot_spider.py。

  (2)在qidian_hot_spider.py檔案中定義HotSalesSpider類,實作爬蟲功能。

  實作代碼如下:

  #--coding:utf-8--

  from scrapy import Request

  from scrapy.spiders import Spider

  class HotSalesSpider(Spider):

   #定義爬蟲名稱

   name = 'hot'

   #起始的URL清單

   start_urls = ["https://www.qidian.com/rank/hotsales?style=1"]

   #解析函數

   def parse(self, response):

   #使用xpath定位到小說内容的div元素,儲存到清單中

   list_selector = response.xpath("//div[@class='book-mid-info']")

   #依次讀取每部小說的元素,從中擷取名稱、作者、類型和形式

   for one_selector in list_selector:

   #擷取小說名稱

   name = one_selector.xpath("h4/a/text()").extract()[0]

   #擷取作者

   author = one_selector.xpath("p[1]/a[1]/text()").extract()[0]

   #擷取類型

   type = one_selector.xpath("p[1]/a[2]/text()").extract()[0]

   #擷取形式(連載/完本)

   form = one_selector.xpath("p[1]/span/text()").extract()[0]

   #将爬取到的一部小說儲存到字典中

   hot_dict = {"name":name, #小說名稱

   "author":author, #作者

   "type":type, #類型

   "form":form} #形式

   #使用yield傳回字典

   yield hot_dict

  以上代碼雖然添加了不少注釋,但相信大家了解起來還是有點困難。不用擔心,下一章将會詳細講解,這裡先成功運作一個爬蟲,建立信心和整體認識即可。

  下面簡單說明HotSalesSpider的實作方法。

  • 爬蟲所有的功能都是在類HotSalesSpider中實作的,它的基類為Spider。
  • 類中定義了兩個屬性:name和start_urls。其中,name為爬蟲名稱,運作爬蟲時需要用到;start_urls中存儲的是目标網址的清單。如想要爬取兩頁熱銷榜的小說資訊,可以将start_urls修改為:

  start_urls = ["https://www.qidian.com/rank/hotsales?style=1",

   "https://www.qidian.com/rank/hotsales?style=1&page=3"]

  類中定義了一個方法parse(),這是爬蟲的核心方法,通常完成兩個任務:

  • 提取頁面中的資料。
  • 提取頁面中的連結,并産生對連結頁面的下載下傳請求。

3.4.5 運作爬蟲

  代碼完成後,就可以使用指令執行爬蟲了。

  (1)通過指令行定位到qidian_hot項目目錄下(很重要)。

  >cd D:scrapyProjectqidian_hot

  (2)輸入爬蟲執行指令(hot為爬蟲名,hot.csv為儲存資料的檔案名)。

  >scrapy crawl hot -o hot.csv

  回車,爬蟲程式開始執行,指令提示符中會不斷顯示爬蟲執行時的資訊。爬蟲執行完後,資料會自動儲存于hot.csv檔案中。打開hot.csv檔案檢視資料,如圖3-10所示。

帶你讀《從零開始學Scrapy網絡爬蟲》之三:Scrapy架構介紹第3章 Scrapy架構介紹

圖3-10 生成的CSV檔案

 需要特别注意的是,爬蟲程式不能頻繁執行。因為網站一般都有反爬蟲措施,如頻繁執行會被認定是爬蟲程式,網站就會封掉你的IP,禁止通路。關于這個問題,下一章會給出解決方案。

3.4.6 常見問題

  在生成的CSV檔案中,有時會發現資料之間會有空行間隔,如圖3-11所示。

帶你讀《從零開始學Scrapy網絡爬蟲》之三:Scrapy架構介紹第3章 Scrapy架構介紹

圖3-11 有空行的CSV檔案

  原因:這是Scrapy架構預設的組織形式,即資料之間以空行間隔。

  解決方法:修改預設的組織形式。在Anaconda中找到exporters.py(筆者的是在C:Anaconda3Libsite-packagesscrapy目錄下)。打開源檔案,在類CsvItemExporter中添加一行代碼,如圖3-12所示。儲存檔案,重新運作爬蟲程式。

帶你讀《從零開始學Scrapy網絡爬蟲》之三:Scrapy架構介紹第3章 Scrapy架構介紹

圖3-12 手動添加換行形式

3.5 本 章 小 結

  本章首先介紹了網絡爬蟲的原理;接着介紹了Scrapy架構結構、執行流程及安裝過程;最後以爬取起點中文網小說24小時熱銷榜為例,實作了第一個Scrapy爬蟲案例,讓大家對Scrapy爬蟲有個初步的認識。