2012-05-12 10 views
9

Voglio essere in grado di eseguire il Scrapy web crawling framework da dentro Django. Scrapy fornisce solo uno strumento da riga di comando scrapy per eseguire i suoi comandi, vale a dire che lo strumento non è stato scritto in modo intenzionale per essere chiamato da un programma esterno.Comando di gestione personalizzato Django in esecuzione Scrapy: come includere le opzioni di Scrapy?

L'utente Mikhail Korobov ha creato uno nice solution, ovvero per chiamare Scrapy da un comando di gestione personalizzato Django. Per comodità, ripeto la sua soluzione qui:

# -*- coding: utf-8 -*- 
# myapp/management/commands/scrapy.py 

from __future__ import absolute_import 
from django.core.management.base import BaseCommand 

class Command(BaseCommand): 

    def run_from_argv(self, argv): 
     self._argv = argv 
     return super(Command, self).run_from_argv(argv) 

    def handle(self, *args, **options): 
     from scrapy.cmdline import execute 
     execute(self._argv[1:]) 

Invece di chiamare ad es. scrapy crawl domain.com Ora posso fare python manage.py scrapy crawl domain.com da un progetto Django. Tuttavia, le opzioni di un comando Scrapy non vengono affatto analizzate. Se lo faccio python manage.py scrapy crawl domain.com -o scraped_data.json -t json, ho solo la seguente risposta:

Usage: manage.py scrapy [options] 

manage.py: error: no such option: -o 

Quindi la mia domanda è, come estendere il comando di gestione personalizzato per adottare le opzioni della riga di comando di Scrapy?

Sfortunatamente, il numero documentation of this part di Django non è molto esteso. Ho letto anche la documentazione di Python optparse module ma in seguito non è stato più chiaro per me. Qualcuno può aiutarmi in questo senso? Grazie mille in anticipo!

+0

ma non dovremmo essere nella directory principale per eseguire la scansione ?? Come è fatto? @pemistahl – Nabin

risposta

5

Ok, ho trovato una soluzione al mio problema. È un po 'brutto ma funziona. Poiché il comando manage.py del progetto Django non accetta le opzioni della riga di comando di Scrapy, ho diviso la stringa di opzioni in due argomenti che sono accettati da manage.py. Dopo aver completato con successo l'analisi, mi unisco ai due argomenti e li passo a Scrapy.

Cioè, invece di scrivere

python manage.py scrapy crawl domain.com -o scraped_data.json -t json 

inserire spazi tra le opzioni come questo

python manage.py scrapy crawl domain.com - o scraped_data.json - t json 

La mia funzione

maniglia assomiglia a questo:

def handle(self, *args, **options): 
    arguments = self._argv[1:] 
    for arg in arguments: 
     if arg in ('-', '--'): 
      i = arguments.index(arg) 
      new_arg = ''.join((arguments[i], arguments[i+1])) 
      del arguments[i:i+2] 
      arguments.insert(i, new_arg) 

    from scrapy.cmdline import execute 
    execute(arguments) 

Nel frattempo, Mikhail Korobov ha fornito la soluzione ottimale. Vedi qui:

# -*- coding: utf-8 -*- 
# myapp/management/commands/scrapy.py 

from __future__ import absolute_import 
from django.core.management.base import BaseCommand 

class Command(BaseCommand): 

    def run_from_argv(self, argv): 
     self._argv = argv 
     self.execute() 

    def handle(self, *args, **options): 
     from scrapy.cmdline import execute 
     execute(self._argv[1:]) 
3

penso che stai veramente cercando orientamento 10 del POSIX argument syntax conventions:

L'argomento - dovrebbe essere accettato come un delimitatore che indica la fine delle opzioni. I seguenti argomenti devono essere considerati come operandi, anche se iniziano con il carattere '-'. L'argomento - non dovrebbe essere usato come opzione o come operando.

Il modulo Python optparse si comporta in questo modo, anche in Windows.

ho messo il modulo impostazioni del progetto Scrapy nella lista degli argomenti, quindi posso creare progetti Scrapy separati in applicazioni indipendenti:

# <app>/management/commands/scrapy.py 
from __future__ import absolute_import 
import os 

from django.core.management.base import BaseCommand 

class Command(BaseCommand): 
    def handle(self, *args, **options): 
     os.environ['SCRAPY_SETTINGS_MODULE'] = args[0] 
     from scrapy.cmdline import execute 
     # scrapy ignores args[0], requires a mutable seq 
     execute(list(args)) 

Invocato come segue:

python manage.py scrapy myapp.scrapyproj.settings crawl domain.com -- -o scraped_data.json -t json 

Testato con Scrapy 0,12 e django 1.3.1