2017-06-14 10 views
2

Ich schreibe eine Scrapy Spider, um eine Reise-Website zu durchlaufen. Die Struktur der Website ist die folgende:Python Scrapy web-crawling und scraping

Continents 
    North America 
     USA 
      lat: 123 
      long: 456 
     Canada 
      lat: 123 
      long: 456 
    South America 
     Brazil 
      lat: 456 
      long: 789 
     Peru 
      lat: 123 
      long: 456 

Ich habe herausgefunden, wie der einzelne Länder Seite zu kriechen und lat/long info mit dem Skript unten greifen, aber was ich habe Schwierigkeiten mit den technischen Daten zu speichern.

import scrapy 


class WorldSpider(scrapy.Spider): 
    name = "world" 

    def start_requests(self): 
     urls = [ 
      'www.world.com' 
     ] 
     for url in urls: 
      # yield scrapy.Request(url=url, callback=self.parse) 
      yield scrapy.Request(url=url, callback=self.parse_region) 

    def parse(self, response): 
     for link in response.css(CONTINENT_SELECTOR): 
      continent = link.css('a::attr(href)').extract_first() 
      if continent is not None: 
       continent = response.urljoin(continent) 
       yield response.follow(continent, callback=self.parse_continent) 

    def parse_continent(self, continent_response): 
     country_urls = continent_response.css(COUNTRY_SELECTOR) 
     if len(country_urls) == 0: 
      # This if-statement is entered when the Spider is at a country web page (e.g. USA, Canada, etc.). 
      # TODO figure out how to store this to text file or append to JSON object 
      yield { 
       'country': continent_response.css(TITLE_SELECTOR).extract_first(), 
       'latitude' : continent_response.css(LATITUDE_SELECTOR).extract_first(), 
       'longitude' : continent_response.css(LONGITUDE_SELECTOR).extract_first() 
      } 

     for link in country_urls: 
      country = link.css('a::attr(href)').extract_first() 
      if area is not None: 
       yield continent_response.follow(continent_response.urljoin(area), callback=self.parse_continent) 

Wie schreibe ich diese Informationen in eine Datei oder ein JSON-Objekt? Am besten gefällt mir die Struktur der Daten, um die Struktur der Website zu erfassen.

Beispiel:

{ 
    "continents": [ 
     {"North America" : [ 
      {"country" : {"title": "USA", "latitude" : 123, "longitude" : 456}}, 
      {"country" : {"title": "Canada", "latitude" : 123, "longitude" : 456}} 
     ]}, 
     {"South America" : [ 
      {"country" : {"title": "Brazil", "latitude" : 456, "longitude" : 789}}, 
      {"Peru" : {"title": "Peru", "latitude" : 123, "longitude" : 456}} 
     ]}   
    ] 
} 

Wie soll ich meine Spinne modifizieren oben Ziel zu erreichen?

+0

Sie müssen [** eine Pipeline **] (https://doc.scrapy.org/en/latest/topics/item-pipeline.html#write-items-to-a-json-file) – Jan

+0

@ Jan Vielen Dank für Ihre Eingabe. Ich arbeite immer noch mit Scrapy, also ist es hilfreich, zu wissen, was ich in der Dokumentation anschaue. Vielen Dank! – GobiasKoffi

Antwort

1

Das Speichern von Daten in Dateien kann auf zwei Arten erfolgen. Zuerst wird als @Jan erwähnt, unter Verwendung der JsonWritePipeline, wo eine solche Methode empfohlen wird, wenn die Scrapy Spinne viele Male ausgeführt wird und verwendet wird, um jedes Mal an die Datei anzuhängen.

Es folgt ein Beispiel für eine solche Ausführung:

with open(filename, 'a') as f: 
      f.write(response.body) 
self.log('Saved file %s' % filename) 

Obwohl die einfachste Methode, die Feed Export Optionen zu verwenden, die für eine einfachere Implementierung ermöglicht.

Feed Exporte, mit denen Sie einen Feed mit den Scraped-Elementen erstellen können, indem Sie mehrere Serialisierungsformate und Speicher-Backends verwenden. Für die Serialisierung der Scraped-Daten verwenden die Feed-Exporte den Artikel Exporteure. Diese Formate werden aus der Box unterstützt:

JSON 
    JSON lines 
    CSV 
    XML 

Es folgt ein Beispiel von Fileexport unter Verwendung von Daten als JSON-Datei zu speichern:

$scrapy crawl myExample -o output.json 

Hinweis: Scrapy anhängt, um ein gegebene Datei, anstatt den Inhalt zu überschreiben. Wenn Sie diesen Befehl zweimal ausführen, ohne die Datei vor der zweiten Zeit zu entfernen, werden Sie mit einer beschädigten JSON-Datei enden.

Was die Struktur von Daten in JSON, ich arbeite lieber mit Item wie es Ihnen eine sehr klaren Struktur im Auge bietet und mit vielen Tiefen JSONs vorzuziehen ist, die Struktur für die Überprüfung.

Für Ihre Implementierung sollte die Struktur so erklärt werden:

import scrapy 

class Address(scrapy.Item): 
    title = scrapy.Field() 
    latitude = scrapy.Field() 
    longitude = scrapy.Field() 

class Place(scrapy.Item): 
    country = scrapy.Field()   #object of Address 

class Continents(scrapy.Item): 
    name = scrapy.Field()    #array of Place 

Sie lasse ich herausfinden, wie das realisieren ;-)

-1

Scrapy bietet diese Funktionalität sofort mit den Feed-Exporten, mit denen Sie einen Feed mit den Scraped-Elementen erstellen können, indem Sie mehrere Serialisierungsformate und Speicher-Backends verwenden.

scrapy crawl WorldSpider -o name.json -t json 

werden die analysierten Elemente gespeichert.

+0

Danke für Ihre Eingabe. Ich werde einen Blick auf Feed-Exporte in der Scrapy-Dokumentation werfen. – GobiasKoffi