4

我想获取不同域下的网页,这意味着我必须在命令“scrapy crawl myspider”下使用不同的蜘蛛。但是,由于网页的内容不同,我必须使用不同的管道逻辑将数据放入数据库。但是对于每个蜘蛛来说,它们都必须经过 settings.py 中定义的所有管道。还有其他优雅的方法可以为每个蜘蛛使用单独的管道吗?

4

3 回答 3

9

ITEM_PIPELINES在引擎启动期间为项目中的所有蜘蛛全局定义设置。它不能动态更改每个蜘蛛。

以下是一些需要考虑的选项:

  • 更改管道的代码。跳过/继续处理蜘蛛在process_item您的管道方法中返回的项目,例如:

    def process_item(self, item, spider): 
        if spider.name not in ['spider1', 'spider2']: 
            return item  
    
        # process item
    
  • 改变你开始爬行的方式。从脚本中执行它,基于作为参数传递的蜘蛛名称,ITEM_PIPELINES在调用之前覆盖您的设置crawler.configure()

也可以看看:

希望有帮助。

于 2013-06-29T19:05:39.017 回答
6

上面的一个稍微好一点的版本如下。这样做更好,因为这种方式允许您有选择地为不同的蜘蛛打开管道,而不是上面管道中的 'not in ['spider1','spider2']' 的编码

在您的蜘蛛类中,添加:

#start_urls=...
pipelines = ['pipeline1', 'pipeline2'] #allows you to selectively turn on pipelines within spiders
#...

然后在每个管道中,您可以使用该getattr方法作为魔术。添加:

class pipeline1():  
    def process_item(self, item, spider):
       if 'pipeline1' not in getattr(spider, 'pipelines'):
          return item
       #...keep going as normal  
于 2014-07-16T03:17:56.993 回答
2

更强大的解决方案;不记得我在哪里找到它,但是一个scrapy开发人员在某处提出了它。使用这种方法可以让你在不使用包装器的情况下在所有蜘蛛上运行一些管道。它还使您不必重复检查是否使用管道的逻辑。

包装:

def check_spider_pipeline(process_item_method):
    """
        This wrapper makes it so pipelines can be turned on and off at a spider level.
    """
    @functools.wraps(process_item_method)
    def wrapper(self, item, spider):
        if self.__class__ in spider.pipeline:
            return process_item_method(self, item, spider)
        else:
            return item

    return wrapper

用法:

@check_spider_pipeline
def process_item(self, item, spider):
    ........
    ........
    return item

蜘蛛用法:

pipeline = {some.pipeline, some.other.pipeline .....}
于 2015-06-17T19:08:48.927 回答