【问题标题】:scrapy: Middleware/Pipeline single instancescrapy:中间件/管道单实例
【发布时间】:2018-01-03 03:10:24
【问题描述】:

我正在创建一个本地响应缓存,我正在为其创建一个 Pipeline,因为我需要根据从站点收集的 ID 存储项目的信息。

现在我还需要创建一个Downloader Middleware,因为根据我之前存储的 ID,我不想用新的Request 访问该站点,所以我在发送之前拦截了Request到服务器,检查该 ID 是否已存在于我的缓存中,如果存在,则仅从我的缓存中返回相同的项目。

现在你看到 PipelineMiddleware 需要一起工作,所以分离看起来不是很干净(我也有两个变量,我想是唯一的),但是当我在他们的各自的设置:

DOWNLOADER_MIDDLEWARES = {
    'myproject.urlcache.CachePipelineMiddleware': 1,
}

ITEM_PIPELINES = {
    'myproject.urlcache.CachePipelineMiddleware': 800,
}

我得到两个不同的实例(检查构造函数上的日志消息,因此它被创建了两次)。

如何确保只创建一个实例并且不会与我的项目的PipelineDownloader Middleware 功能发生冲突?

【问题讨论】:

    标签: python scrapy


    【解决方案1】:

    我刚刚意识到这是一个简单的Singleton 问题,scrapy 实际上可以与管道和中间件的相同实例一起使用。

    我首先创建了这个Singleton 类:

    class Singleton(type):
        _instances = {}
    
        def __call__(cls, *args, **kwargs):
            if cls not in cls._instances:
                cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
            return cls._instances[cls]
    

    然后,在管道/中间件的类上,我添加了以下内容:

    class CachePipelineMiddleware(object):
    
        __metaclass__ = Singleton
    
        def process_item(self, item, spider):
            # it works as a Pipeline
    
        def process_request(self, request, spider):
            # it works as a Middleware
    

    【讨论】:

    • 只是问 - 对于这个简单的案例,是否有任何理由更喜欢使用元类而不是直接在 CachePipelineMiddleware__new__ 方法)中处理单例?
    • 真的没有,我刚刚创建了 Singleton 类,因此它可以用于我项目中的不同事物。任何 Singleton 实现都不会与 scrapy 引擎冲突。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多