Come passare un argomento definito dall'utente in scrapy spider


100

Sto cercando di passare un argomento definito dall'utente al ragno di uno scrapy. Qualcuno può suggerire come farlo?

Ho letto di un parametro -ada qualche parte ma non ho idea di come usarlo.

Risposte:


187

Gli argomenti del ragno vengono passati nel crawlcomando utilizzando l' -aopzione. Per esempio:

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

Gli spider possono accedere agli argomenti come attributi:

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

Tratto dal documento Scrapy: http://doc.scrapy.org/en/latest/topics/spiders.html#spider-arguments

Aggiornamento 2013 : aggiungi il secondo argomento

Aggiornamento 2015 : modifica della formulazione

Aggiornamento 2016 : usa la nuova classe base e aggiungi super, grazie @Birla

Aggiornamento 2017 : usa Python3 super

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

Aggiornamento 2018 : come sottolinea @eLRuLL , gli spider possono accedere agli argomenti come attributi


3
scrapy crawl myspider -a category = electronics -a domain = system
Steven Almeroth

1
Il codice sopra funziona solo parzialmente per me. Per es. Se definisco l'utilizzo del dominio self.domain, non riesco ancora ad accedervi al di fuori del __init__metodo. Python genera un errore non definito. BTW, perché hai omesso la superchiamata? PS. Sto lavorando con la classe CrawlSpider
Birla

2
@FlyingAtom Per favore correggimi se ho frainteso, ma ognuna di queste chiamate simultanee sarebbe istanze diverse del ragno, non è vero?
L Lawliet

1
@Birla, usa self.domain = domain nel costruttore per popolare la variabile dell'ambito della classe.
Hassan Raza

1
@nealmcb __init__è un metodo della classe spider. La sua implementazione non rende di per sé lo spider meno robusto ed è incluso nella risposta per mostrare che puoi dichiarare i valori predefiniti per gli argomenti delle parole chiave ma come hai detto è opzionale. Come abbiamo sottolineato l'anno scorso non è necessario utilizzarlo getattr, puoi semplicemente accedere agli argomenti come attributi, ad esempio self.categoryo come vediamo nella rispostaself.domain
Steven Almeroth

31

Le risposte precedenti erano corrette, ma non è necessario dichiarare il costruttore ( __init__) ogni volta che si desidera codificare lo spider di uno scrapy, è sufficiente specificare i parametri come prima:

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

e nel tuo codice spider puoi semplicemente usarli come argomenti spider:

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

E funziona e basta.


4
Vero. Entra nel lato oscuro del pitone.
Barney

14

Per passare argomenti con il comando di scansione

scrapy crawl myspider -a category = 'mycategory' -a domain = 'example.com'

Per passare argomenti da eseguire su scrapyd, sostituire -a con -d

curl http://your.ip.address.here:port/schedule.json -d spider = myspider -d category = 'mycategory' -d domain = 'example.com'

Il ragno riceverà argomenti nel suo costruttore.


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 mette tutti gli argomenti come attributi spider e puoi saltare completamente il metodo init . Fai attenzione all'uso del metodo getattr per ottenere quegli attributi in modo che il tuo codice non si interrompa.


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

    def parse(self,response):
        print getattr(self,'category','')
        print getattr(self,'domain','')

Succinto, robusto e flessibile!
nealmcb

8

Gli argomenti Spider vengono passati durante l'esecuzione del comando di scansione utilizzando l'opzione -a. Ad esempio, se voglio passare un nome di dominio come argomento al mio spider, lo farò-

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

E ricevi argomenti nei costruttori di spider:

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

...

Funzionerà :)


0

In alternativa possiamo usare ScrapyD che espone un'API dove possiamo passare start_url e il nome dello spider. ScrapyD ha API per arrestare / avviare / visualizzare / elencare i ragni.

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

scrapyd-deploydistribuirà il ragno sotto forma di uovo nel daemon e anche mantiene la versione del ragno. Durante l'avvio del ragno puoi indicare quale versione di ragno usare.

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"

Il vantaggio aggiuntivo è che puoi creare la tua interfaccia utente per accettare l'URL e altri parametri dall'utente e pianificare un'attività utilizzando l'API di pianificazione scrapyd sopra

Fare riferimento alla documentazione API di scrapyd per maggiori dettagli

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.