2013-03-22 9 views
10

C'è un modo per eseguire tutti gli spider in un progetto Scrapy senza utilizzare il daemon Scrapy? C'era un modo per eseguire più spider con scrapy crawl, ma quella sintassi è stata rimossa e il codice di Scrapy è cambiato parecchio.Locally esegue tutti gli spider in Scrapy

Ho cercato di creare il mio comando:

from scrapy.command import ScrapyCommand 
from scrapy.utils.misc import load_object 
from scrapy.conf import settings 

class Command(ScrapyCommand): 
    requires_project = True 

    def syntax(self): 
     return '[options]' 

    def short_desc(self): 
     return 'Runs all of the spiders' 

    def run(self, args, opts): 
     spman_cls = load_object(settings['SPIDER_MANAGER_CLASS']) 
     spiders = spman_cls.from_settings(settings) 

     for spider_name in spiders.list(): 
      spider = self.crawler.spiders.create(spider_name) 
      self.crawler.crawl(spider) 

     self.crawler.start() 

Ma una volta che un ragno è iscritto su self.crawler.crawl(), ricevo errori di asserzione per tutti gli altri ragni:

Traceback (most recent call last): 
    File "/usr/lib/python2.7/site-packages/scrapy/cmdline.py", line 138, in _run_command 
    cmd.run(args, opts) 
    File "/home/blender/Projects/scrapers/store_crawler/store_crawler/commands/crawlall.py", line 22, in run 
    self.crawler.crawl(spider) 
    File "/usr/lib/python2.7/site-packages/scrapy/crawler.py", line 47, in crawl 
    return self.engine.open_spider(spider, requests) 
    File "/usr/lib/python2.7/site-packages/twisted/internet/defer.py", line 1214, in unwindGenerator 
    return _inlineCallbacks(None, gen, Deferred()) 
--- <exception caught here> --- 
    File "/usr/lib/python2.7/site-packages/twisted/internet/defer.py", line 1071, in _inlineCallbacks 
    result = g.send(result) 
    File "/usr/lib/python2.7/site-packages/scrapy/core/engine.py", line 215, in open_spider 
    spider.name 
exceptions.AssertionError: No free spider slots when opening 'spidername' 

Esiste un modo per Fai questo? Preferirei non iniziare la sottoclasse dei componenti di base di Scrapy solo per eseguire tutti i miei spider in questo modo.

+0

Quale versione di Scrapy stai usando? '$ scrapy version -v' –

+0

Sai di [' scrapyd'] (http://doc.scrapy.org/en/latest/topics/scrapyd.html)? –

+0

'0.16.4'. So di Scrapyd, ma sto testando questi spider localmente, quindi preferirei non usarlo. – Blender

risposta

16

Ecco un esempio che non viene eseguito all'interno di un comando personalizzato, ma corre il reattore manualmente e crea un nuovo Crawler for each spider:

from twisted.internet import reactor 
from scrapy.crawler import Crawler 
# scrapy.conf.settings singlton was deprecated last year 
from scrapy.utils.project import get_project_settings 
from scrapy import log 

def setup_crawler(spider_name): 
    crawler = Crawler(settings) 
    crawler.configure() 
    spider = crawler.spiders.create(spider_name) 
    crawler.crawl(spider) 
    crawler.start() 

log.start() 
settings = get_project_settings() 
crawler = Crawler(settings) 
crawler.configure() 

for spider_name in crawler.spiders.list(): 
    setup_crawler(spider_name) 

reactor.run() 

si dovrà progettare some signal system per fermare il reattore quando tutti i ragni sono finito.

EDIT: Ed ecco come è possibile eseguire più ragni in un comando personalizzato:

from scrapy.command import ScrapyCommand 
from scrapy.utils.project import get_project_settings 
from scrapy.crawler import Crawler 

class Command(ScrapyCommand): 

    requires_project = True 

    def syntax(self): 
     return '[options]' 

    def short_desc(self): 
     return 'Runs all of the spiders' 

    def run(self, args, opts): 
     settings = get_project_settings() 

     for spider_name in self.crawler.spiders.list(): 
      crawler = Crawler(settings) 
      crawler.configure() 
      spider = crawler.spiders.create(spider_name) 
      crawler.crawl(spider) 
      crawler.start() 

     self.crawler.start() 
+0

Grazie, questo è esattamente quello che stavo cercando di fare. – Blender

+0

Come avviare il programma? – user1787687

+0

Inserisci il codice in un editor di testo e salva come 'mycoolcrawler.py'. In Linux è probabile che tu possa eseguire 'python mycoolcrawler.py' dalla riga di comando nella directory in cui l'hai salvato. In Windows forse puoi semplicemente fare doppio clic su di esso da file manager. –

14

Perché non basta usare qualcosa di simile:

scrapy list|xargs -n 1 scrapy crawl 

?

+1

Usa l'opzione '-P 0' per' xargs' per eseguire tutti gli spider in parallelo. – rgtk

4

la risposta di @Steven Almeroth sarà fallito nel Scrapy 1.0, e si dovrebbe modificare lo script come questo:

from scrapy.commands import ScrapyCommand 
from scrapy.utils.project import get_project_settings 
from scrapy.crawler import CrawlerProcess 

class Command(ScrapyCommand): 

    requires_project = True 
    excludes = ['spider1'] 

    def syntax(self): 
     return '[options]' 

    def short_desc(self): 
     return 'Runs all of the spiders' 

    def run(self, args, opts): 
     settings = get_project_settings() 
     crawler_process = CrawlerProcess(settings) 

     for spider_name in crawler_process.spider_loader.list(): 
      if spider_name in self.excludes: 
       continue 
      spider_cls = crawler_process.spider_loader.load(spider_name) 
      crawler_process.crawl(spider_cls) 
     crawler_process.start() 
0

questo codice è Monta sulla mia versione Scrapy è 1.3.3 (salvarlo nella stessa directory in scrapy.cfg):

from scrapy.utils.project import get_project_settings 
from scrapy.crawler import CrawlerProcess 

setting = get_project_settings() 
process = CrawlerProcess(setting) 

for spider_name in process.spiders.list(): 
    print ("Running spider %s" % (spider_name)) 
    process.crawl(spider_name,query="dvh") #query dvh is custom argument used in your scrapy 

process.start()