天天看點

2.python開源——scrapy使用

此環節是在MAC OS中進行搭建

安裝scrapy

pip install scrapy  即可快速完成安裝

建立項目:

$ scrapy startproject tutorial

輸出如下:

New Scrapy project 'tutorial', using template directory '/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/scrapy/templates/project', created in:

    /Users/huilinwang/tutorial

You can start your first spider with:

    cd tutorial

    scrapy genspider example example.com

該目錄下結構如下:

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()

編寫第一個爬蟲(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.spiders.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)

name屬性很重要,不同spider不能使用相同的name

start_urls是spider抓取網頁的起始點,可以包括多個url

parse方法是spider抓到一個網頁以後預設調用的callback,避免使用這個名字來定義自己的方法。

當spider拿到url的内容以後,會調用parse方法,并且傳遞一個response參數給它,response包含了抓到的網頁的内容,在parse方法裡,你可以從抓到的網頁裡面解析資料。上面的代碼隻是簡單地把網頁内容儲存到檔案。

爬取

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

scrapy crawl dmoz

        有兩個包含url所對應的内容的檔案被建立了: Book , Resources 。

       Scrapy為Spider的 start_urls 屬性中的每個URL建立了 scrapy.Request 對象,并将 parse 方法作為回調函數(callback)指派給了Request。

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

提取Item

從網頁中提取資料有很多方法。Scrapy使用了一種基于 XPath 和 CSS 表達式機制: Scrapy Selectors 。

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

xpath(): 傳入xpath表達式,傳回該表達式所對應的所有節點的selector list清單 。

css(): 傳入CSS表達式,傳回該表達式所對應的所有節點的selector list清單.

extract(): 序列化該節點為unicode字元串并傳回list。

re(): 根據傳入的正規表達式對資料進行提取,傳回unicode字元串list清單。

在Shell中嘗試Selector選擇器

進入項目的根目錄,執行下列指令來啟動shell:

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

當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)。

提取資料

嘗試從這些頁面中提取些有用的資料

        在終端中輸入 response.body 來觀察HTML源碼并确定合适的XPath表達式。不過,這任務非常無聊且不易。您可以考慮使用Firefox的Firebug擴充來使得工作更為輕松。

檢視了網頁的源碼後,您會發現網站的資訊是被包含在 第二個 <ul> 元素中。

我們可以通過這段代碼選擇該頁面中網站清單裡所有 <li> 元素:

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

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):

        for sel in response.xpath('//ul/li'):

            title = sel.xpath('a/text()').extract()

            link = sel.xpath('a/@href').extract()

            desc = sel.xpath('text()').extract()

            print title, link, desc

現在嘗試再次爬取dmoz.org,您将看到爬取到的網站資訊被成功輸出

/ul/li表示選擇所有的ul标簽下的li标簽

a/@href表示選擇所有a标簽的href屬性

a/text()表示選擇a标簽文本

a[@href="abc" target="_blank" rel="external nofollow" ]表示選擇所有href屬性是abc的a标簽

儲存爬取到的資料

最簡單存儲爬取的資料的方式是使用 Feed exports:

scrapy crawl dmoz -o items.json

該指令将采用 JSON 格式對爬取的資料進行序列化,生成 items.json 檔案。