So übergeben Sie ein benutzerdefiniertes Argument in Scrapy Spider

100

Ich versuche, ein benutzerdefiniertes Argument an die Spinne eines Scrapys zu übergeben. Kann jemand vorschlagen, wie das geht?

Ich habe -airgendwo über einen Parameter gelesen , habe aber keine Ahnung, wie ich ihn verwenden soll.

L Lawliet
quelle

Antworten:

187

Spider-Argumente werden im crawlBefehl mit der -aOption übergeben. Beispielsweise:

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

Spinnen können auf Argumente als Attribute zugreifen:

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

Entnommen aus dem Scrapy-Dokument: http://doc.scrapy.org/en/latest/topics/spiders.html#spider-arguments

Update 2013 : Zweites Argument hinzufügen

Update 2015 : Wortlaut anpassen

Update 2016 : Verwenden Sie eine neuere Basisklasse und fügen Sie super hinzu, danke @Birla

Update 2017 : Verwenden Sie Python3 super

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

Update 2018 : Wie @eLRuLL hervorhebt, können Spinnen als Attribute auf Argumente zugreifen

Steven Almeroth
quelle
3
Scrapy Crawl Myspider -a Kategorie = Elektronik -a Domain = System
Steven Almeroth
1
Der obige Code funktioniert bei mir nur teilweise. Zum Beispiel. Wenn ich Domain mit definiere self.domain, kann ich außerhalb der __init__Methode immer noch nicht darauf zugreifen . Python gibt einen nicht definierten Fehler aus. Übrigens, warum haben Sie den superAnruf weggelassen ? PS. Ich arbeite mit der CrawlSpider-Klasse
Birla
2
@FlyingAtom Bitte korrigieren Sie mich, wenn ich falsch verstanden habe, aber jeder dieser gleichzeitigen Aufrufe wäre eine andere Instanz der Spinne, nicht wahr?
L Lawliet
1
@Birla, verwenden Sie self.domain = domain im Konstruktor, um die Klassenbereichsvariable zu füllen.
Hassan Raza
1
@nealmcb __init__ist eine Methode der Spinnenklasse. Die Implementierung selbst macht die Spinne nicht weniger robust und ist in der Antwort enthalten, um zu zeigen, dass Sie Standardwerte für Schlüsselwortargumente deklarieren können, aber wie Sie sagten, ist dies optional. Wie wir letztes Jahr betont haben, müssen Sie nicht getattrauf Argumente als Attribute zugreifen, z. B. self.categoryoder wie wir in der Antwort sehenself.domain
Steven Almeroth
31

Frühere Antworten waren korrekt, aber Sie müssen den Konstruktor ( __init__) nicht jedes Mal deklarieren, wenn Sie die Spinne eines Scrapys codieren möchten. Sie können die Parameter einfach wie zuvor angeben:

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

und in Ihrem Spinnencode können Sie sie einfach als Spinnenargumente verwenden:

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

Und es funktioniert einfach.

eLRuLL
quelle
3
Wahr. Betreten Sie die dunkle Seite von Python.
Barney
14

Argumente mit dem Befehl crawl übergeben

Scrapy Crawlen myspider -a category = 'mycategory' -a domain = 'example.com'

Um Argumente zu übergeben, die auf Scrapyd ausgeführt werden sollen, ersetzen Sie -a durch -d

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

Die Spinne erhält Argumente in ihrem Konstruktor.


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 fügt alle Argumente als Spider-Attribute ein und Sie können die init- Methode vollständig überspringen . Beachten Sie , dass Sie die getattr- Methode verwenden, um diese Attribute abzurufen , damit Ihr Code nicht beschädigt wird.


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
quelle
Prägnant, robust und flexibel!
Nealmcb
8

Spider-Argumente werden übergeben, während der Crawl-Befehl mit der Option -a ausgeführt wird. Wenn ich zum Beispiel einen Domainnamen als Argument an meine Spinne übergeben möchte, werde ich dies tun:

Scrapy Crawl Myspider -a Domain = "http://www.example.com"

Und erhalten Sie Argumente in Spinnenkonstruktoren:

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

...

es wird klappen :)

Siyaram Malav
quelle
0

Alternativ können wir ScrapyD verwenden, das eine API verfügbar macht , in der wir den Namen start_url und spider übergeben können. ScrapyD hat APIs zum Stoppen / Starten / Statusieren / Auflisten der Spinnen.

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

scrapyd-deploywird die Spinne in Form eines Eies in den Dämon einsetzen und sogar die Version der Spinne beibehalten. Beim Starten der Spinne können Sie angeben, welche Version der Spinne verwendet werden soll.

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"

Ein zusätzlicher Vorteil ist, dass Sie Ihre eigene Benutzeroberfläche erstellen können, um die URL und andere Parameter vom Benutzer zu akzeptieren und eine Aufgabe mithilfe der oben genannten Scrapyd-Zeitplan-API zu planen

Weitere Informationen finden Sie in der Scrapyd-API-Dokumentation

Nagendran
quelle