Исключение NameError: неопределенная локальная переменная или метод `products 'для Wheyscrapper: Class - PullRequest
1 голос
/ 24 июня 2019

Я строю небольшой веб-скребок, используя Ruby, и теперь я пытаюсь реорганизовать мой код. К сожалению, я сталкиваюсь с некоторыми ошибками при рефакторинге своего кода. Это одна из ошибок.

По сути, я вызываю два отдельных метода в первом методе, который называется whey_scrapper. Каждый из этих двух методов в основном отвечает за удаление определенного элемента на веб-странице. Когда я запускаю и отлаживаю этот код с помощью byebug, я в основном пытаюсь отобразить продукты или цены, которые я выбрал, но я получаю сообщение об ошибке, в котором говорится, что «продукты» или «цены» не определены. Это мой текущий код:

require 'open-uri'
require 'nokogiri'
require 'httparty'
require 'byebug'
require 'csv'

class Wheyscrapper
    def whey_scrapper
        company = 'Body+%26+fit'
        url = "https://www.bodyenfitshop.nl/afslanken/afslank-toppers/?manufacturer=#{company}"
        unparsed_page = open(url).read
        parsed_page = Nokogiri::HTML(unparsed_page)
        product_scrapper
        prices_scrapper
        # csv = CSV.open('wheyprotein.csv', 'wb')       
    end 


    def product_scrapper
        products = Array.new
        product_names = parsed_page.css('div.product-primary')
        product_names.each do |product_name| 
            product = {
                name: product_name.css('h2.product-name').text
            }
            products << product 
        end
    end

    def prices_scrapper
        prices = Array.new
        product_prices = parsed_page.css('div.price-box')
        product_prices.each do |product_price|
            price = {
                amount: product_price.css('span.price').text
            }
            prices << price
        end
    end
    byebug
    whey_scrapper
end     

Ответы [ 2 ]

1 голос
/ 24 июня 2019

Здесь много чего происходит, но для того, чтобы сделать его более рубиновым, вам стоит подумать о том, чтобы lazy-initialized и дать им имена, отражающие это:

class Wheyscrapper
  URL = "https://www.bodyenfitshop.nl/afslanken/afslank-toppers/?%s"

  def initialize(company:)
    @company = company
    # Use encode_www_form to encode query-string parameters
    @url = URL % URI.encode_www_form(manufacturer: company)
  end

  def document
    # Lazy-initialize a parsd version of the page
    @document ||= Nokogiri::HTML(open(url).read)
  end

  def products
    document.css('div.product-primary').map do |product_name| 
      {
        name: product_name.css('h2.product-name').text
      }
    end
  end

  def prices
    document.css('div.price-box').map do |product_price|
      {
        amount: product_price.css('span.price').text
      }
    end
  end
end

Это исправляетмного проблем с распространением данных, которые у вас были в оригинале.Когда вы объявляете переменную, это локальная переменная, то есть она не существует вне определенного вызова этого конкретного метода.Если вы хотите сохранить его дольше, вам нужно использовать переменные экземпляра , как в @products, или вам нужно определить методы, которые возвращают нужные вам данные.

Приведенный выше подход объединяетчто, используя переменную экземпляра с отложенной инициализацией для сохранения проанализированного документа, и предоставляет этот метод в качестве метода, который могут использовать другие методы.

Теперь вы можете ускорить это:

scraper = WheyScraper.new(company: "Body & Fit")

Гдеэто должно сделать все доступным напрямую:

scraper.prices
scraper.products

Когда вы научитесь эффективно использовать Ruby, вы часто найдете решения ваших проблем, которые действительно минимальны.Обычно большое количество кода Ruby является признаком того, что он не используется должным образом.

0 голосов
/ 24 июня 2019

Это должно быть реорганизовано в лучшую сторону, но это должно по крайней мере работать без рефакторинга, основываясь на моих комментариях выше

require 'open-uri'
require 'nokogiri'
require 'httparty'
require 'csv'

class Wheyscrapper
  def whey_scrapper
    company = 'Body+%26+fit'
    url = "https://www.bodyenfitshop.nl/afslanken/afslank-toppers/?manufacturer=#{company}"
    unparsed_page = open(url).read
    @parsed_page = Nokogiri::HTML(unparsed_page)
    product_scrapper
    prices_scrapper
    # csv = CSV.open('wheyprotein.csv', 'wb')
  end


  def product_scrapper
    @products = Array.new
    product_names = @parsed_page.css('div.product-primary')
    product_names.each do |product_name|
      product = {
        name: product_name.css('h2.product-name').text
      }
      @products << product
    end
  end

  def prices_scrapper
    @prices = Array.new
    @product_prices = @parsed_page.css('div.price-box')
    @product_prices.each do |product_price|
      price = {
        amount: product_price.css('span.price').text
      }
      @prices << price
    end
  end
end

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