2013-03-22 13 views
10

Gibt es eine Möglichkeit, alle Spider in einem Scrapy-Projekt auszuführen, ohne den Scrapy-Daemon zu verwenden? Früher gab es eine Möglichkeit, mehrere Spider mit scrapy crawl auszuführen, aber diese Syntax wurde entfernt und Scrapys Code änderte sich ziemlich stark.Führen Sie alle Spider lokal in Scrapy aus.

habe ich versucht, meine eigenen Befehl zu erstellen:

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() 

Aber sobald eine Spinne mit self.crawler.crawl() registriert ist, erhalte ich Behauptung Fehler für alle anderen Spinnen:

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' 

Gibt es eine Möglichkeit zu mach das? Ich würde eher nicht damit beginnen, Core-Scrapy-Komponenten zu untergliedern, nur um all meine Spinnen so laufen zu lassen.

+0

Welche Scrapy-Version verwenden Sie? '$ scrapy version -v' –

+0

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

+0

'0.16.4'. Ich weiß von Scrapyd, aber ich teste diese Spinnen lokal, also würde ich es lieber nicht benutzen. – Blender

Antwort

16

Hier ist ein Beispiel, das nicht in einem benutzerdefinierten Befehl ausführen, aber den Reactor läuft manuell und erstellt einen neuen 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() 

Sie some signal system entwerfen müssen, um den Reaktor zu stoppen, wenn alle Spinnen fertig.

EDIT: Und hier ist, wie Sie mehrere Spinnen in einem benutzerdefinierten Befehl ausführen können:

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

Danke, genau das habe ich versucht. – Blender

+0

Wie kann ich das Programm starten? – user1787687

+0

Setzen Sie den Code in einen Texteditor und speichern Sie ihn als 'mycoolcrawler.py'. Unter Linux können Sie 'python mycoolcrawler.py' von der Befehlszeile in dem Verzeichnis ausführen, in dem Sie es gespeichert haben. In Windows können Sie es vielleicht einfach aus dem Datei-Manager heraus doppelklicken. –

14

Warum so etwas wie hast du nicht nur verwenden:

scrapy list|xargs -n 1 scrapy crawl 

? Version

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() 
+1

Verwenden Sie die Option "-P 0" für 'xargs', um alle Spider parallel laufen zu lassen. – rgtk

4

die Antwort von @ Steven Almeroth wird in Scrapy 1.0, und Sie sollten das Skript wie folgt bearbeiten nicht bestanden Verzeichnis 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() 
0

dieser Code funktioniert auf meinem scrapy ist 1.3.3 (in gleichen sparen:

Verwandte Themen