1. 程式人生 > >Scrapy 框架 入門教程

Scrapy 框架 入門教程

lin directory 生成 cal build isbn int path this

Scrapy入門教程

在本篇教程中,我已經安裝好Scrapy

本篇教程中將帶您完成下列任務:

  1. 創建一個Scrapy項目
  2. 定義提取的Item
  3. 編寫爬取網站的 spider 並提取 Item
  4. 編寫 Item Pipeline 來存儲提取到的Item(即數據)

創建項目

在開始爬取之前,您必須創建一個新的Scrapy項目。 進入您打算存儲代碼的目錄中,運行下列命令:

scrapy startproject 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代碼的目錄.

定義Item

Item 是保存爬取到的數據的容器;其使用方法和python字典類似, 並且提供了額外保護機制來避免拼寫錯誤導致的未定義字段錯誤。

首先根據需要從dmoz.org獲取到的數據對item進行建模。 我們需要從dmoz中獲取名字,url,以及網站的描述。 對此,在item中定義相應的字段。編輯 tutorial 目錄中的 items.py 文件:

import scrapy

class DmozItem(scrapy.Item):
    title = scrapy.Field()
    link = scrapy.Field()
    desc = scrapy.Field()

一開始這看起來可能有點復雜,但是通過定義item, 您可以很方便的使用Scrapy的其他方法。而這些方法需要知道您的item的定義。

編寫第一個爬蟲(Spider)

Spider是用戶編寫用於從單個網站(或者一些網站)爬取數據的類。

其包含了一個用於下載的初始URL,如何跟進網頁中的鏈接以及如何分析頁面中的內容, 提取生成 item 的方法。

為了創建一個Spider,您必須繼承 scrapy.Spider 類, 且定義以下三個屬性:

  • name: 用於區別Spider。 該名字必須是唯一的,您不可以為不同的Spider設定相同的名字。
  • start_urls: 包含了Spider在啟動時進行爬取的url列表。 因此,第一個被獲取到的頁面將是其中之一。 後續的URL則從初始的URL獲取到的數據中提取。
  • parse() 是spider的一個方法。 被調用時,每個初始URL完成下載後生成的 Response 對象將會作為唯一的參數傳遞給該函數。 該方法負責解析返回的數據(response data),提取數據(生成item)以及生成需要進一步處理的URL的 Request 對象。

以下為我們的第一個Spider代碼,保存在 tutorial/spiders 目錄下的 dmoz_spider.py 文件中:

import scrapy

class DmozSpider(scrapy.Spider):
    name = "dmoz"
    allowed_domains = ["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]
        with open(filename, wb) as f:
            f.write(response.body)

爬取

進入項目的根目錄,執行下列命令啟動spider:

scrapy crawl dmoz

crawl dmoz 啟動用於爬取 dmoz.org 的spider,您將得到類似的輸出:

2014-01-23 18:13:07-0400 [scrapy] INFO: Scrapy started (bot: tutorial)
2014-01-23 18:13:07-0400 [scrapy] INFO: Optional features available: ...
2014-01-23 18:13:07-0400 [scrapy] INFO: Overridden settings: {}
2014-01-23 18:13:07-0400 [scrapy] INFO: Enabled extensions: ...
2014-01-23 18:13:07-0400 [scrapy] INFO: Enabled downloader middlewares: ...
2014-01-23 18:13:07-0400 [scrapy] INFO: Enabled spider middlewares: ...
2014-01-23 18:13:07-0400 [scrapy] INFO: Enabled item pipelines: ...
2014-01-23 18:13:07-0400 [dmoz] INFO: Spider opened
2014-01-23 18:13:08-0400 [dmoz] DEBUG: Crawled (200) <GET http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/> (referer: None)
2014-01-23 18:13:09-0400 [dmoz] DEBUG: Crawled (200) <GET http://www.dmoz.org/Computers/Programming/Languages/Python/Books/> (referer: None)
2014-01-23 18:13:09-0400 [dmoz] INFO: Closing spider (finished)

查看包含 [dmoz] 的輸出,可以看到輸出的log中包含定義在 start_urls 的初始URL,並且與spider中是一一對應的。在log中可以看到其沒有指向其他頁面( (referer:None) )。

除此之外,更有趣的事情發生了。就像我們 parse 方法指定的那樣,有兩個包含url所對應的內容的文件被創建了: Book , Resources

剛才發生了什麽?

Scrapy為Spider的 start_urls 屬性中的每個URL創建了 scrapy.Request 對象,並將 parse 方法作為回調函數(callback)賦值給了Request。

Request對象經過調度,執行生成 scrapy.http.Response 對象並送回給spider parse() 方法。

提取Item

這裏給出XPath表達式的例子及對應的含義:

  • /html/head/title: 選擇HTML文檔中 <head> 標簽內的 <title> 元素
  • /html/head/title/text(): 選擇上面提到的 <title> 元素的文字
  • //td: 選擇所有的 <td> 元素
  • //div[@class="mine"]: 選擇所有具有 class="mine" 屬性的 div 元素

Selector有四個基本的方法(點擊相應的方法可以看到詳細的API文檔):

  • xpath(): 傳入xpath表達式,返回該表達式所對應的所有節點的selector list列表 。
  • css(): 傳入CSS表達式,返回該表達式所對應的所有節點的selector list列表.
  • extract(): 序列化該節點為unicode字符串並返回list。
  • re(): 根據傳入的正則表達式對數據進行提取,返回unicode字符串list列表。

在Shell中嘗試Selector選擇器

為了介紹Selector的使用方法,接下來我們將要使用內置的 Scrapy shell 。Scrapy Shell需要您預裝好IPython(一個擴展的Python終端)。

您需要進入項目的根目錄,執行下列命令來啟動shell:

scrapy shell "http://www.dmoz.org/Computers/Programming/Languages/Python/Books/"

註意:當您在終端運行Scrapy時,請一定記得給url地址加上引號,否則包含參數的url(例如 & 字符)會導致Scrapy運行失敗。

shell的輸出類似:

[ ... Scrapy log here ... ]

2014-01-23 17:11:42-0400 [default] DEBUG: Crawled (200) <GET http://www.dmoz.org/Computers/Programming/Languages/Python/Books/> (referer: None)
[s] Available Scrapy objects:
[s]   crawler    <scrapy.crawler.Crawler object at 0x3636b50>
[s]   item       {}
[s]   request    <GET http://www.dmoz.org/Computers/Programming/Languages/Python/Books/>
[s]   response   <200 http://www.dmoz.org/Computers/Programming/Languages/Python/Books/>
[s]   settings   <scrapy.settings.Settings object at 0x3fadc50>
[s]   spider     <Spider default at 0x3cebf50>
[s] Useful shortcuts:
[s]   shelp()           Shell help (print this help)
[s]   fetch(req_or_url) Fetch request (or URL) and update local objects
[s]   view(response)    View response in a browser

In [1]:

當shell載入後,您將得到一個包含response數據的本地 response 變量。輸入 response.body 將輸出response的包體, 輸出 response.headers 可以看到response的包頭。

更為重要的是,當輸入 response.selector 時, 您將獲取到一個可以用於查詢返回數據的selector(選擇器), 以及映射到 response.selector.xpath()response.selector.css() 的 快捷方法(shortcut): response.xpath()response.css()

同時,shell根據response提前初始化了變量 sel 。該selector根據response的類型自動選擇最合適的分析規則(XML vs HTML)。

讓我們來試試:

In [1]: response.xpath(//title)
Out[1]: [<Selector xpath=//title data=u<title>Open Directory - Computers: Progr>]

In [2]: response.xpath(//title).extract()
Out[2]: [u<title>Open Directory - Computers: Programming: Languages: Python: Books</title>]

In [3]: response.xpath(//title/text())
Out[3]: [<Selector xpath=//title/text() data=uOpen Directory - Computers: Programming:>]

In [4]: response.xpath(//title/text()).extract()
Out[4]: [uOpen Directory - Computers: Programming: Languages: Python: Books]

In [5]: response.xpath(//title/text()).re((\w+):)
Out[5]: [uComputers, uProgramming, uLanguages, uPython]

在我們的spider中加入這段代碼:

一般來說,Spider將會將爬取到的數據以 Item 對象返回。所以為了將爬取的數據返回,我們最終的代碼將是:

import scrapy

from tutorial.items import DmozItem

class DmozSpider(scrapy.Spider):
    name = "dmoz"
    allowed_domains = ["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):
        for sel in response.xpath(//ul/li):
            item = DmozItem()
            item[title] = sel.xpath(a/text()).extract()
            item[link] = sel.xpath(a/@href).extract()
            item[desc] = sel.xpath(text()).extract()
            yield item

現在嘗試再次爬取dmoz.org,您將看到爬取到的網站信息被成功輸出:

scrapy crawl dmoz
[dmoz] DEBUG: Scraped from <200 http://www.dmoz.org/Computers/Programming/Languages/Python/Books/>
     {desc: [u - By David Mertz; Addison Wesley. Book in progress, full text, ASCII format. Asks for feedback. [author website, Gnosis Software, Inc.\n],
      link: [uhttp://gnosis.cx/TPiP/],
      title: [uText Processing in Python]}
[dmoz] DEBUG: Scraped from <200 http://www.dmoz.org/Computers/Programming/Languages/Python/Books/>
     {desc: [u - By Sean McGrath; Prentice Hall PTR, 2000, ISBN 0130211192, has CD-ROM. Methods to build XML applications fast, Python tutorial, DOM and SAX, new Pyxie open source XML processing library. [Prentice Hall PTR]\n],
      link: [uhttp://www.informit.com/store/product.aspx?isbn=0130211192],
      title: [uXML Processing with Python]}

保存爬取到的數據

scrapy crawl dmoz -o items.json

該命令將采用 JSON 格式對爬取的數據進行序列化,生成 items.json 文件。

Scrapy 框架 入門教程