Scrapy中如何从CrawlerProcess获取FEED_URI动态生成的实际文件名
你只需要手动实例化Crawler对象而非直接传入爬虫类到CrawlerProcess.crawl,即可拿到 crawler 引用,爬虫运行结束后直接读取 FeedExport 扩展的属性即可拿到实际生成的URI。
方案1:兼容所有Scrapy 2.x版本
from scrapy.crawler import Crawler, CrawlerProcess def handler(event, context): # 手动创建Crawler实例,持有引用 crawler = Crawler( BbSpider, settings={ 'FEED_FORMAT': 'csv', 'FEED_URI': 's3://bucket-name/%(name)s/%(time)s.csv' } ) process = CrawlerProcess(settings={}) # 传入已经实例化的crawler而非爬虫类 process.crawl(crawler) # 阻塞等待爬虫运行结束 process.start() # 从激活的扩展中取出FeedExport实例 feed_export_ext = crawler.extensions['scrapy.extensions.feedexport.FeedExport'] # 取出所有生成的实际URI,单爬虫单导出配置下只会有一个值 result_uris = [slot.uri for slot in feed_export_ext.slots.values()] # 返回第一个(也是唯一的)生成文件名 return result_uris[0]
原理说明:
- 你之前无法获取 FeedExport 实例的核心原因是直接把
BbSpider类传给process.crawl时,Crawler实例是框架内部隐式创建的,你没有持有该实例的引用,自然无法访问其内部的扩展属性 - 所有Scrapy激活的扩展都会存在
crawler.extensions字典中,键是扩展类的全路径名,直接取值即可拿到 FeedExport 实例
方案2:Scrapy 2.6+版本推荐(官方公开API,无内部属性依赖)
2.6及以上版本官方新增了feed_exported信号,导出完成时会主动触发,无需依赖FeedExport的内部属性,稳定性更高:
from scrapy import signals from scrapy.crawler import Crawler, CrawlerProcess def handler(event, context): generated_uri = None # 定义信号回调,导出完成时自动拿到实际URI def catch_uri(feed, **kwargs): nonlocal generated_uri generated_uri = feed['uri'] crawler = Crawler( BbSpider, settings={ 'FEED_FORMAT': 'csv', 'FEED_URI': 's3://bucket-name/%(name)s/%(time)s.csv' } ) # 绑定信号回调 crawler.signals.connect(catch_uri, signal=signals.feed_exported) process = CrawlerProcess(settings={}) process.crawl(crawler) process.start() return generated_uri
内容的提问来源于stack exchange,提问作者Karishma Sukhwani
相关产品推荐
相关产品推荐

