Comment passer un argument défini par l'utilisateur dans Scrapy Spider

100

J'essaye de passer un argument défini par l'utilisateur à l'araignée d'une scrapy. Quelqu'un peut-il suggérer comment faire cela?

J'ai lu -aquelque part sur un paramètre mais je n'ai aucune idée de comment l'utiliser.

L Lawliet
la source

Réponses:

187

Les arguments Spider sont passés dans la crawlcommande à l'aide de l' -aoption. Par exemple:

scrapy crawl myspider -a category=electronics -a domain=system

Les araignées peuvent accéder aux arguments en tant qu'attributs:

class MySpider(scrapy.Spider):
    name = 'myspider'

    def __init__(self, category='', **kwargs):
        self.start_urls = [f'http://www.example.com/{category}']  # py36
        super().__init__(**kwargs)  # python3

    def parse(self, response)
        self.log(self.domain)  # system

Extrait du document Scrapy: http://doc.scrapy.org/en/latest/topics/spiders.html#spider-arguments

Mise à jour 2013 : ajouter un deuxième argument

Mise à jour 2015 : Ajuster le libellé

Mise à jour 2016 : utilisez la nouvelle classe de base et ajoutez super, merci @Birla

Mise à jour 2017 : utilisez Python3 super

# previously
super(MySpider, self).__init__(**kwargs)  # python2

Mise à jour 2018 : comme le souligne @eLRuLL , les araignées peuvent accéder aux arguments en tant qu'attributs

Steven Almeroth
la source
3
scrapy crawl myspider -a category = electronics -a domain = system
Steven Almeroth
1
Le code ci-dessus ne fonctionne que partiellement pour moi. Pour par exemple. Si je définis le domaine en utilisant self.domain, je ne suis toujours pas en mesure d'y accéder en dehors de la __init__méthode. Python renvoie une erreur non définie. BTW, pourquoi avez-vous omis l' superappel? PS. Je travaille avec la classe CrawlSpider
Birla
2
@FlyingAtom Veuillez me corriger si j'ai mal compris, mais chacun de ces appels simultanés serait des instances différentes de l'araignée, n'est-ce pas?
L Lawliet
1
@Birla, utilisez self.domain = domain dans le constructeur pour remplir la variable d'étendue de classe.
Hassan Raza
1
@nealmcb __init__est une méthode de la classe spider. Son implémentation ne rend pas elle-même l'araignée moins robuste et elle est incluse dans la réponse pour montrer que vous pouvez déclarer des valeurs par défaut pour les arguments de mots-clés, mais comme vous l'avez dit, c'est facultatif. Comme nous l'avons souligné l'année dernière, vous n'avez pas besoin d'utiliser, getattrvous pouvez simplement accéder aux arguments en tant qu'attributs, par exemple self.categoryou comme nous le voyons dans la réponseself.domain
Steven Almeroth
31

Les réponses précédentes étaient correctes, mais vous n'avez pas à déclarer le constructeur ( __init__) à chaque fois que vous voulez coder l'araignée d'un scrapy, vous pouvez simplement spécifier les paramètres comme avant:

scrapy crawl myspider -a parameter1=value1 -a parameter2=value2

et dans votre code d'araignée, vous pouvez simplement les utiliser comme arguments d'araignée:

class MySpider(Spider):
    name = 'myspider'
    ...
    def parse(self, response):
        ...
        if self.parameter1 == value1:
            # this is True

        # or also
        if getattr(self, parameter2) == value2:
            # this is also True

Et ça marche.

eLRuLL
la source
4
Vrai. Entrez dans le côté obscur de python.
Barney
14

Pour passer des arguments avec la commande crawl

scrapy crawl myspider -a category = 'ma catégorie' -a domaine = 'exemple.com'

Pour passer des arguments à exécuter sur scrapyd, remplacez -a par -d

curl http://your.ip.address.here:port/schedule.json -d spider = myspider -d category = 'ma catégorie' -d domaine = 'exemple.com'

L'araignée recevra des arguments dans son constructeur.


class MySpider(Spider):
    name="myspider"
    def __init__(self,category='',domain='', *args,**kwargs):
        super(MySpider, self).__init__(*args, **kwargs)
        self.category = category
        self.domain = domain

Scrapy met tous les arguments en tant qu'attributs d'araignée et vous pouvez ignorer complètement la méthode init . Attention, utilisez la méthode getattr pour obtenir ces attributs afin que votre code ne se casse pas.


class MySpider(Spider):
    name="myspider"
    start_urls = ('https://httpbin.org/ip',)

    def parse(self,response):
        print getattr(self,'category','')
        print getattr(self,'domain','')
Hassan Raza
la source
Succinct, robuste et flexible!
nealmcb
8

Les arguments Spider sont transmis lors de l'exécution de la commande crawl à l'aide de l'option -a. Par exemple, si je veux passer un nom de domaine comme argument à mon araignée, je le ferai-

scrapy crawl myspider -a domain = "http://www.example.com"

Et recevez des arguments dans les constructeurs d'araignée:

class MySpider(BaseSpider):
    name = 'myspider'
    def __init__(self, domain='', *args, **kwargs):
        super(MySpider, self).__init__(*args, **kwargs)
        self.start_urls = [domain]
        #

...

ça va marcher :)

Siyaram Malav
la source
0

Alternativement, nous pouvons utiliser ScrapyD qui expose une API où nous pouvons passer le start_url et le nom de l'araignée. ScrapyD a des API pour arrêter / démarrer / statut / lister les araignées.

pip install scrapyd scrapyd-deploy
scrapyd
scrapyd-deploy local -p default

scrapyd-deploydéploiera l'araignée sous forme d'oeuf dans le démon et maintiendra même la version de l'araignée. Lors du démarrage de l'araignée, vous pouvez mentionner la version de l'araignée à utiliser.

class MySpider(CrawlSpider):

    def __init__(self, start_urls, *args, **kwargs):
        self.start_urls = start_urls.split('|')
        super().__init__(*args, **kwargs)
    name = testspider

curl http://localhost:6800/schedule.json -d project=default -d spider=testspider -d start_urls="https://www.anyurl...|https://www.anyurl2"

L'avantage supplémentaire est que vous pouvez créer votre propre interface utilisateur pour accepter l'url et d'autres paramètres de l'utilisateur et planifier une tâche à l'aide de l'API de planification scrapyd ci-dessus.

Consultez la documentation de l'API scrapyd pour plus de détails

Nagendran
la source