2017-07-02 61 views
1

我刮的網站有多個產品具有相同的ID但價格不同。我想只保留最低的價格版本。我該如何保留Scrapy的最低價格產品?

from scrapy.exceptions import DropItem 

class DuplicatesPipeline(object): 

    def __init__(self): 
     self.ids_seen = dict() 

    def process_item(self, item, spider): 
     if item['ID'] in self.ids_seen: 
      if item['sale_price']>self.ids_seen[item['ID']]: 
       raise DropItem("Duplicate item found: %s" % item) 
     else: 
      self.ids_seen.add(item['ID']) 
      return item 

所以這個代碼應該下降是一個更高的價格比之前看到的項目,但我無法弄清楚如何在價格較低更新先前刮項目。

# -*- coding: utf-8 -*- 
import scrapy 
import urlparse 
import re 

class ExampleSpider(scrapy.Spider): 
    name = 'name' 
    allowed_domains = ['domain1','domain2'] 
    start_urls = ['url1','url2'] 

    def parse(self, response): 
     for href in response.css('div.catalog__main__content .c-product-card__name::attr("href")').extract(): 
      url = urlparse.urljoin(response.url, href) 
      yield scrapy.Request(url=url, callback=self.parse_product) 

    # follow pagination links 
     href = response.css('.c-paging__next-link::attr("href")').extract_first() 
     if href is not None: 
      url = urlparse.urljoin(response.url, href) 
      yield scrapy.Request(url=url, callback=self.parse) 
    def parse_product(self, response): 
     # process the response here (omitted because it's long and doesn't add anything) 
     yield { 
      'product-name': name, 
      'price-sale': price_sale, 
      'price-regular': price_regular[:-1], 
      'raw-sku': raw_sku, 
      'sku': sku.replace('_','/'), 
      'img': response.xpath('//img[@class="itm-img"]/@src').extract()[-1], 
      'description': response.xpath('//div[@class="product-description__block"]/text()').extract_first(), 
      'url' : response.url, 
     } 
+0

什麼是你刮的網站?什麼是蜘蛛的代碼? – Umair

+0

@Umair我不能告訴你網站,但我已經包含了蜘蛛代碼。不確定它適用於這個問題,但在這裏。 –

回答

0

在開始之前,您是否知道產品ID?如果是這樣,那麼正常的網站行爲將允許您搜索價格低>高,因此您可以刮掉每個產品ID返回的第一個項目,這將避免任何管道處理的需要。

如果您不這樣做,那麼您可以執行兩個步驟,首先搜索所有產品以獲取Id,然後針對每個Id執行上述過程。

+0

我不知道身份證,但從價格低至高的頁面開始是一個好主意!謝謝 –

1

你不能用流水線做這件事,因爲它正在進行中。換句話說,它會返回物品,而不用等待蜘蛛完成。

不過,如果你有一個數據庫,你可以解決這個問題:

在semy僞代碼:

class DbPipeline(object): 

    def __init__(self): 
     self.connection = # connect to your database 

    def process_item(self, item, spider): 
     db_item = self.connection.get(item['ID']) 
     if item['price'] < db_item['price']: 
      self.connection.remove(item['ID']) 
      self.connection.add(item) 
     return item 

你仍然得到scrapy輸出未經過濾的結果,但你的數據庫會訂購。
個人建議將使用基於文檔的數據庫,鍵值數據庫,如redis

+0

是否沒有選擇通過自定義項目導出器完成此操作?我想在scrapinghub上運行它,並且我已經設置了一個系統來使用它們的API。 –

+0

@TahaAttari您可能可以,但這意味着將所有數據保存在緩衝區中,然後將其寫入文件中,這是一個壞主意,除非爬網非常小。 – Granitosaurus

相關問題