(三) Spider

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

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

Spider的創建

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

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

Spider示例

示例1:

import scrapy

class MySpider(scrapy.Spider):
    name = '[example.com](http://example.com/)'
    allowed_domains = ['[example.com](http://example.com/)']
    start_urls = [
        '[http://www.example.com/1.html](http://www.example.com/1.html)',
        '[http://www.example.com/2.html](http://www.example.com/2.html)',
        '[http://www.example.com/3.html](http://www.example.com/3.html)',
    ]

    def parse(self, response):
        self.log('A response from %s just arrived!' % response.url)

示例2:

import scrapy
from myproject.items import MyItem

class MySpider(scrapy.Spider):
    name = '[example.com](http://example.com/)'
    allowed_domains = ['[example.com](http://example.com/)']
    start_urls = [
        '[http://www.example.com/1.html](http://www.example.com/1.html)',
        '[http://www.example.com/2.html](http://www.example.com/2.html)',
        '[http://www.example.com/3.html](http://www.example.com/3.html)',
    ]

    def parse(self, response):
        sel = scrapy.Selector(response)
        for h3 in response.xpath('//h3').extract():
            yield MyItem(title=h3)

        for url in response.xpath('//a/@href').extract():
            yield scrapy.Request(url, callback=self.parse)

Spider的業務循環

對spider來說,爬取的循環類似下文:

  1. 以初始的URL初始化Request,並設置回調函數。 當該request下載完畢並返回時,將生成response,並作爲參數傳給該回調函數。

    spider中初始的request是通過調用 start_requests() 來獲取的。 start_requests() 讀取 start_urls 中的URL, 並以 parse 爲回調函數生成 Request

  2. 在回調函數內分析返回的(網頁)內容,返回 Item 對象或者 Request 或者一個包括二者的可迭代容器。 返回的Request對象之後會經過Scrapy處理,下載相應的內容,並調用設置的callback函數(函數可相同)。

  3. 在回調函數內,您可以使用 選擇器(Selectors) (您也可以使用BeautifulSoup, lxml 或者您想用的任何解析器) 來分析網頁內容,並根據分析的數據生成item。

  4. 最後,由spider返回的item將被存到數據庫(由某些 Item Pipeline 處理)或使用 Feed exports 存入到文件中。

雖然該循環對任何類型的spider都(多少)適用,但Scrapy仍然爲了不同的需求提供了多種默認spider。

Spider類其他屬性方法

allowed_domains

可選。包含了spider允許爬取的域名(domain)列表(list)。 當 OffsiteMiddleware 啓用時, 域名不在列表中的URL不會被跟進。

start_requests()

該方法必須返回一個可迭代對象(iterable)。該對象包含了spider用於爬取的第一個Request。

當spider啓動爬取並且未制定URL時,該方法被調用。 當指定了URL時,make_requests_from_url() 將被調用來創建Request對象。 該方法僅僅會被Scrapy調用一次,因此您可以將其實現爲生成器。

該方法的默認實現是使用 start_urls 的url生成Request。

如果您想要修改最初爬取某個網站的Request對象,您可以重寫(override)該方法。 例如,如果您需要在啓動時以POST登錄某個網站,你可以這麼寫:

def start_requests(self):
    return [scrapy.FormRequest("[http://www.example.com/login](http://www.example.com/login)",
                               formdata={'user': 'john', 'pass': 'secret'},
                               callback=self.logged_in)]

def logged_in(self, response):
    # here you would extract links to follow and return Requests for
    # each of them, with another callback
    pass

make_requests_from_url(url)

該方法接受一個URL並返回用於爬取的 Request 對象。 該方法在初始化request時被 start_requests() 調用,也被用於轉化url爲request。

默認未被複寫(overridden)的情況下,該方法返回的Request對象中, parse() 作爲回調函數,dont_filter參數也被設置爲開啓。 (詳情參見 Request).

closed(reason)

當spider關閉時,該函數被調用。 該方法提供了一個替代調用signals.connect()來監聽 spider_closed 信號的快捷方式。

Spider子類

CrawlSpider

class scrapy.contrib.spiders.CrawlSpider
爬取一般網站常用的spider。其定義了一些規則(rule)來提供跟進link的方便的機制。 也許該spider並不是完全適合您的特定網站或項目,但其對很多情況都使用。 因此您可以以其爲起點,根據需求修改部分方法。當然您也可以實現自己的spider。

XMLFeedSpider

class scrapy.contrib.spiders.XMLFeedSpider
XMLFeedSpider被設計用於通過迭代各個節點來分析XML源(XML feed)。 迭代器可以從 iternodes , xml , html 選擇。 鑑於 xml 以及 html 迭代器需要先讀取所有DOM再分析而引起的性能問題, 一般還是推薦使用 iternodes 。 不過使用 html 作爲迭代器能有效應對錯誤的XML。

CSVFeedSpider

class scrapy.contrib.spiders.CSVFeedSpider
該spider除了其按行遍歷而不是節點之外其他和XMLFeedSpider十分類似。 而其在每次迭代時調用的是 parse_row()

SitemapSpider

class scrapy.contrib.spiders.SitemapSpider
SitemapSpider使您爬取網站時可以通過 Sitemaps 來發現爬取的URL。

其支持嵌套的sitemap,並能從 robots.txt 中獲取sitemap的url。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章