2016-03-23 19 views
1

Ich habe Scrapyd Server mit mehreren Spinnen zur gleichen Zeit ausgeführt, starte ich die Spinnen eins nach dem anderen mit dem schedule.json Endpunkt. Alle Spinnen schreiben Inhalte über gemeinsame DateiScrapyd mehrere Spinnen Artikel in dieselbe Datei schreiben

class JsonWriterPipeline(object): 

def __init__(self, json_filename): 
    # self.json_filepath = json_filepath 
    self.json_filename = json_filename 
    self.file = open(self.json_filename, 'wb') 

@classmethod 
def from_crawler(cls, crawler): 
    save_path='/tmp/' 
    json_filename=crawler.settings.get('json_filename', 'FM_raw_export.json') 
    completeName = os.path.join(save_path, json_filename) 
    return cls(
     completeName 
    ) 

def process_item(self, item, spider): 
    line = json.dumps(dict(item)) + "\n" 
    self.file.write(line) 
    return item 

Nachdem die Spinnen eine Pipeline mit laufen kann ich sehen, wie sie Daten richtig sammeln, Gegenstände in Dateien XXXX.jl gespeichert werden und die Spinnen richtig funktioniert, aber die Inhalte gecrawlt werden in der gemeinsamen Datei nicht wiedergegeben. Spiders scheint gut zu funktionieren, aber die Pipeline macht ihre Arbeit nicht gut und sammelt keine Daten in einer gemeinsamen Datei.

Ich bemerkte auch, dass nur eine Spinne gleichzeitig auf Datei schreibt.

Antwort

1

Ich sehe keinen guten Grund zu tun, was Sie tun :) Sie können die json_filename Einstellung ändern, indem Sie Argumente auf Ihrem scrapyd schedule.json Anfrage festlegen. Dann können Sie jede Spinne dazu bringen, leicht unterschiedliche Dateien zu generieren, die Sie mit der Nachbearbeitung oder zur Abfragezeit zusammenführen. Sie können JSON-Dateien auch ähnlich wie bei Ihnen schreiben, indem Sie einfach den Wert FEED_URI (example) eingeben. Wenn Sie aus mehreren Prozessen gleichzeitig in eine einzelne Datei schreiben (insbesondere wenn Sie mit 'wb' starten), suchen Sie nach beschädigten Daten.

Edit:

Nach ein bisschen besser zu verstehen, was Sie brauchen - in diesem Fall - es ist scrapyd starten mehrere kriecht verschiedene Spinnen laufen, wo jeder eine andere Website kriecht. Der Consumer-Prozess überwacht kontinuierlich eine einzelne Datei.

Es gibt verschiedene Lösungen, darunter:

  • Named Pipes

relativ einfach für sehr kleine Gegenstände und ok zu implementieren nur (see here)

  • RabbitMQ oder ein anderer Warteschlangenmechanismus

Große Lösung, aber könnte ein bisschen übertrieben sein

  • Eine Datenbank z. SQLite-basierte Lösung

Schön und einfach, erfordert aber wahrscheinlich einige Codierung (individuelle Verbraucher)

  • Eine schöne inotifywait -basierte oder andere Dateisystem-Monitoring-Lösung

Nizza und wahrscheinlich leicht

zu implementieren

Der letzte scheint die attraktivste Option für mich. Wenn scrapy crawl beendet wird (spider_closed signal), verschieben, kopieren oder erstellen Sie einen Softlink für die Datei FEED_URL in ein Verzeichnis, das Sie mit einem Skript wie this überwachen. mv oder ln ist eine atomare Unix-Operation, so sollten Sie in Ordnung sein. Hacken Sie das Skript, um die neue Datei an Ihre tmp Datei anzuhängen, die Sie einmal an Ihr Verbraucherprogramm senden.

Mit dieser Methode verwenden Sie die Standard-Feed-Exporteure, um Ihre Dateien zu schreiben. Die Endlösung ist so einfach, dass Sie keine Pipeline benötigen. Eine einfache Erweiterung sollte die Rechnung erfüllen.

Auf einem extensions.py im selben Verzeichnis wie settings.py:

from scrapy import signals 
from scrapy.exceptions import NotConfigured 

class MoveFileOnCloseExtension(object): 

    def __init__(self, feed_uri): 
     self.feed_uri = feed_uri 

    @classmethod 
    def from_crawler(cls, crawler): 
     # instantiate the extension object 
     feed_uri = crawler.settings.get('FEED_URI') 
     ext = cls(feed_uri) 

     crawler.signals.connect(ext.spider_closed, signal=signals.spider_closed) 

     # return the extension object 
     return ext 

    def spider_closed(self, spider): 
     # Move the file to the proper location 
     # os.rename(self.feed_uri, ... destination path...) 

Auf Ihrem settings.py:

EXTENSIONS = { 
    'myproject.extensions.MoveFileOnCloseExtension': 500, 
} 
+0

Vielen Dank für Ihre Antwort. Ich denke, ich verstehe nicht gut, wie Pipelines in scrapy arbeiten. Nach meinem Verständnis generiert der Spider Items, die Items aller Spider werden an die Pipeline weitergeleitet, die für alle global ist, und sie verarbeiten. Aus Ihrer Antwort gehe ich davon aus, dass jede Spinne eine eigene Pipeline hat und mehrere Pipelines mit derselben Datei arbeiten, was zu Problemen führt. Habe ich recht? . Ich mache es auf diese Weise, weil es einen anderen Prozess gibt, der etwas mit dem Inhalt macht und nur eine Datei akzeptiert. – silvestrelosada

+0

Die Phrasierung ist nicht 100% genau, aber was Sie sagen, ist richtig. Genauer gesagt führt Scrapyd mehrere Scrapy-Prozesse parallel durch. Jeder Scrapy-Prozess führt eine Spinne und deine Pipeline aus. Dies bedeutet, dass Sie während dieses Crawls dieselbe Datei öffnen, um von vielen Prozessen zu schreiben, was zu Korruption führt. "... akzeptiert nur eine Datei". Ich bin mir sicher, dass es einen besseren Weg gibt, dies zu tun. Kannst du Scrapyd laufen lassen? 100 Dateien daraus, [concat sie zu einem] (http://stackoverflow.com/questions/4969641/append-one-file-to-another-in-linux) und dann das zu Ihrem Prozess füttern? Dies ist viel häufiger. – neverlastn

+0

Kennen Sie eine Option, um das Ergebnis (Elemente) aller Spider auf dieselbe Datei mit nur scrappy zu setzen? Dank – silvestrelosada