2017-06-13 2 views
1

Set-upWie url durch zwei Funktionen übergeben - Rückruf

I Wohnungsanzeigen mit scrapy bin Schaben: pro Gehäuse ad ich mehrere Gehäuseeigenschaften kratzen.

Schaben der Gehäuseeigenschaften funktioniert gut.


Problem

Neben den Gehäuseeigenschaften, möchte ich ein Bild pro Anzeige kratzen.

Ich habe den folgenden Code:

class ApartmentSpider(scrapy.Spider): 
name = 'apartments' 
start_urls = [ 
    'http://www.jaap.nl/huurhuizen/noord+holland/groot-amsterdam/amsterdam' 
    ] 

def parse(self, response): 
     for href in response.xpath(
       '//*[@id]/a', 
       ).css("a.property-inner::attr(href)").extract(): 
      yield scrapy.Request(response.urljoin(href), 
        callback=self.parse_ad) # parse_ad() scrapes housing characteristics 
      yield scrapy.Request(response.urljoin(href), 
        callback=self.parse_AdImage) # parse_AdImage() obtains one image per ad 

Also, ich habe zwei yield Befehle, die nicht funktioniert. Das heißt, ich bekomme die Eigenschaften, aber nicht die Bilder.

Ich kann die erste kommentieren, so dass ich die Bilder bekomme.

Wie behebe ich das so, dass ich beides bekomme? Danke im Voraus.

+0

Was war die Absicht zweimal hinter Nachgeben? Es scheint die naheliegendste Lösung zu sein, beide gleichzeitig zu senden. –

+0

Ich möchte sowohl die Eigenschaften als auch das Bild.Also zwei Renditen, da ich nicht weiß, wie ich es beherrschen soll, dass ein Ertrag mir das gewünschte Ergebnis gibt. Diese "intuitive" Lösung ist eindeutig fehlgeschlagen. – LucSpan

+0

Warum nicht nur ein Tupel beider Ergebnisse ergeben? – alexis

Antwort

0

Ergeben Sie sie beide zusammen.

yield (scrapy.Request(response.urljoin(href), callback=self.parse_ad), scrapy.Request(response.urljoin(href), callback=self.parse_AdImage)) 

am empfangenden Ende, greifen sowohl als separate Werte

characteristics, image = ApartmentSpider.parse(response) 
+0

Danke Alex, ich bin mir nicht sicher, aber was du mit "auf der Empfängerseite" meinst? – LucSpan

+0

Überall dort, wo Sie den aus der Rendite zurückgegebenen Wert erfassen. Sie ändern Ihren Rückgabetyp in ein Tupel. Um das gleiche Verhalten beizubehalten, das Sie jetzt haben, setzen Sie die beiden Variablen, die Sie heute verwenden, um diese Informationen in der gleichen Zeile links vom Gleichheitszeichen zu speichern, getrennt durch ein Komma. –

0

Ich habe zwei wichtige Vorschläge:

Nummer 1

Ich würde vorschlagen, stark wieder arbeiten, um Ihre Code, um alle Informationen gleichzeitig zu verwalten. Anstatt zwei separate parse_X-Funktionen zu haben, brauchen Sie nur eine, die die Informationen erhält und ein einzelnes Element zurückgibt.

Nummer 2

eine Spinne Middleware implementieren, die Spaltung nicht verschmelzenden/ähnlich dem, was ich für Rohrleitungen unterhalb haben. Ein einfaches Beispiel Middleware ist https://github.com/scrapy/scrapy/blob/ebef6d7c6dd8922210db8a4a44f48fe27ee0cd16/scrapy/spidermiddlewares/urllength.py. Sie würden einfach Elemente zusammenführen und sie hier verfolgen, bevor sie die Artikelpipelines eingeben.

WARNUNG NICHT TUN, WAS UNTEN IST. Ich wollte dies vorschlagen, und der Code könnte funktionieren ... aber mit einigen potentiell versteckten Fragen.

ES aus Vollständigkeitsgründen, was ich erforschte - ES IST GEGEN HIER EMPFEHLUNGEN: https://github.com/scrapy/scrapy/issues/1915

Verwenden Sie die Artikel Verarbeitungspipelines in scrapy. Sie sind unglaublich nützlich zum Sammeln von Daten. Verfüge über eine Element-Joiner-Pipeline, deren Zweck es ist, auf die zwei separaten Teildatenelemente zu warten und sie zu einem Element zu verketten und sie in der Anzeigen-ID (oder einem anderen eindeutigen Datenelement) einzugeben.

In rauen nicht-runnable psuedocode:

class HousingItemPipeline(object): 
    def __init__(): 
     self.assembledItems = dict() 
    def process_item(self, item, spider): 
     if type(item, PartialAdHousingItem): 
      self.assembledItems[unique_id] = AssembledHousingItem() 
      self.assembledItems[unique_id]['field_of_interst'] = ... 
      ...assemble more data 
      raise DropItem("Assembled it's data") 
     if type(item, PartialAdImageHousingItem): 
      self.assembledItems[unique_id]['field_of_interst'] = ... 
      ...assemble more data 
      raise DropItem("Assembled it's data") 
     if Fully Assembled: 
      return self.assembledItems.pop(unique_id) 
Verwandte Themen