2017-06-13 48 views
1

建立如何通過兩個功能來傳遞網址 - 回調

我刮住房廣告中scrapy:每租房信息我湊幾個住房特徵。

刮擦住房的特點工作正常。


問題

除了住房特點,我想湊每個廣告一個圖像。

我有以下代碼:

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 

所以,我有兩個yield命令,這是行不通的。也就是說,我得到的是特徵,但不是圖像。

我可以評論第一個,這樣我就可以得到圖像。

我該如何解決這個問題?提前致謝。

+0

是什麼背後產生兩倍的意圖是什麼?看起來這裏最明顯的解決方案是同時發送兩者。 –

+0

我想要的特點和形象。所以兩個收益率,因爲我不知道如何命令它使得一個收益率給我期望的結果。顯然,這種「直觀的」解決方案失敗了。 – LucSpan

+0

爲什麼不只是產生兩個結果的元組? – alexis

回答

0

只是讓它們都在一起。

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

在接收端,搶都作爲單獨的值

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

謝謝亞歷克斯,但我不確定你的意思是'在接收端'? – LucSpan

+0

無論你在何處捕獲從收益中返回的值。你正在改變你的返回類型爲一個元組。爲了保持您現在具有的相同行爲,請將您今天使用的兩個變量放在等號左邊的相同行中,並用逗號分隔。 –

0

我有兩個主要的建議:

1號

我強烈建議重新工作的代碼實際上在同一時間將所有信息全部用完。而不是有兩個單獨的parse_X函數...只有一個獲取信息並返回單個項目。

2號

實現蜘蛛中間件,它合併相似,我有下面的管道/分裂。一個簡單的示例中間件是https://github.com/scrapy/scrapy/blob/ebef6d7c6dd8922210db8a4a44f48fe27ee0cd16/scrapy/spidermiddlewares/urllength.py。您只需合併項目並在進入itempipelines之前在這裏跟蹤它們。

警告不要做下面的事情。我正在努力提出這個建議,而且這個守則可能會奏效......但有一些潛在的隱藏問題。

它是在這裏爲完整我是研究 - 建議這裏對抗:https://github.com/scrapy/scrapy/issues/1915

使用項目處理管道中scrapy。它們對於積累數據非常有用。有一個項目連接器管道,其目的是等待兩個單獨的部分數據項並將它們連接成一個項目並將它們鍵入到ad id(或其他一些獨特的數據)中。

在粗糙未運行的僞代碼:

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)