我正在使用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>
);
};
答案 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