97 votes

Comment puis-je utiliser différents pipelines pour différents spiders dans un seul projet Scrapy ?

J'ai un projet scrapy qui contient plusieurs spiders. Existe-t-il un moyen de définir les pipelines à utiliser pour chaque spider ? Tous les pipelines que j'ai définis ne sont pas applicables pour chaque spider.

Merci

3 votes

Merci pour votre très bonne question. Veuillez sélectionner une réponse pour tous les futurs googleurs. La réponse fournie par mstringer a très bien fonctionné pour moi.

168voto

user2134226 Points 2532

Il suffit de supprimer tous les pipelines des paramètres principaux et d'utiliser ce système dans le spider.

Ceci définira le pipeline à utiliser par araignée.

class testSpider(InitSpider):
    name = 'test'
    custom_settings = {
        'ITEM_PIPELINES': {
            'app.MyPipeline': 400
        }
    }

6 votes

Pour ceux qui, comme moi, se demandent ce qu'est le '400' - DU DOC - "Les valeurs entières que vous attribuez aux classes dans ce paramètre déterminent l'ordre dans lequel elles sont exécutées : les éléments passent des classes de valeur inférieure aux classes de valeur supérieure. Il est d'usage de définir ces nombres dans la plage 0-1000". docs.scrapy.org/fr/latest/topics/item-pipeline.html

6 votes

Je ne sais pas pourquoi ce n'est pas la réponse acceptée, cela fonctionne parfaitement, beaucoup plus propre et plus simple que la réponse acceptée. C'est exactement ce que je recherchais. Fonctionne toujours dans scrapy 1.8

3 votes

Je viens de vérifier dans scrapy 1.6. Il n'est pas nécessaire de supprimer les paramètres du pipeline dans settings.py. Les custom_settings dans le spider remplacent les paramètres du pipeline dans settings.py.

39voto

mstringer Points 443

Construire sur la solution de Pablo Hoffman vous pouvez utiliser le décorateur suivant sur l'objet process_item d'un objet Pipeline afin qu'il vérifie la méthode pipeline de votre araignée pour savoir si elle doit être exécutée ou non. Par exemple :

def check_spider_pipeline(process_item_method):

    @functools.wraps(process_item_method)
    def wrapper(self, item, spider):

        # message template for debugging
        msg = '%%s %s pipeline step' % (self.__class__.__name__,)

        # if class is in the spider's pipeline, then use the
        # process_item method normally.
        if self.__class__ in spider.pipeline:
            spider.log(msg % 'executing', level=log.DEBUG)
            return process_item_method(self, item, spider)

        # otherwise, just return the untouched item (skip this step in
        # the pipeline)
        else:
            spider.log(msg % 'skipping', level=log.DEBUG)
            return item

    return wrapper

Pour que ce décorateur fonctionne correctement, l'araignée doit avoir un attribut pipeline avec un conteneur des objets Pipeline que vous voulez utiliser pour traiter l'élément, par exemple :

class MySpider(BaseSpider):

    pipeline = set([
        pipelines.Save,
        pipelines.Validate,
    ])

    def parse(self, response):
        # insert scrapy goodness here
        return item

Et puis dans un pipelines.py fichier :

class Save(object):

    @check_spider_pipeline
    def process_item(self, item, spider):
        # do saving here
        return item

class Validate(object):

    @check_spider_pipeline
    def process_item(self, item, spider):
        # do validating here
        return item

Tous les objets Pipeline devraient toujours être définis dans ITEM_PIPELINES dans les paramètres (dans l'ordre correct -- il serait bien de changer pour que l'ordre puisse être spécifié sur le Spider, aussi).

17voto

eLRuLL Points 1031

Les autres solutions données ici sont bonnes, mais je pense qu'elles pourraient être lentes, parce que nous ne sommes pas vraiment pas Nous n'utilisons pas le pipeline par araignée, mais nous vérifions si un pipeline existe à chaque fois qu'un élément est renvoyé (et dans certains cas, cela peut atteindre des millions).

Une bonne façon de désactiver (ou d'activer) complètement une fonctionnalité par araignée est d'utiliser custom_setting y from_crawler pour toutes les extensions de ce type :

pipelines.py

from scrapy.exceptions import NotConfigured

class SomePipeline(object):
    def __init__(self):
        pass

    @classmethod
    def from_crawler(cls, crawler):
        if not crawler.settings.getbool('SOMEPIPELINE_ENABLED'):
            # if this isn't specified in settings, the pipeline will be completely disabled
            raise NotConfigured
        return cls()

    def process_item(self, item, spider):
        # change my item
        return item

paramètres.py

ITEM_PIPELINES = {
   'myproject.pipelines.SomePipeline': 300,
}
SOMEPIPELINE_ENABLED = True # you could have the pipeline enabled by default

spider1.py

class Spider1(Spider):

    name = 'spider1'

    start_urls = ["http://example.com"]

    custom_settings = {
        'SOMEPIPELINE_ENABLED': False
    }

Comme vous le vérifiez, nous avons spécifié custom_settings qui remplacera les éléments spécifiés dans settings.py et nous désactivons SOMEPIPELINE_ENABLED pour cette araignée.

Maintenant, quand vous exécutez ce spider, vérifiez quelque chose comme :

[scrapy] INFO: Enabled item pipelines: []

Maintenant, scrapy a complètement désactivé le pipeline, sans se soucier de son existence pendant toute la durée de l'exécution. Vérifiez que cela fonctionne aussi pour scrapy extensions y middlewares .

15voto

pad Points 1876

Vous pouvez utiliser le name attribut de l'araignée dans votre pipeline

class CustomPipeline(object)

    def process_item(self, item, spider)
         if spider.name == 'spider1':
             # do something
             return item
         return item

En définissant tous les pipelines de cette manière, vous pouvez obtenir ce que vous voulez.

12voto

Francis Avila Points 18236

Je peux penser à au moins quatre approches :

  1. Utiliser un projet scrapy différent par ensemble de spiders+pipelines (peut être approprié si vos spiders sont suffisamment différents pour être dans des projets différents).
  2. Sur la ligne de commande de l'outil scrapy, modifiez le paramètre du pipeline avec scrapy settings entre chaque invocation de votre araignée
  3. Isolez vos araignées dans leur propre commandes de l'outil scrapy et définissez le default_settings['ITEM_PIPELINES'] sur votre classe de commande à la liste de pipeline que vous voulez pour cette commande. Voir ligne 6 de cet exemple .
  4. Dans les classes de pipeline elles-mêmes, il faut process_item() vérifie contre quelle araignée il est exécuté, et ne fait rien s'il doit être ignoré pour cette araignée. Voir le exemple d'utilisation des ressources par araignée pour vous aider à démarrer. (Cette solution semble être laide car elle couple étroitement les spiders et les pipelines d'articles. Vous ne devriez probablement pas utiliser celle-ci).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X