1. 程式人生 > 實用技巧 >Scrapy網路爬蟲簡介

Scrapy網路爬蟲簡介

Scrapy 是一個為了爬取網站資料、提取結構性資料而編寫的應用框架,可以應用在包括資料探勘、資訊處理或儲存歷史資料等一系列的程式中。

1. Scrapy 架構

Scrapy 的整體架構由 Scrapy 引擎(ScrapyEngine)、排程器(Scheduler)、下載器(Downloader)、爬蟲(Spiders)和資料項管道(itemPipeline)5 個元件組成。圖 1 展示了各個元件的互動關係和系統中的資料流。

Scrapy架構
圖 1 Scrapy 架構

Scrapy 的架構由以下 5 個元件和兩個中介軟體構成。

元件/中介軟體 作用
Scrapy 引擎(ScrapyEngine) 是整個系統的核心,負責控制資料在整個元件中的流動,並在相應動作發生時觸發事件。
排程器(Scheduler) 管理 Request 請求的出入棧,去除重複的請求。排程器從 Scrapy 引擎接收請求,並將請求加入請求佇列,以便在後期需要的時候提交給 Scrapy 引擎。
下載器(Downloader) 負責獲取頁面資料,並通過 Scrapy 引擎提供給網路爬蟲。
網路爬蟲(Spiders) 是 Scrapy 使用者編寫的用於分析結果並提取資料項或跟進的 URL 的類。每個爬蟲負責處理一個(或者一組)特定網站。
資料項管道(ItemPipeline) 負責處理被爬蟲提取出來的資料項。典型的處理有清理、驗證及持久化。
下載器中介軟體 是引擎和下載器之間的特定介面,處理下載器傳遞給引擎的結果。其通過插入自定義程式碼來擴充套件下載器的功能。
爬蟲中介軟體 是引擎和爬蟲之間的特定介面,用來處理爬蟲的輸入,並輸出資料項。其通過插入自定義程式碼來擴充套件爬蟲的功能。

Scrapy 中的資料流由 Scrapy 引擎控制,整體的流程如下。

1)Scrapy 引擎開啟一個網站,找到處理該網站的爬蟲,並詢問爬蟲第一次要爬取的 URL。

2)Scrapy 引擎從爬蟲中獲取第一次要爬取的 URL,並以 Request 方式傳送給排程器。

3)Scrapy 引擎向排程器請求下一個要爬取的 URL。

4)排程器返回下一個要爬取的 URL 給 Scrapy 引擎,Scrapy 引擎將 URL 通過下載器中介軟體轉發給下載器。

5)下載器下載給定的網頁,下載完畢後,生成一個該頁面的結果,並將其通過下載器中介軟體傳送給 Scrapy 引擎。

6)Scrapy 引擎從下載器中接收到下載結果,並通過爬蟲中介軟體傳送給爬蟲進行處理。

7)爬蟲對結果進行處理,並返回爬取到的資料項及需要跟進的新的 URL 給 Scrapy 引擎。

8)Scrapy 引擎將爬取到的資料項傳送給資料項管道,將爬蟲生成的新的請求傳送給排程器。

9)從步驟(2)開始重複,直到排程器中沒有更多的請求,Scrapy 引擎關閉該網站。

2. Scrapy 應用案例

如果需要從某個網站中獲取資訊,但該網站未提供 API 或能通過程式獲取資訊的機制,Scrapy 就可以用來完成這個任務。

本節通過一個具體應用來講解使用 Scrapy 抓取資料的方法。本應用要獲取在噹噹網站銷售的有關“Python核心程式設計”和“Python 基礎教程”的所有書籍的 URL、名字、描述及價格等資訊。

1)建立專案

在開始爬取之前,必須建立一個新的 Scrapy 專案。進入打算儲存程式碼的目錄中,執行下列命令。

scrapy startproject tutorial

該命令將會建立包含下列內容的 tutorial 目錄。

tutorial/
scrapy.cfg
tutorial/
—init_.py
items.py
pipelines.py
settings.py
spiders/
_init_.py

這些檔案分別如下。

名稱 說明
scrapy.cfg 專案的配置檔案
tutorial/ 專案的 Python 模組,之後將在此加入程式碼
tutorial/items.py 專案中的 item 檔案
tutorial/pipelines.py 專案中的 pipelines 檔案
tutorial/settings.py 專案的設定檔案
tutorial/spiders/ 放置 Spider 程式碼的目錄

2)定義 Item

在 Scrapy 中,Item 是儲存爬取到的資料的容器,其使用方法和 Python 字典類似,並且提供了額外保護機制來避免拼寫錯誤導致的未定義欄位錯誤。

一般來說,Item 可以用 scrapy.item.Item 類來建立,並且用 scrapy.item.Field 物件來定義屬性。

如果想要從網頁抓取的每一本書的內容為書名(Title)、連結(Link)、簡介(Description)和價格(Price),則根據要抓取的內容,可構建 Item 的模型。

修改 tutorial 目錄下的 items.py 檔案,在原來的類後面新增新的類。因為要抓噹噹網站的內容,所以我們可以將其命名為 DangItem,並定義相應的欄位。編輯 tutorial 目錄中的 items.py 檔案。

import scrapy

class DangItem(scrapy.Item):
title = scrapy.Field()
link. = scrapy.Field()
dese = scrapy.Field()
price = scrapy.Filed()

3)編寫 Spider

Spider 是使用者編寫的用於從單個(或一組)網站爬取資料的類。它包含了一個用於下載的初始 URL,負責跟進網頁中的連結的方法,負責分析頁面中的內容的方法,以及負責提取生成的 Item 的方法。

建立的 Spider 必須繼承 scrapy.Spider 類,並且需要定義以下 3 個屬性。

  • name:Spider 的名字,必須是唯一的,不可以為不同的 Spider 設定相同的名字。
  • start_urls:包含了 Spider 在啟動時進行爬取的 URL 列表。第一個被獲取到的頁面是其中之一,後續的 URL 則從初始的 URL 獲取到的資料中提取。
  • parse():是一個用來解析下載返回資料的方法。被呼叫時,每個初始 URL 完成下載後生成的 Response 物件將會作為唯一的引數傳遞給該方法。該方法將負責解析返回的資料(Response),提取資料生成 Item,以及生成需要進一步處理的 URL 的 Request 物件。

以下是我們編寫的 Spider 程式碼,儲存在 tutorial/spiders 目錄下的 dang_spider.py 檔案中。

  1. importscrapy
  2. classDangSpider(scrapy.Spider):
  3. name=“dangdang”
  4. allowed_domains=[“dangdang.com”]
  5. start_urls=[
  6. http://search.dangdang.com/?key=python核心程式設計&act=click,
  7. http://search.dangdang.com/?key=python基礎教程&act=click]
  8. def parse(self,response):
  9. filename=response.url.split(“/“)[-2]
  10. with open(filename,’wb’)as f:
  11. f.write(response.body)

4)爬取

進入專案的根目錄,執行下列命令啟動 Spider。

scrapy crawl dmoz

該命令將會啟動用於爬取 dangdang.com 的 Spider,系統將會產生類似的輸出。

2017-01-23 18:13:07-0400 [scrapy] INFO: Scrapy started (bot: tutorial)
2017-01-23 18:13:07-0400 [scrapy] INFO: Optional features available: …
2017-01-23 18:13:07-0400 [scrapy] INFO: Overridden settings: {}
2017-01-23 18:13:07-0400 [scrapy] INFO: Enabled extensions: …
2017-01-23 18:13:07-0400 [scrapy] INFO: Enabled downloader middlewares: …
2017-01-23 18:13:07-0400 [scrapy] INFO: Enabled spider middlewares: …
2017-01-23 18:13:07-0400 [scrapy] INFO: Enabled item.pipelines: …
2017-01-23 18:13:07-0400 [dangdang] INFO: Spider opened
2017-01-23 18:13:08-0400: [dangdang] DEBUG: Crawled (200)<GET http://search.
langdang.com/?key=python 核心程式設計&act=click> (referer: None)
2017-01-23 18:13:08-0400 [dangdang] DEBUG: Crawled (200)<GET http://search.
dangdang.com/?key=python 基礎教程&act=click> (referer: None)
2017-01-23 18:13:09-0400 [dangdang] INFO: Closing spider (finished)

檢視包含“dangdang”的輸出,可以看到,輸出的 log 中包含定義在 start_urls 中的初始 URL,並且與 Spider 中是一一對應的。在 log 中可以看到其沒有指向其他頁面(referer:None)。

除此之外,根據parse方法,有兩個包含URL所對應的內容的檔案被建立了,即 Python 核心程式設計和 Python 基礎教程。

在執行上面的 shell 命令時,scrapy 會建立一個 scrapy.http.Request 物件,將 start_url 傳遞給 它,抓取完畢後,回撥 parse 函式。

5)提取 Item

在抓取任務中,一般不會只抓取網頁,而是要將抓取的結果直接變成結構化資料。根據前面定義的 Item 資料模型,我們就可以修改 Parser,並用 Scmpy 內建的 XPath 解析 HTML 文件。

通過觀察噹噹網頁原始碼,我們發現有關書籍的資訊都是包含在第二個<ul>元素中的,並且相關的書籍被用列表方式展現出來。所以,我們可以用下述程式碼選擇該網頁中書籍列表裡所有<Vli>元素,每一個元素對應一本書。選擇<li>元素的函式是 response.xpath(“//ul/li”)。

  1. fromscrapy.spiderimportbpiaer
  2. fromscrapy.selectorimportSelector
  3. fromtutorial.itemsimportDangItem
  4. classDangSpider(Spider)
  5. name=“dangdang”
  6. allowed_domains=[“dangdang.com”]
  7. start_urls=[
  8. http://search.dangdang.com/?key=python 核心程式設計&act=click,
  9. http://search.dangdang.com/?key=python 基礎教程&act=click ]
  10. defparse(self,response):
  11. sel=Selector(response)
  12. sites=sel.xpath(‘//ul/li)
  13. items =[]
  14. for site in sites:
  15. item = DangItem()
  16. item[‘title‘] = site.xpath (‘a/text()‘).extract() item[‘link‘] = site.xpath (‘a/@href‘).extract() item[‘desc‘] = site.xpath (‘text()‘).extract()
  17. item[‘rice‘] = site.xpath(‘text()‘) .extract() items.append(item)
  18. return items

增加 json 選項把結果儲存為 JSON 格式,執行下列命令啟動 Scrapy。

scrapy crawl dangdang -o items.json

該命名將採用 JSON 格式對爬取的資料進行序列化,並生成 items.json 檔案。

大資料零基礎快速入門教程

Java基礎教程

9.通過網路爬蟲採集大資料
10.Scrapy網路爬蟲簡介
11.大資料預處理架構和方法