💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
# 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') ```