请求最终是谁发出去的?file://、data: 是怎么处理的?能不能自己加一个协议?把 HTTP 处理器换成 aiohttp 会有什么不同?这篇从 DOWNLOAD_HANDLERS 讲起,把几种处理器的行为实测一遍。
{'data': 'scrapy.core.downloader.handlers.datauri.DataURIDownloadHandler',
'file': 'scrapy.core.downloader.handlers.file.FileDownloadHandler',
'ftp': 'scrapy.core.downloader.handlers.ftp.FTPDownloadHandler',
'http': 'scrapy.core.downloader.handlers.http11.HTTP11DownloadHandler',
'https': 'scrapy.core.downloader.handlers.http11.HTTP11DownloadHandler',
's3': 'scrapy.core.downloader.handlers.s3.S3DownloadHandler'}每个 URL 协议对应一个处理器类;DOWNLOAD_HANDLERS 覆盖或追加基础映射,值为 None 禁用。
…hello.html HtmlResponse status=200 38 字节 头={} 文本='<html><title>local f'
…blob.bin Response status=200 256 字节 头={} 文本=None
…missing.html 错误 FileNotFoundError: [Errno 2] No such file or directory: '/Users/w/Des
…plain;charset=utf-8;base64 TextResponse status=200 23 字节 头={} 文本='数据 URI 里的中文'
…data:,hello%20world TextResponse status=200 11 字节 头={} 文本='hello world'
…h1%3E HtmlResponse status=200 10 字节 头={} 文本='<h1>x</h1>'
…s44b 错误 IsADirectoryError: [Errno 21] Is a directory: '/Users/w/Desktop/zen/tfile:// 直接读本地文件,data: 解析 URI,都不走网络和下载槽;响应类按扩展名或 MIME 判定,file 响应没有头。
{'e': 'handler 被调用', 'url': 'myproto://some/resource'}
{'who': 'callback', 'url': 'myproto://some/resource', 'status': 200, 'text': 'hello from myproto: some/resource'}
{'who': 'errback', 'url': 'ftp://example.com/x', 'exc': "NotSupported: Unsupported URL scheme 'ftp': no handler available for that scheme"}继承 BaseDownloadHandler 并实现 async download_request(request) 返回 Response 即可注册新协议。
默认 HTTP11DownloadHandler:48 个各 0.2 s 的请求、每域名并发 4 → 服务器并发峰值 48,总耗时 0.27 s;response.ip_address=127.0.0.1,protocol=HTTP/1.1,certificate=None
AiohttpDownloadHandler:48 个各 0.2 s 的请求、每域名并发 4 → 服务器并发峰值 4,总耗时 2.52 s;response.ip_address=127.0.0.1,protocol=HTTP/1.1,certificate=None
警告:WARNING: AiohttpDownloadHandler is experimental an
aiohttp 处理器 + meta bindaddress=("127.0.0.1", 0):[{'who': 'callback'}];日志 ["ERROR: The 'bindaddress' request meta key is not supported by AiohttpDownloadHandler and will be ignored."]
aiohttp 处理器 + meta proxy="http://127.0.0.1:1":[{'who': 'errback', 'exc': 'DownloadConnectionRefusedError', 'msg': 'Cannot connect to host 127.0.0.1:1 ssl:<ssl.SSLContext object at 0x…> [C'}];日志 []AiohttpDownloadHandler(实验性)自带连接数限制,所以每域名并发限制生效;不支持 bindaddress,会记 ERROR 并忽略。