Cara melewatkan argumen yang ditentukan pengguna di scrapy spider

100

Saya mencoba untuk memberikan argumen yang ditentukan pengguna ke laba-laba scrapy. Adakah yang bisa menyarankan bagaimana melakukan itu?

Saya membaca tentang suatu parameter di -asuatu tempat tetapi tidak tahu cara menggunakannya.

L Lawliet
sumber

Jawaban:

187

Argumen laba-laba diteruskan dalam crawlperintah menggunakan -aopsi. Sebagai contoh:

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

Spider dapat mengakses argumen sebagai atribut:

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

Diambil dari dokumen Scrapy: http://doc.scrapy.org/en/latest/topics/spiders.html#spider-arguments

Pembaruan 2013 : Tambahkan argumen kedua

Pembaruan 2015 : Sesuaikan kata-kata

Pembaruan 2016 : Gunakan kelas dasar yang lebih baru dan tambahkan super, terima kasih @Birla

Pembaruan 2017 : Gunakan super Python3

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

Pembaruan 2018 : Seperti yang ditunjukkan @eLRuLL , spider dapat mengakses argumen sebagai atribut

Steven Almeroth
sumber
3
scrapy crawl myspider -a category = electronics -a domain = system
Steven Almeroth
1
Kode di atas hanya berfungsi sebagian untuk saya. Misalnya. Jika saya mendefinisikan domain menggunakan self.domain, saya masih tidak dapat mengaksesnya di luar __init__metode. Python memunculkan kesalahan yang tidak ditentukan. BTW, mengapa Anda mengabaikan superpanggilan? PS. Saya bekerja dengan kelas CrawlSpider
Birla
2
@FlyingAtom Harap perbaiki saya jika saya salah paham, tetapi setiap panggilan bersamaan ini akan menjadi contoh laba-laba yang berbeda, bukan?
L Lawliet
1
@Birla, gunakan self.domain = domain dalam konstruktor untuk mengisi variabel cakupan kelas.
Hassan Raza
1
@nealmcb __init__adalah metode kelas spider. Implementasinya tidak dengan sendirinya membuat laba-laba menjadi kurang kuat dan itu termasuk dalam jawaban untuk menunjukkan bahwa Anda dapat mendeklarasikan default untuk argumen kata kunci tetapi seperti yang Anda katakan itu opsional. Seperti yang kami tunjukkan tahun lalu Anda tidak perlu menggunakan getattrAnda hanya dapat mengakses argumen sebagai atribut, misalnya self.categoryatau seperti yang kita lihat dalam jawabanself.domain
Steven Almeroth
31

Jawaban sebelumnya benar, tetapi Anda tidak perlu mendeklarasikan konstruktor ( __init__) setiap kali Anda ingin mengkodekan spider scrapy, Anda dapat menentukan parameter seperti sebelumnya:

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

dan dalam kode laba-laba Anda, Anda bisa menggunakannya sebagai argumen laba-laba:

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

Dan itu berhasil.

eLRuLL
sumber
4
Benar. Masukkan sisi gelap python.
Barney
14

Untuk meneruskan argumen dengan perintah crawl

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

Untuk meneruskan argumen agar berjalan di scrapyd, ganti -a dengan -d

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

Laba-laba akan menerima argumen dalam konstruktornya.


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 menempatkan semua argumen sebagai atribut spider dan Anda dapat melewati metode init sepenuhnya. Hati-hati gunakan metode getattr untuk mendapatkan atribut tersebut sehingga kode Anda tidak rusak.


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
sumber
Ringkas, kuat, dan fleksibel!
nealmcb
8

Argumen laba-laba diteruskan saat menjalankan perintah perayapan menggunakan opsi -a. Misalnya jika saya ingin memberikan nama domain sebagai argumen untuk laba-laba saya maka saya akan melakukan ini-

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

Dan menerima argumen di konstruktor laba-laba:

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

...

itu akan berhasil :)

Siyaram Malav
sumber
0

Alternatifnya kita bisa menggunakan ScrapyD yang mengekspos API dimana kita bisa meneruskan nama start_url dan spider. ScrapyD memiliki api untuk menghentikan / memulai / status / daftar laba-laba.

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

scrapyd-deployakan menyebarkan laba-laba dalam bentuk telur ke daemon dan bahkan mempertahankan versi laba-laba. Saat memulai laba-laba, Anda dapat menyebutkan laba-laba versi mana yang akan digunakan.

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"

Keuntungan tambahannya adalah Anda dapat membangun UI Anda sendiri untuk menerima url dan parameter lain dari pengguna dan menjadwalkan tugas menggunakan API jadwal scrapyd di atas

Lihat dokumentasi API scrapyd untuk lebih jelasnya

Nagendran
sumber