Scrapy: как оценить цену продукта, которая состоит из двух частей? - PullRequest
0 голосов
/ 12 марта 2020

У меня есть скребок, который собирает данные с веб-сайта "www.bol.com", единственная проблема, с которой я до сих пор сталкивался, заключается в том, что цена состоит из двух частей (в источнике HTML). Число и дробь числа разделены.

Я попытался очистить как цену, так и дробь цены отдельно. Это работает, однако, не каждый продукт имеет цену с дробью. Таким образом, мой скребок закончил только очисткой всех продуктов с ценами, которые состоят из числа и дроби, а не чисел без дроби. Может быть мне нужно вернуть число «0», когда нет доступной дроби?

HTML Источник для цены с дробью

Цена отображается как: 777 , 86

<span class="promo-price" data-test="price">777
  <sup class="promo-price__fraction" data-test="price-fraction">86</sup>
</span>

Источник: https://www.bol.com/nl/p/apple-iphone-11-64gb-zwart/9200000119815601/?bltgh=j0qmNqgyvLwjCGWgGxxPmA.1_30.31.ProductTitle

HTML Источник цены без дроби

Цена отображается как 739- (мне не нужен символ -)

<span class="promo-price" data-test="price">739
  <sup class="promo-price__fraction  promo-price__fraction--dash" data-test="price-fraction">-</sup>
</span>

Источник: https://www.bol.com/nl/p/apple-iphone-xr-64gb-zwart/9200000098453451/?bltgh=j0qmNqgyvLwjCGWgGxxPmA.1_30.33.ProductTitle

Скребок

import scrapy
from ..items import Mobile

class AmazonScraper(scrapy.Spider):
    name = "bol_scraper"

    # How many pages you want to scrape
    no_of_pages = 1

    # Headers to fix 503 service unavailable error
    # Spoof headers to force servers to think that request coming from browser ;)
    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.2840.71 Safari/539.36'}

    def start_requests(self):
        # starting urls for scraping
        urls = ["https://www.bol.com/nl/l/apple-iphones/N/4010+4294862300/?ruleRedirect=1&sI=iphone&variants="]

        for url in urls: yield scrapy.Request(url = url, callback = self.parse, headers = self.headers)

    def parse(self, response):

        self.no_of_pages -= 1

        # print(response.text)

        mobiles = response.xpath("//a[@class='product-title px_list_page_product_click']").xpath("@href").getall()

        # print(len(mobiles))

        for mobile in mobiles:
            final_url = response.urljoin(mobile)
            yield scrapy.Request(url=final_url, callback = self.parse_mobile, headers = self.headers)
            # break

        if(self.no_of_pages > 0):
            next_page_url = response.xpath("//ul[@class='pagination']/li[@class='[ pagination__controls pagination__controls--next ]']/a").xpath("@href").get()
            final_url = response.urljoin(next_page_url)
            yield scrapy.Request(url = final_url, callback = self.parse, headers = self.headers)

    def parse_mobile(self, response):
        title = response.xpath("//span[@class='h-boxedright--xs']//text()").get() or response.xpath("//h1[@class='page-heading']//text()").get()
        rawprice = '.'.join(response.css('.promo-price ::text').extract())
        cleanprice = rawprice.replace('-','00').replace('\n', '').replace(' ','')
        price = cleanprice[:-1]


        print(title, price, price_fraction)


        yield Mobile(title = title.strip(), price = price.strip(), price_fraction = price_fraction.strip())

Результат до очистки данных

{"title": "Apple iPhone 11 - 64GB - Zwart", "price": "777\n  .86."},
{"title": "Apple iPhone Xs - 64GB - Goud", "price": ""},
{"title": "Apple iPhone 11 Pro Max - 256GB - Spacegrijs", "price": "1319\n  .-."},
{"title": "Apple iPhone 11 Pro Max - 512GB - Goud", "price": "1589\n  .-."},
{"title": "Apple iPhone 11 - 256GB - Zwart", "price": "899\n  .-."},
{"title": "iPhone Xs Max - 64GB - Space Grey", "price": "849\n  .-."},
{"title": "Apple iPhone Xs - 64GB - Zilver", "price": "752\n  .-."},
{"title": "Apple iPhone XR - 128GB -  Zwart", "price": "716\n  .45."},
{"title": "Apple iPhone 11 Pro - 64GB - Middernachtgroen", "price": "1199\n  .-."},
{"title": "Apple iPhone 8 - 64GB - Spacegrijs", "price": "535\n  .12."},
{"title": "Apple iPhone 11 - 128GB - Zwart", "price": "833\n  .-."},
{"title": "Apple iPhone XR - 64GB - Zwart", "price": "739\n  .-."},
{"title": "Apple iPhone Xs - 64GB - Spacegrijs", "price": "745\n  .58."},
{"title": "Apple iPhone 7 - 32GB - Spacegrijs", "price": "378\n  .95."}

Результат после очистки данных

{"title": "Apple iPhone 11 - 64GB - Zwart", "price": "777.86"},
{"title": "Apple iPhone 11 Pro Max - 256GB - Spacegrijs", "price": "1319.00"},
{"title": "Apple iPhone Xs - 64GB - Goud", "price": ""},
{"title": "Apple iPhone Xs - 64GB - Zilver", "price": "752.00"},
{"title": "Apple iPhone 11 Pro Max - 512GB - Goud", "price": "1589.00"},
{"title": "Apple iPhone 11 - 256GB - Zwart", "price": "899.00"},
{"title": "iPhone Xs Max - 64GB - Space Grey", "price": "849.00"},
{"title": "Apple iPhone XR - 128GB -  Zwart", "price": "716.45"},
{"title": "Apple iPhone 8 - 64GB - Spacegrijs", "price": "535.12"},
{"title": "Apple iPhone 11 Pro - 64GB - Middernachtgroen", "price": "1199.00"},
{"title": "Apple iPhone Xs - 64GB - Spacegrijs", "price": "745.58"},
{"title": "Apple iPhone 11 - 128GB - Zwart", "price": "833.00"},
{"title": "Apple iPhone XR - 64GB - Zwart", "price": "739.00"},
{"title": "Apple iPhone 7 - 32GB - Spacegrijs", "price": "378.95"}

Ответы [ 2 ]

2 голосов
/ 12 марта 2020

Я считаю,

price = '.'.join(response.css('.promo-price ::text').extract())

Ваша ошибка в использовании функции .get(), которая выбирает только первый найденный фрагмент текста, в то время как есть два для извлечения.

2 голосов
/ 12 марта 2020

Используя два html семпла в качестве основы, взгляните на это и попробуйте изменить его в свой собственный код:

pricing = """
<prices>
  <unit>
  <span class="promo-price" data-test="price">777
  <sup class="promo-price__fraction" data-test="price-fraction">86</sup>
</span>
  </unit>
  <unit>
    <span class="promo-price" data-test="price">739
  <sup class="promo-price__fraction  promo-price__fraction--dash" data-test="price-fraction">-</sup>
</span>
  </unit>
</prices>

"""

from scrapy.selector import Selector
sel = Selector(text=pricing)
prices = sel.xpath('//span[@class="promo-price"]').extract()
for price in prices:
    sel = Selector(text=price)    
    fract = sel.xpath('.//text()').extract()
    full = sel.xpath('//span/text()').extract()
    price = full[0].strip() + '.' + fract[1].strip().replace('-','00')
    print(price)

Вывод:

777.86
739.00
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...