1. 程式人生 > >scrapy 1.5 第一篇 初窺scrapy

scrapy 1.5 第一篇 初窺scrapy

    我想要在開始之前先和閱讀這篇文章的朋友們說上幾句話。首先,這篇文章內,我挑選一部分官方文件中重要的內容進行翻譯。其次,我本人的英語水平和程式設計水平也屬於渣渣中的渣渣,有什麼問題,請務必在評論中指出。

    一、如何開始你的第一個scrapy專案?

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

    scrapy startproject tutorial

        這條命令將會在目錄下建立一個名為tutorial的資料夾,資料夾內部的內容如下:

tutorial/
    scrapy.cfg            # 專案的配置檔案
    tutorial/             # 用來放你py程式碼的地方
        __init__.py

        items.py          # 用來定義你抓取內容的欄位

        middlewares.py    # 中間器

        pipelines.py      # 管道檔案

        settings.py       # 設定

        spiders/          # 放爬蟲檔案的資料夾
            __init__.py
    

    二、你的第一隻爬蟲!

    爬蟲是你定義的一個用於在一個或者一組網頁上抓取資料的類,他們必須繼承scrapy.spider類。同時,這個類也應該定義一個初始的request,如何在現有網頁中提取後續連結,在下載完的網頁中提取資料等方法。

    下面是我們的第一個爬蟲程式碼,把它儲存在一個被命名為quotes_spider.py的檔案中,然後放置在你的專案的tutorial/spiders下。

import scrapy


class QuotesSpider(scrapy.Spider):        #QuotesSpider類必須要繼承scrapy.Spider類,你可以在這個類裡面定義一些方法和屬性。
    name = "quotes"                       #name屬性,用來區分爬蟲,在一個專案中,你不能用同樣的名稱來命名不同的爬蟲。

    def start_requests(self):             #必須返回一個可迭代的物件,或者寫一個生成器。你的爬蟲將會從這個類開始抓取。
        urls = [                          #初始url,這裡不解釋了,這兩個網站是給你做練習用的,原來中文教程的DMOZ掛了。
            'http://quotes.toscrape.com/page/1/',
            'http://quotes.toscrape.com/page/2/',
        ]
        for url in urls:                
            yield scrapy.Request(url=url, callback=self.parse) 

    def parse(self, response):           #parse方法用來處理request返回的結果。關於這一部分的一些內容,我在後面詳細介紹。
        page = response.url.split("/")[-2]
        filename = 'quotes-%s.html' % page
        with open(filename, 'wb') as f:
            f.write(response.body)
        self.log('Saved file %s' % filename)

    三、執行你的第一個爬蟲!

    想要執行上面的程式碼,你只需要進入目錄下的cmd介面,然後執行scrapy crawl quotes命令就可以了。

    這條命令會啟動name屬性是quotes的爬蟲(也就是你剛剛寫進去的那個),之後你就會看見,你的介面上刷出像是下面的東西:

... (省略了一丟丟東西)
2016-12-16 21:24:05 [scrapy.core.engine] INFO: Spider opened
2016-12-16 21:24:05 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min)
2016-12-16 21:24:05 [scrapy.extensions.telnet] DEBUG: Telnet console listening on 127.0.0.1:6023
2016-12-16 21:24:05 [scrapy.core.engine] DEBUG: Crawled (404) <GET http://quotes.toscrape.com/robots.txt> (referer: None)
2016-12-16 21:24:05 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://quotes.toscrape.com/page/1/> (referer: None)
2016-12-16 21:24:05 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://quotes.toscrape.com/page/2/> (referer: None)
2016-12-16 21:24:05 [quotes] DEBUG: Saved file quotes-1.html
2016-12-16 21:24:05 [quotes] DEBUG: Saved file quotes-2.html
2016-12-16 21:24:05 [scrapy.core.engine] INFO: Closing spider (finished)
...

    現在看你的根目錄下,是不是多了兩個檔案呢?如果你問我為什麼沒有對這兩個html檔案做更進一步的處理的話,我會在接下來一部分做這一步的。

    四、剛剛發生了什麼?

    scrapy將spider中start_requests方法返回的scrapy.Request物件列入工作表內。為每一個返回的內容,例項化了一個Response物件,然後引用一個關聯的方法(例子中,我們使用的是parse方法),將response作為內容傳遞過去。

    五、start_request的作弊寫法!

    你可以將包含了一大串url的start_url作為spider類的一個類屬性寫在類裡面,這樣你就不用實現從url中生成scrapy.Response物件的start_request方法啦!scrapy會自動的讀取這個列表中的url,然後呼叫預設的start_request方法來為你的爬蟲建立初始的request。是不是輕鬆加愉快?

    你也許會疑惑,那麼我怎麼處理返回的資料呢?這都不是問題。你只需要定義一個parse方法在類內,scrapy會自動呼叫這個方法來進行處理。(即使你沒有明確告訴scrapy!)則是因為parse方法是scrapy預設的,只要沒有明確定義回撥方法,那麼scrapy就會預設使用parse。