Como passar um argumento definido pelo usuário no scrapy spider

100

Estou tentando passar um argumento definido pelo usuário para um scrapy's spider. Alguém pode sugerir como fazer isso?

Eu li sobre um parâmetro em -aalgum lugar, mas não tenho ideia de como usá-lo.

L Lawliet
fonte

Respostas:

188

Os argumentos do Spider são passados ​​no crawlcomando usando a -aopção. Por exemplo:

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

Spiders podem acessar argumentos como atributos:

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

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

Atualização 2013 : Adicionar segundo argumento

Atualização 2015 : Ajustar redação

Atualização 2016 : use a classe base mais recente e adicione super, obrigado @Birla

Atualização de 2017 : use Python3 super

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

Atualização 2018 : como @eLRuLL aponta , os spiders podem acessar argumentos como atributos

Steven Almeroth
fonte
3
scrapy crawl myspider -a category = eletrônicos -a domain = system
Steven Almeroth
1
O código acima está funcionando apenas parcialmente para mim. Por exemplo. Se eu definir domínio usando self.domain, ainda não consigo acessá-lo fora do __init__método. Python gera um erro não definido. BTW, por que você omitiu a superchamada? PS. Estou trabalhando com a classe CrawlSpider
Birla
2
@FlyingAtom Por favor, corrija-me se eu entendi mal, mas cada uma dessas chamadas simultâneas seriam instâncias diferentes do spider, não seria?
L Lawliet,
1
@Birla, use self.domain = domain no construtor para preencher a variável de escopo da classe.
Hassan Raza,
1
@nealmcb __init__é um método da classe spider. Sua implementação não torna o spider menos robusto e está incluído na resposta para mostrar que você pode declarar padrões para argumentos de palavra-chave, mas como você disse, é opcional. Como apontamos no ano passado, você não precisa usar, getattrvocê pode apenas acessar os argumentos como atributos, por exemplo, self.categoryou como vemos na respostaself.domain
Steven Almeroth
31

As respostas anteriores estavam corretas, mas você não precisa declarar o construtor ( __init__) toda vez que quiser codificar um spider de scrapy, você pode apenas especificar os parâmetros como antes:

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

e em seu código de aranha você pode apenas usá-los como argumentos de aranha:

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 simplesmente funciona.

eLRuLL
fonte
4
Verdade. Entre no lado negro do python.
Barney de
14

Para passar argumentos com o comando crawl

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

Para passar argumentos para executar em scrapyd, substitua -a por -d

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

O spider receberá argumentos em seu construtor.


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

O Scrapy coloca todos os argumentos como atributos de aranha e você pode pular o método init completamente. Cuidado com o uso do método getattr para obter esses atributos para que seu código não seja interrompido.


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
fonte
Sucinto, robusto e flexível!
nealmcb
8

Os argumentos do Spider são transmitidos durante a execução do comando crawl usando a opção -a. Por exemplo, se eu quiser passar um nome de domínio como argumento para o meu spider, então farei isso-

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

E receba argumentos nos construtores de aranha:

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

...

vai funcionar :)

Siyaram Malav
fonte
0

Alternativamente, podemos usar o ScrapyD, que expõe uma API onde podemos passar o start_url e o nome do spider. ScrapyD tem APIs para parar / iniciar / status / listar os spiders.

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

scrapyd-deployirá implantar a aranha na forma de ovo no daemon e até mesmo manter a versão da aranha. Ao iniciar a aranha, você pode mencionar qual versão da aranha usar.

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"

A vantagem adicional é que você pode construir sua própria IU para aceitar o url e outros parâmetros do usuário e agendar uma tarefa usando a API de agendamento de scrapyd acima

Consulte a documentação da API do scrapyd para obter mais detalhes

Nagendran
fonte