Jak przekazać argument zdefiniowany przez użytkownika w Scrapy Spider

100

Próbuję przekazać argument zdefiniowany przez użytkownika do pająka scrapy's. Czy ktoś może zasugerować, jak to zrobić?

Czytałem -agdzieś o parametrze, ale nie mam pojęcia, jak go użyć.

L Lawliet
źródło

Odpowiedzi:

187

Argumenty Spider są przekazywane w crawlpoleceniu przy użyciu -aopcji. Na przykład:

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

Pająki mogą uzyskać dostęp do argumentów jako atrybutów:

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

Zaczerpnięte z dokumentu Scrapy: http://doc.scrapy.org/en/latest/topics/spiders.html#spider-arguments

Aktualizacja 2013 : dodaj drugi argument

Aktualizacja 2015 : Dostosuj sformułowanie

Aktualizacja 2016 : użyj nowszej klasy bazowej i dodaj super, dzięki @Birla

Aktualizacja 2017 : użyj Python3 super

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

Aktualizacja 2018 : Jak wskazuje @eLRuLL , pająki mogą uzyskać dostęp do argumentów jako atrybutów

Steven Almeroth
źródło
3
scrapy crawl myspider -a category = elektronika -a domain = system
Steven Almeroth
1
Powyższy kod działa u mnie tylko częściowo. Np. Jeśli zdefiniuję domenę przy użyciu self.domain, nadal nie mogę uzyskać do niej dostępu poza __init__metodą. Python zgłasza niezdefiniowany błąd. BTW, dlaczego pominąłeś superpołączenie? PS. Pracuję z klasą CrawlSpider
Birla
2
@FlyingAtom Proszę mnie poprawić, jeśli źle zrozumiałem, ale każde z tych jednoczesnych wezwań byłoby różnymi instancjami pająka, prawda?
L Lawliet
1
@Birla, użyj self.domain = domain w konstruktorze do wypełnienia zmiennej zakresu klasy.
Hassan Raza,
1
@nealmcb __init__to metoda klasy pająka. Jego implementacja sama w sobie nie czyni pająka mniej odpornym i jest uwzględniona w odpowiedzi, aby pokazać, że można zadeklarować wartości domyślne dla argumentów słów kluczowych, ale jak powiedziałeś, jest to opcjonalne. Jak wskazaliśmy w zeszłym roku, nie musisz używać getattrargumentów, możesz po prostu uzyskać dostęp do argumentów jako atrybutów, np. self.categoryLub jak widzimy w odpowiedziself.domain
Steven Almeroth
31

Poprzednie odpowiedzi były poprawne, ale nie musisz deklarować konstruktora ( __init__) za każdym razem, gdy chcesz zakodować pająka scrapy, możesz po prostu określić parametry jak poprzednio:

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

aw swoim kodzie pająka możesz po prostu użyć ich jako argumentów pająka:

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

I to po prostu działa.

eLRuLL
źródło
4
Prawdziwe. Wejdź w ciemną stronę Pythona.
Barney
14

Przekazywanie argumentów za pomocą polecenia crawl

indeksowanie scrapy myspider -a kategoria = 'moja kategoria' -a domena = 'example.com'

Przekazywać argumenty do uruchomienia na scrapyd zastąpić -a z -d

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

Pająk otrzyma argumenty w swoim konstruktorze.


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 umieszcza wszystkie argumenty jako atrybuty pająka i możesz całkowicie pominąć metodę init . Uważaj, aby uzyskać te atrybuty, użyj metody getattr, aby Twój kod się nie zepsuł.


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
źródło
Zwięzłe, solidne i elastyczne!
nealmcb
8

Argumenty pająka są przekazywane podczas wykonywania polecenia indeksowania z opcją -a. Na przykład, jeśli chcę przekazać nazwę domeny jako argument mojemu pająkowi, zrobię to-

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

I otrzymuj argumenty w konstruktorach pająka:

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

...

to będzie działać :)

Siyaram Malav
źródło
0

Alternatywnie możemy użyć ScrapyD, które ujawnia API, w którym możemy przekazać start_url i nazwę pająka. ScrapyD ma api do zatrzymywania / uruchamiania / statusu / wyświetlania pająków.

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

scrapyd-deploywdroży pająka w postaci jajka do demona, a nawet on zachowa wersję pająka. Uruchamiając pająka możesz wspomnieć, której wersji pająka użyć.

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"

Dodatkową zaletą jest to, że możesz zbudować własny interfejs użytkownika, aby akceptować adres URL i inne parametry od użytkownika i zaplanować zadanie za pomocą powyższego interfejsu API scrapyd

Patrz scrapyd dokumentacji API więcej szczegółów

Nagendran
źródło