DropItem、IgnoreRequest、CloseSpider、NotConfigured……这些异常是 Scrapy 给你控制流程的开关,但“在哪里抛”决定它是否有效。这篇把它们放进回调、中间件、pipeline、信号处理函数里各抛一次,看引擎怎么处理。
下载器中间件 process_request 抛 IgnoreRequest:errback (IgnoreRequest: mw says no);spider_exceptions=0;日志 ["'downloader/exception_type_count/scrapy.exceptions.IgnoreRequest': 1,"] 下载器中间件 process_response 抛 IgnoreRequest:errback (IgnoreRequest: resp says no);spider_exceptions=0;日志 [] 爬虫中间件 process_spider_input 抛 IgnoreRequest:errback (IgnoreRequest: spider-mw says no);spider_exceptions=0;日志 [] 回调里抛 IgnoreRequest:回调/errback 都没有被调用;spider_exceptions=1;日志 ['ERROR: Spider error processing <GET http://127.0.0.1:9960/target> (referer: None)']
在中间件里抛表示“丢弃这个请求/响应”,errback 会收到它;在回调里抛没有这个含义,只是普通的回调异常。
回调里 raise CloseSpider("my_reason")(第 5 个页面):finish_reason=my_reason;服务器收到 7 个请求;item_scraped_count=0;日志里的第一条错误:(无)
pipeline.process_item 里抛(第 5 个 item):finish_reason=finished;服务器收到 31 个请求;item_scraped_count=29;日志里的第一条错误:ERROR: Error processing {'u': 'http://127.0.0.1:9960/p25'}
start() 里抛:finish_reason=start_reason;服务器收到 1 个请求;item_scraped_count=0;日志里的第一条错误:(无)
下载器中间件 process_request 里抛(第 5 个请求):finish_reason=finished;服务器收到 30 个请求;item_scraped_count=0;日志里的第一条错误:ERROR: Error downloading <GET http://127.0.0.1:9960/p26>
信号处理函数里抛(response_received 的第 5 次):finish_reason=finished;服务器收到 31 个请求;item_scraped_count=0;日志里的第一条错误:ERROR: Error caught on signal handler: <function S.from_crawler.<locals>.f at 0x只有回调和 start() 里抛的 CloseSpider 才会按给定原因关闭爬虫;其它位置抛只会变成普通的错误日志,爬虫继续跑。
日志里的 Disabled 行:WARNING: Disabled <class 'spider.LoudExt'>: missing LOUD_SETTING | WARNING: Disabled <class 'spider.DM'>: no config for DM | WARNING: Disabled <class 'spider.P'>: pipeline off 爬虫照常跑完:finish_reason=finished;item_scraped_count=1 [scrapy.middleware] INFO: Enabled item pipelines: []
组件构造时抛出,Scrapy 就跳过它,爬虫继续;给了消息会打 WARNING。常用于“没配置就不启用”。
foo://bar/x:[{'who': 'errback', 'exc': 'scrapy.exceptions.NotSupported', 'msg': "Unsupported URL scheme 'foo': no handler available for that scheme"}];retry/count=0;downloader/exception_count=1没有对应下载处理器的协议会抛 NotSupported,走 errback,不重试。