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來說,爬取的循環類似下文:
-
以初始的URL初始化Request,並設置回調函數。 當該request下載完畢並返回時,將生成response,並作爲參數傳給該回調函數。
spider中初始的request是通過調用
start_requests()
來獲取的。start_requests()
讀取start_urls
中的URL, 並以parse
爲回調函數生成Request
。 在回調函數內分析返回的(網頁)內容,返回
Item
對象或者Request
或者一個包括二者的可迭代容器。 返回的Request對象之後會經過Scrapy處理,下載相應的內容,並調用設置的callback函數(函數可相同)。在回調函數內,您可以使用 選擇器(Selectors) (您也可以使用BeautifulSoup, lxml 或者您想用的任何解析器) 來分析網頁內容,並根據分析的數據生成item。
最後,由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。