NameError异常:Wheyscrapper:Class的未定义局部变量或方法“产品”

时间:2019-06-24 14:45:47

标签: ruby

我正在使用Ruby构建一个小型Web抓取工具,现在我正在尝试重构代码。不幸的是,我在重构代码时遇到一些错误。这是错误之一。

基本上,我在第一个方法whey_scrapper中调用两个单独的方法。这两种方法中的每一种基本上都负责在网页上抓取特定项目。当我使用byebug运行和调试此代码时,基本上我会尝试显示我已抓取的产品或价格,但是会收到一条错误消息,指出“产品”或“价格”未定义。这是我当前的代码:

import React, { useState } from 'react';
import { Text, View, Button, StyleSheet } from 'react-native';

export default () => {
  const [count, setCount] = useState(0);

  return (
    <View style={{ flex: 1, justifyContent: 'space-around', alignItems: 'center'}}}>
      <Text>You clicked {count} times</Text>
      <Button onPress={() => setCount(count + 1)} title="Click me" />
    </View>
  );
};

2 个答案:

答案 0 :(得分:1)

这里有很多事情要做,但是要使它变得更Ruby,您可以考虑将这些 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

这可以解决许多原始数据传播问题。当声明一个变量时,它是一个 local 变量,这意味着它不在该特定方法的特定调用之外。如果要持久保留它,则需要像@products中那样使用 instance变量,或者需要定义返回所需数据的方法。

上述方法通过使用延迟初始化的实例变量来合并已解析的文档,并将其公开为其他方法可以使用的方法。

现在您可以旋转它:

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

应该在哪里使所有内容直接可用:

scraper.prices
scraper.products

当您学习如何有效使用Ruby时,您通常会找到对您的问题的解决方案,这些解决方案的确很少。通常,很多Ruby代码都表明没有正确使用它。

答案 1 :(得分:0)

根据我上面的评论,应该以更好的方式进行重构,但这至少应该在没有重构的情况下起作用

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