# Spider
> 譯者:[OSGeo 中國](https://www.osgeo.cn/)
spider是定義一個特定站點(或一組站點)如何被抓取的類,包括如何執行抓取(即跟蹤鏈接)以及如何從頁面中提取結構化數據(即抓取項)。換言之,spider是為特定站點(或者在某些情況下,一組站點)定義爬行和解析頁面的自定義行為的地方。
對于 Spider 來說,抓取周期是這樣的:
1. 首先生成對第一個URL進行爬網的初始請求,然后指定一個回調函數,該函數使用從這些請求下載的響應進行調用。
要執行的第一個請求是通過調用 [`start_requests()`](#scrapy.spiders.Spider.start_requests "scrapy.spiders.Spider.start_requests") (默認)生成的方法 [`Request`](request-response.html#scrapy.http.Request "scrapy.http.Request") 對于中指定的URL [`start_urls`](#scrapy.spiders.Spider.start_urls "scrapy.spiders.Spider.start_urls") 以及 [`parse`](#scrapy.spiders.Spider.parse "scrapy.spiders.Spider.parse") 方法作為請求的回調函數。
2. 在回調函數中,解析響應(網頁)并返回提取數據的dict, [`Item`](items.html#scrapy.item.Item "scrapy.item.Item") 物體, [`Request`](request-response.html#scrapy.http.Request "scrapy.http.Request") 對象,或這些對象中的一個不可重復的對象。這些請求還將包含回調(可能相同),然后由scrappy下載,然后由指定的回調處理它們的響應。
3. 在回調函數中,解析頁面內容,通常使用 [選擇器](selectors.html#topics-selectors) (但您也可以使用beautifulsoup、lxml或任何您喜歡的機制)并使用解析的數據生成項。
4. 最后,從spider返回的項目通常被持久化到數據庫(在某些 [Item Pipeline](item-pipeline.html#topics-item-pipeline) )或者使用 [Feed 導出](feed-exports.html#topics-feed-exports) .
盡管這個循環(或多或少)適用于任何類型的 Spider ,但是為了不同的目的,有不同類型的默認 Spider 被捆綁成碎片。我們將在這里討論這些類型。
## scrapy.Spider
```py
class scrapy.spiders.Spider
```
這是最簡單的 Spider ,也是每個 Spider 都必須繼承的 Spider (包括與 Scrapy 捆綁在一起的 Spider ,還有你自己寫的 Spider )。它不提供任何特殊功能。它只是提供了一個默認值 [`start_requests()`](#scrapy.spiders.Spider.start_requests "scrapy.spiders.Spider.start_requests") 從發送請求的實現 [`start_urls`](#scrapy.spiders.Spider.start_urls "scrapy.spiders.Spider.start_urls") spider屬性并調用spider的方法 `parse` 對于每個結果響應。
```py
name
```
定義此 Spider 名稱的字符串。spider名稱是scrappy定位(和實例化)spider的方式,因此它必須是唯一的。但是,沒有什么可以阻止您實例化同一個 Spider 的多個實例。這是最重要的 Spider 屬性,也是必需的。
如果 Spider 抓取一個域,通常的做法是在域后命名 Spider ,無論有沒有 [TLD](https://en.wikipedia.org/wiki/Top-level_domain) . 例如,一只爬行的 Spider `mywebsite.com` 經常被稱為 `mywebsite` .
注解
在Python2中,這只能是ASCII。
```py
allowed_domains
```
包含允許此 Spider 爬行的域的字符串的可選列表。對于不屬于此列表(或其子域)中指定的域名的URL請求,如果 [`OffsiteMiddleware`](spider-middleware.html#scrapy.spidermiddlewares.offsite.OffsiteMiddleware "scrapy.spidermiddlewares.offsite.OffsiteMiddleware") 啟用。
假設您的目標URL是 `https://www.example.com/1.html` 然后添加 `'example.com'` 列在名單上。
```py
start_urls
```
當沒有指定特定的URL時, Spider 將從中開始爬行的URL列表。所以,下載的第一頁將是這里列出的那些。隨后 [`Request`](request-response.html#scrapy.http.Request "scrapy.http.Request") 將從包含在起始URL中的數據依次生成。
```py
custom_settings
```
運行此spider時,將從項目范圍配置中重寫的設置字典。它必須被定義為類屬性,因為在實例化之前更新了設置。
有關可用內置設置的列表,請參閱: [內置設置參考](settings.html#topics-settings-ref) .
```py
crawler
```
此屬性由 [`from_crawler()`](item-pipeline.html#from_crawler "from_crawler") 初始化類后的類方法,并鏈接到 [`Crawler`](api.html#scrapy.crawler.Crawler "scrapy.crawler.Crawler") 此 Spider 實例綁定到的對象。
Crawler封裝了項目中的許多組件,用于它們的單入口訪問(例如擴展、中間件、信號管理器等)。見 [爬蟲API](api.html#topics-api-crawler) 了解更多。
```py
settings
```
用于運行此 Spider 的配置。這是一個 [`Settings`](api.html#scrapy.settings.Settings "scrapy.settings.Settings") 實例,請參見 [設置](settings.html#topics-settings) 有關此主題的詳細介紹。
```py
logger
```
用 Spider 創建的python記錄器 [`name`](#scrapy.spiders.Spider.name "scrapy.spiders.Spider.name") . 您可以使用它通過它發送日志消息,如中所述 [從 Spider 記錄](logging.html#topics-logging-from-spiders) .
```py
from_crawler(crawler, *args, **kwargs)
```
這是Scrapy用來創建 Spider 的類方法。
您可能不需要直接重寫它,因為默認實現充當 `__init__()` 方法,使用給定參數調用它 `args` 和命名參數 `kwargs` .
盡管如此,此方法設置了 [`crawler`](#scrapy.spiders.Spider.crawler "scrapy.spiders.Spider.crawler") 和 [`settings`](#scrapy.spiders.Spider.settings "scrapy.spiders.Spider.settings") 新實例中的屬性,以便稍后在 Spider 代碼中訪問它們。
| 參數: |
* **crawler** ([`Crawler`](api.html#scrapy.crawler.Crawler "scrapy.crawler.Crawler") instance) -- Spider 將被綁到的爬行器
* **args** (_list_) -- 傳遞給的參數 `__init__()` 方法
* **kwargs** (_dict_) -- 傳遞給的關鍵字參數 `__init__()` 方法
|
| --- | --- |
```py
start_requests()
```
此方法必須返回一個iterable,其中包含對此spider進行爬網的第一個請求。當 Spider 被打開刮的時候,它被 Scrapy 稱為。Scrapy只調用一次,因此可以安全地實現 [`start_requests()`](#scrapy.spiders.Spider.start_requests "scrapy.spiders.Spider.start_requests") 作為發電機。
默認實現生成 `Request(url, dont_filter=True)` 對于每個URL [`start_urls`](#scrapy.spiders.Spider.start_urls "scrapy.spiders.Spider.start_urls") .
如果要更改用于開始抓取域的請求,這是要重寫的方法。例如,如果您需要從使用POST請求登錄開始,可以執行以下操作:
```py
class MySpider(scrapy.Spider):
name = 'myspider'
def start_requests(self):
return [scrapy.FormRequest("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
```
```py
parse(response)
```
這是Scrapy在請求未指定回調時用來處理下載響應的默認回調。
這個 `parse` 方法負責處理響應,并返回抓取的數據和/或更多的URL。其他請求回調與 [`Spider`](#scrapy.spiders.Spider "scrapy.spiders.Spider") 類。
此方法以及任何其他請求回調都必須返回 [`Request`](request-response.html#scrapy.http.Request "scrapy.http.Request") 和/或DICT或 [`Item`](items.html#scrapy.item.Item "scrapy.item.Item") 物體。
| 參數: | **response** ([`Response`](request-response.html#scrapy.http.Response "scrapy.http.Response")) -- 解析的響應 |
| --- | --- |
```py
log(message[, level, component])
```
通過Spider的 [`logger`](#scrapy.spiders.Spider.logger "scrapy.spiders.Spider.logger") ,保持向后兼容性。有關詳細信息,請參閱 [從 Spider 記錄](logging.html#topics-logging-from-spiders) .
```py
closed(reason)
```
Spider 關閉時調用。此方法為 [`spider_closed`](signals.html#std:signal-spider_closed) 信號。
我們來看一個例子:
```py
import scrapy
class MySpider(scrapy.Spider):
name = 'example.com'
allowed_domains = ['example.com']
start_urls = [
'http://www.example.com/1.html',
'http://www.example.com/2.html',
'http://www.example.com/3.html',
]
def parse(self, response):
self.logger.info('A response from %s just arrived!', response.url)
```
從單個回調返回多個請求和項目:
```py
import scrapy
class MySpider(scrapy.Spider):
name = 'example.com'
allowed_domains = ['example.com']
start_urls = [
'http://www.example.com/1.html',
'http://www.example.com/2.html',
'http://www.example.com/3.html',
]
def parse(self, response):
for h3 in response.xpath('//h3').getall():
yield {"title": h3}
for href in response.xpath('//a/@href').getall():
yield scrapy.Request(response.urljoin(href), self.parse)
```
而不是 [`start_urls`](#scrapy.spiders.Spider.start_urls "scrapy.spiders.Spider.start_urls") 你可以用 [`start_requests()`](#scrapy.spiders.Spider.start_requests "scrapy.spiders.Spider.start_requests") 直接;給數據更多的結構,你可以使用 [項目](items.html#topics-items) ::
```py
import scrapy
from myproject.items import MyItem
class MySpider(scrapy.Spider):
name = 'example.com'
allowed_domains = ['example.com']
def start_requests(self):
yield scrapy.Request('http://www.example.com/1.html', self.parse)
yield scrapy.Request('http://www.example.com/2.html', self.parse)
yield scrapy.Request('http://www.example.com/3.html', self.parse)
def parse(self, response):
for h3 in response.xpath('//h3').getall():
yield MyItem(title=h3)
for href in response.xpath('//a/@href').getall():
yield scrapy.Request(response.urljoin(href), self.parse)
```
## Spider 論點
Spider 可以接受改變其行為的論據。spider參數的一些常見用途是定義起始URL或將爬行限制在站點的某些部分,但它們可以用于配置spider的任何功能。
Spider 參數通過 [`crawl`](commands.html#std:command-crawl) 命令使用 `-a` 選項。例如::
```py
scrapy crawl myspider -a category=electronics
```
Spider 可以在它們的 <cite>__init__</cite> 方法::
```py
import scrapy
class MySpider(scrapy.Spider):
name = 'myspider'
def __init__(self, category=None, *args, **kwargs):
super(MySpider, self).__init__(*args, **kwargs)
self.start_urls = ['http://www.example.com/categories/%s' % category]
# ...
```
默認值 <cite>__init__</cite> 方法將獲取任何spider參數,并將其作為屬性復制到spider。上面的例子也可以寫如下:
```py
import scrapy
class MySpider(scrapy.Spider):
name = 'myspider'
def start_requests(self):
yield scrapy.Request('http://www.example.com/categories/%s' % self.category)
```
請記住,spider參數只是字符串。 Spider 本身不會進行任何解析。如果你要設置 `start_urls` 屬性來自命令行,您必須使用類似的 [ast.literal_eval](https://docs.python.org/library/ast.html#ast.literal_eval) 或 [json.loads](https://docs.python.org/library/json.html#json.loads) 然后將其設置為屬性。否則,您將在 `start_urls` 字符串(一個非常常見的Python陷阱),導致每個字符被視為一個單獨的URL。
有效的用例是設置 [`HttpAuthMiddleware`](downloader-middleware.html#scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware "scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware") 或用戶代理 [`UserAgentMiddleware`](downloader-middleware.html#scrapy.downloadermiddlewares.useragent.UserAgentMiddleware "scrapy.downloadermiddlewares.useragent.UserAgentMiddleware") ::
```py
scrapy crawl myspider -a http_user=myuser -a http_pass=mypassword -a user_agent=mybot
```
Spider 參數也可以通過scrapyD傳遞 `schedule.json` 應用程序編程接口。見 [Scrapyd documentation](https://scrapyd.readthedocs.io/en/latest/) .
## 類 Spider
Scrapy附帶了一些有用的通用 Spider ,您可以使用它們來對 Spider 進行子類化。他們的目標是為一些常見的抓取案例提供方便的功能,比如根據特定規則跟蹤站點上的所有鏈接,從 [Sitemaps](https://www.sitemaps.org/index.html) 或分析XML/CSV源。
對于以下 Spider 中使用的示例,我們假設您有一個項目 `TestItem` 宣布為 `myproject.items` 模塊:
```py
import scrapy
class TestItem(scrapy.Item):
id = scrapy.Field()
name = scrapy.Field()
description = scrapy.Field()
```
### CrawlSpider
```py
class scrapy.spiders.CrawlSpider
```
這是最常用的爬行常規網站的 Spider ,因為它通過定義一組規則為跟蹤鏈接提供了一種方便的機制。它可能不是最適合您的特定網站或項目的,但它對于某些情況來說已經足夠通用了,因此您可以從它開始,并根據需要覆蓋它以獲得更多的自定義功能,或者只實現您自己的 Spider 。
除了從spider繼承的屬性(必須指定),這個類還支持一個新的屬性:
```py
rules
```
這是一個(或多個)列表 [`Rule`](#scrapy.spiders.Rule "scrapy.spiders.Rule") 物體。各 [`Rule`](#scrapy.spiders.Rule "scrapy.spiders.Rule") 定義對網站進行爬行的特定行為。規則對象如下所述。如果多個規則與同一鏈接匹配,則將根據在該屬性中定義的順序使用第一個規則。
這個 Spider 還公開了一個可重寫的方法:
```py
parse_start_url(response)
```
啟動URL響應調用此方法。它允許分析初始響應,并且必須返回 [`Item`](items.html#scrapy.item.Item "scrapy.item.Item") 對象,A [`Request`](request-response.html#scrapy.http.Request "scrapy.http.Request") 對象,或包含任何對象的iterable。
#### 爬行規則
```py
class scrapy.spiders.Rule(link_extractor, callback=None, cb_kwargs=None, follow=None, process_links=None, process_request=None)
```
`link_extractor` 是一個 [Link Extractor](link-extractors.html#topics-link-extractors) 對象,定義如何從每個已爬網頁提取鏈接。
`callback` 是一個可調用的或字符串(在這種情況下,將使用具有該名稱的spider對象中的方法),用于為使用指定的鏈接提取器提取的每個鏈接調用。此回調接收響應作為其第一個參數,并且必須返回包含 [`Item`](items.html#scrapy.item.Item "scrapy.item.Item") 和/或 [`Request`](request-response.html#scrapy.http.Request "scrapy.http.Request") 對象(或其任何子類)。
警告
編寫爬行 Spider 規則時,請避免使用 `parse` 作為回調,因為 [`CrawlSpider`](#scrapy.spiders.CrawlSpider "scrapy.spiders.CrawlSpider") 使用 `parse` 方法本身來實現其邏輯。所以如果你重寫 `parse` 方法,爬行 Spider 將不再工作。
`cb_kwargs` 是包含要傳遞給回調函數的關鍵字參數的dict。
`follow` 是一個布爾值,用于指定是否從使用此規則提取的每個響應中遵循鏈接。如果 `callback` 沒有 `follow` 默認為 `True` ,否則默認為 `False` .
`process_links` 是一個可調用的,或一個字符串(在這種情況下,將使用具有該名稱的 Spider 對象中的方法),對于使用指定的 `link_extractor` . 這主要用于過濾目的。
`process_request` 是可調用的(或字符串,在這種情況下,將使用具有該名稱的spider對象中的方法),它將為 [`Request`](request-response.html#scrapy.http.Request "scrapy.http.Request") 按此規則提取。此可調用文件應將所述請求作為第一個參數,并且 [`Response`](request-response.html#scrapy.http.Response "scrapy.http.Response") 從中發出請求作為第二個參數。它必須返回 `Request` 對象或 `None` (過濾掉請求)。
#### 爬行 Spider 示例
現在讓我們來看一個例子,爬行 Spider 的規則是:
```py
import scrapy
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor
class MySpider(CrawlSpider):
name = 'example.com'
allowed_domains = ['example.com']
start_urls = ['http://www.example.com']
rules = (
# Extract links matching 'category.php' (but not matching 'subsection.php')
# and follow links from them (since no callback means follow=True by default).
Rule(LinkExtractor(allow=('category\.php', ), deny=('subsection\.php', ))),
# Extract links matching 'item.php' and parse them with the spider's method parse_item
Rule(LinkExtractor(allow=('item\.php', )), callback='parse_item'),
)
def parse_item(self, response):
self.logger.info('Hi, this is an item page! %s', response.url)
item = scrapy.Item()
item['id'] = response.xpath('//td[@id="item_id"]/text()').re(r'ID: (\d+)')
item['name'] = response.xpath('//td[@id="item_name"]/text()').get()
item['description'] = response.xpath('//td[@id="item_description"]/text()').get()
return item
```
這個 Spider 會開始對example.com的主頁進行爬行,收集類別鏈接和項目鏈接,并用 `parse_item` 方法。對于每個項目響應,將使用xpath從HTML中提取一些數據,并且 [`Item`](items.html#scrapy.item.Item "scrapy.item.Item") 會裝滿它的。
### XMLFeedSpider
```py
class scrapy.spiders.XMLFeedSpider
```
XMLFeedSpider是為解析XML提要而設計的,它通過使用特定的節點名對這些提要進行迭代。迭代器可以從以下選項中選擇: `iternodes` , `xml` 和 `html` . 建議使用 `iternodes` 由于性能原因,迭代器 `xml` 和 `html` 迭代器一次生成整個DOM以便解析它。然而,使用 `html` 因為迭代器在分析帶有錯誤標記的XML時可能很有用。
要設置迭代器和標記名,必須定義以下類屬性:
```py
iterator
```
定義要使用的迭代器的字符串。它可以是:
> * `'iternodes'` -基于正則表達式的快速迭代器
> * `'html'` -使用的迭代器 [`Selector`](selectors.html#scrapy.selector.Selector "scrapy.selector.Selector") . 請記住,這使用了DOM解析,必須將所有的DOM加載到內存中,這對于大型提要來說可能是一個問題。
> * `'xml'` -使用的迭代器 [`Selector`](selectors.html#scrapy.selector.Selector "scrapy.selector.Selector") . 請記住,這使用了DOM解析,必須將所有的DOM加載到內存中,這對于大型提要來說可能是一個問題。
默認為: `'iternodes'` .
```py
itertag
```
具有要迭代的節點(或元素)名稱的字符串。例子::
```py
itertag = 'product'
```
```py
namespaces
```
列表 `(prefix, uri)` 定義該文檔中可用的命名空間的元組,這些命名空間將使用此 Spider 進行處理。這個 `prefix` 和 `uri` 將用于使用 [`register_namespace()`](selectors.html#scrapy.selector.Selector.register_namespace "scrapy.selector.Selector.register_namespace") 方法。
然后,可以在 [`itertag`](#scrapy.spiders.XMLFeedSpider.itertag "scrapy.spiders.XMLFeedSpider.itertag") 屬性。
例子::
```py
class YourSpider(XMLFeedSpider):
namespaces = [('n', 'http://www.sitemaps.org/schemas/sitemap/0.9')]
itertag = 'n:url'
# ...
```
除了這些新屬性之外,這個 Spider 還具有以下可重寫的方法:
```py
adapt_response(response)
```
一種方法,當響應從 Spider 中間件到達時,在 Spider 開始解析它之前,立即接收響應。它可以用于在解析響應體之前對其進行修改。此方法接收響應并返回響應(可以是相同的或另一個響應)。
```py
parse_node(response, selector)
```
對與提供的標記名匹配的節點調用此方法( `itertag` )接收響應和 [`Selector`](selectors.html#scrapy.selector.Selector "scrapy.selector.Selector") 對于每個節點。必須重寫此方法。否則,你的 Spider 就不會工作了。此方法必須返回 [`Item`](items.html#scrapy.item.Item "scrapy.item.Item") 對象,A [`Request`](request-response.html#scrapy.http.Request "scrapy.http.Request") 對象,或包含任何對象的iterable。
```py
process_results(response, results)
```
對于 Spider 返回的每個結果(項或請求),調用此方法,它旨在在將結果返回到框架核心之前執行所需的任何最后一次處理,例如設置項ID。它接收一個結果列表以及產生這些結果的響應。它必須返回結果列表(項或請求)。
#### XmlFeedSpider示例
這些 Spider 很容易使用,讓我們來看一個例子:
```py
from scrapy.spiders import XMLFeedSpider
from myproject.items import TestItem
class MySpider(XMLFeedSpider):
name = 'example.com'
allowed_domains = ['example.com']
start_urls = ['http://www.example.com/feed.xml']
iterator = 'iternodes' # This is actually unnecessary, since it's the default value
itertag = 'item'
def parse_node(self, response, node):
self.logger.info('Hi, this is a <%s> node!: %s', self.itertag, ''.join(node.getall()))
item = TestItem()
item['id'] = node.xpath('@id').get()
item['name'] = node.xpath('name').get()
item['description'] = node.xpath('description').get()
return item
```
基本上,我們所做的就是創建一個 Spider ,從給定的 `start_urls` ,然后遍歷 `item` 標簽,打印出來,并將一些隨機數據存儲在 [`Item`](items.html#scrapy.item.Item "scrapy.item.Item") .
### CSVFeedSpider
```py
class scrapy.spiders.CSVFeedSpider
```
這個spider與xmlFeedSpider非常相似,只是它迭代行,而不是節點。在每次迭代中被調用的方法是 [`parse_row()`](#scrapy.spiders.CSVFeedSpider.parse_row "scrapy.spiders.CSVFeedSpider.parse_row") .
```py
delimiter
```
帶有csv文件中每個字段分隔符的字符串默認為 `','` (逗號)
```py
quotechar
```
帶有csv文件中每個字段的Shell字符的字符串默認為 `'"'` (引號)。
```py
headers
```
csv文件中的列名列表。
```py
parse_row(response, row)
```
接收響應和dict(代表每一行),其中為csv文件的每個提供的(或檢測到的)頭文件都有一個鍵。這個 Spider 還提供了超越的機會 `adapt_response` 和 `process_results` 用于預處理和后處理目的的方法。
#### CSVFeedspider示例
我們來看一個類似于前一個的例子,但是使用 [`CSVFeedSpider`](#scrapy.spiders.CSVFeedSpider "scrapy.spiders.CSVFeedSpider") ::
```py
from scrapy.spiders import CSVFeedSpider
from myproject.items import TestItem
class MySpider(CSVFeedSpider):
name = 'example.com'
allowed_domains = ['example.com']
start_urls = ['http://www.example.com/feed.csv']
delimiter = ';'
quotechar = "'"
headers = ['id', 'name', 'description']
def parse_row(self, response, row):
self.logger.info('Hi, this is a row!: %r', row)
item = TestItem()
item['id'] = row['id']
item['name'] = row['name']
item['description'] = row['description']
return item
```
### SitemapSpider
```py
class scrapy.spiders.SitemapSpider
```
SiteMapSpider允許您通過使用 [Sitemaps](https://www.sitemaps.org/index.html) .
它支持嵌套的站點地圖和從中發現站點地圖URL [robots.txt](http://www.robotstxt.org/) .
```py
sitemap_urls
```
指向要爬網其URL的網站地圖的URL列表。
您也可以指向 [robots.txt](http://www.robotstxt.org/) 它將被解析為從中提取站點地圖URL。
```py
sitemap_rules
```
元組列表 `(regex, callback)` 在哪里?
* `regex` 是一個正則表達式,用于匹配從站點地圖中提取的URL。 `regex` 可以是str或已編譯的regex對象。
* 回調是用于處理與正則表達式匹配的URL的回調。 `callback` 可以是字符串(指示spider方法的名稱)或可調用的。
例如::
```py
sitemap_rules = [('/product/', 'parse_product')]
```
規則按順序應用,只使用第一個匹配的規則。
如果省略此屬性,則在站點地圖中找到的所有URL都將使用 `parse` 回調。
```py
sitemap_follow
```
應遵循的站點地圖正則表達式列表。這只適用于使用 [Sitemap index files](https://www.sitemaps.org/protocol.html#index) 指向其他站點 Mapfile 。
默認情況下,將遵循所有站點地圖。
```py
sitemap_alternate_links
```
指定是否為一個 `url` 應該遵循。這些是同一網站的鏈接,使用同一網站內傳遞的另一種語言 `url` 塊。
例如::
```py
<url>
<loc>http://example.com/</loc>
<xhtml:link rel="alternate" hreflang="de" href="http://example.com/de"/>
</url>
```
用 `sitemap_alternate_links` 設置,這將檢索兩個URL。用 `sitemap_alternate_links` 只有殘疾人 `http://example.com/` 將被取回。
`sitemap_alternate_links` 殘疾人。
```py
sitemap_filter(entries)
```
這是一個過濾器功能,可以重寫該功能以根據其屬性選擇站點地圖條目。
例如::
```py
<url>
<loc>http://example.com/</loc>
<lastmod>2005-01-01</lastmod>
</url>
```
我們可以定義一個 `sitemap_filter` 要篩選的函數 `entries` 日期:
```py
from datetime import datetime
from scrapy.spiders import SitemapSpider
class FilteredSitemapSpider(SitemapSpider):
name = 'filtered_sitemap_spider'
allowed_domains = ['example.com']
sitemap_urls = ['http://example.com/sitemap.xml']
def sitemap_filter(self, entries):
for entry in entries:
date_time = datetime.strptime(entry['lastmod'], '%Y-%m-%d')
if date_time.year >= 2005:
yield entry
```
這只能找回 `entries` 2005年及以后年份修改。
條目是從站點地圖文檔中提取的dict對象。通常,鍵是標記名,值是其中的文本。
重要的是要注意:
* 由于loc屬性是必需的,因此不帶此標記的條目將被丟棄。
* 備用鏈接用鍵存儲在列表中 `alternate` (見 `sitemap_alternate_links` )
* 名稱空間被刪除,因此名為 `{{namespace}}tagname` 成為唯一 `tagname`
如果省略此方法,則將處理站點地圖中找到的所有條目,同時觀察其他屬性及其設置。
#### SiteMapSpider示例
最簡單的示例:使用 `parse` 回叫:
```py
from scrapy.spiders import SitemapSpider
class MySpider(SitemapSpider):
sitemap_urls = ['http://www.example.com/sitemap.xml']
def parse(self, response):
pass # ... scrape item here ...
```
使用特定回調處理某些URL,使用其他回調處理其他URL::
```py
from scrapy.spiders import SitemapSpider
class MySpider(SitemapSpider):
sitemap_urls = ['http://www.example.com/sitemap.xml']
sitemap_rules = [
('/product/', 'parse_product'),
('/category/', 'parse_category'),
]
def parse_product(self, response):
pass # ... scrape product ...
def parse_category(self, response):
pass # ... scrape category ...
```
遵循中定義的站點地圖 [robots.txt](http://www.robotstxt.org/) 文件,僅跟蹤其URL包含 `/sitemap_shop` ::
```py
from scrapy.spiders import SitemapSpider
class MySpider(SitemapSpider):
sitemap_urls = ['http://www.example.com/robots.txt']
sitemap_rules = [
('/shop/', 'parse_shop'),
]
sitemap_follow = ['/sitemap_shops']
def parse_shop(self, response):
pass # ... scrape shop here ...
```
將SiteMapSpider與其他URL源合并::
```py
from scrapy.spiders import SitemapSpider
class MySpider(SitemapSpider):
sitemap_urls = ['http://www.example.com/robots.txt']
sitemap_rules = [
('/shop/', 'parse_shop'),
]
other_urls = ['http://www.example.com/about']
def start_requests(self):
requests = list(super(MySpider, self).start_requests())
requests += [scrapy.Request(x, self.parse_other) for x in self.other_urls]
return requests
def parse_shop(self, response):
pass # ... scrape shop here ...
def parse_other(self, response):
pass # ... scrape other here ...
```
- 簡介
- 第一步
- Scrapy at a glance
- 安裝指南
- Scrapy 教程
- 實例
- 基本概念
- 命令行工具
- Spider
- 選擇器
- 項目
- 項目加載器
- Scrapy shell
- 項目管道
- Feed 導出
- 請求和響應
- 鏈接提取器
- 設置
- 例外情況
- 內置服務
- Logging
- 統計數據集合
- 發送電子郵件
- 遠程登錄控制臺
- Web服務
- 解決具體問題
- 常見問題
- 調試spiders
- Spider 合約
- 常用做法
- 通用爬蟲
- 使用瀏覽器的開發人員工具進行抓取
- 調試內存泄漏
- 下載和處理文件和圖像
- 部署 Spider
- AutoThrottle 擴展
- Benchmarking
- 作業:暫停和恢復爬行
- 延伸 Scrapy
- 體系結構概述
- 下載器中間件
- Spider 中間件
- 擴展
- 核心API
- 信號
- 條目導出器
- 其余所有
- 發行說明
- 為 Scrapy 貢獻
- 版本控制和API穩定性