# Spider 合约
> 译者:[OSGeo 中国](https://www.osgeo.cn/)
0.15 新版功能.
注解
这是一个新功能(在Scrapy0.15中引入),可能会受到小功能/API更新的影响。检查 [release notes](../news.html#news) 收到更新通知。
测试 Spider 会变得特别烦人,虽然没有什么可以阻止你编写单元测试,但是任务会很快变得很麻烦。Scrapy提供了一种综合的方法,可以通过合同的方式测试你的 Spider 。
这允许您通过硬编码一个示例URL来测试 Spider 的每个回调,并检查回调如何处理响应的各种约束。每个合同的前缀都是 `@` 并包含在docstring中。请参见以下示例:
```py
def parse(self, response):
""" This function parses a sample response. Some contracts are mingled
with this docstring.
@url http://www.amazon.com/s?field-keywords=selfish+gene
@returns items 1 16
@returns requests 0 0
@scrapes Title Author Year Price
"""
```
此回调使用三个内置合同进行测试:
```py
class scrapy.contracts.default.UrlContract
```
本合同(合同) `@url` )设置检查此spider的其他合同条件时使用的示例URL。本合同是强制性的。运行检查时将忽略缺少此协定的所有回调::
```py
@url url
```
```py
class scrapy.contracts.default.ReturnsContract
```
本合同(合同) `@returns` )为 Spider 返回的项和请求设置下限和上限。上限是可选的:
```py
@returns item(s)|request(s) [min [max]]
```
```py
class scrapy.contracts.default.ScrapesContract
```
本合同(合同) `@scrapes` )检查回调返回的所有项是否具有指定的字段::
```py
@scrapes field_1 field_2 ...
```
使用 [`check`](commands.html#std:command-check) 运行合同检查的命令。
## 定制合同
如果您发现您需要比内置的零碎合同更多的电力,您可以使用 [`SPIDER_CONTRACTS`](settings.html#std:setting-SPIDER_CONTRACTS) 设置:
```py
SPIDER_CONTRACTS = {
'myproject.contracts.ResponseCheck': 10,
'myproject.contracts.ItemValidate': 10,
}
```
每个合同必须继承自 [`scrapy.contracts.Contract`](#scrapy.contracts.Contract "scrapy.contracts.Contract") 可以覆盖三种方法:
```py
class scrapy.contracts.Contract(method, *args)
```
| 参数: |
* **method** (_function_) -- 与合同关联的回调函数
* **args** (_list_) -- 传入docstring的参数列表(空格分隔)
|
| --- | --- |
```py
adjust_request_args(args)
```
这接收了 `dict` 作为包含请求对象的默认参数的参数。 [`Request`](request-response.html#scrapy.http.Request "scrapy.http.Request") 默认情况下使用,但可以使用 `request_cls` 属性。如果链中的多个合同定义了此属性,则使用最后一个。
必须返回相同或修改过的版本。
```py
pre_process(response)
```
这允许在将样本请求传递到回调之前,对从该请求接收的响应进行各种检查。
```py
post_process(output)
```
这允许处理回调的输出。迭代器在传递给这个Hook之前被转换为列表化的。
这里是一个演示合同,它检查在收到的响应中是否存在自定义头。提高 `scrapy.exceptions.ContractFail` 为了让故障得到完美的打印:
```py
from scrapy.contracts import Contract
from scrapy.exceptions import ContractFail
class HasHeaderContract(Contract):
""" Demo contract which checks the presence of a custom header
@has_header X-CustomHeader
"""
name = 'has_header'
def pre_process(self, response):
for header in self.args:
if header not in response.headers:
raise ContractFail('X-CustomHeader not present')
```
- 简介
- 第一步
- Scrapy at a glance
- 安装指南
- Scrapy 教程
- 实例
- 基本概念
- 命令行工具
- Spider
- 选择器
- 项目
- 项目加载器
- Scrapy shell
- 项目管道
- Feed 导出
- 请求和响应
- 链接提取器
- 设置
- 例外情况
- 内置服务
- Logging
- 统计数据集合
- 发送电子邮件
- 远程登录控制台
- Web服务
- 解决具体问题
- 常见问题
- 调试spiders
- Spider 合约
- 常用做法
- 通用爬虫
- 使用浏览器的开发人员工具进行抓取
- 调试内存泄漏
- 下载和处理文件和图像
- 部署 Spider
- AutoThrottle 扩展
- Benchmarking
- 作业:暂停和恢复爬行
- 延伸 Scrapy
- 体系结构概述
- 下载器中间件
- Spider 中间件
- 扩展
- 核心API
- 信号
- 条目导出器
- 其余所有
- 发行说明
- 为 Scrapy 贡献
- 版本控制和API稳定性