# 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稳定性