ruby - 为什么这个 JSON 文件填充了上次哈希数据的 1747 倍?

标签 ruby json hash web-scraping mechanize

我正在使用以下代码生成一个 JSON 文件,其中包含特定网站的所有类别信息。

require 'mechanize'

@hashes = []

@categories_hash = {}
@categories_hash['category'] ||= {}
@categories_hash['category']['id'] ||= {}
@categories_hash['category']['name'] ||= {}
@categories_hash['category']['group'] ||= {}

# Initialize Mechanize object
a = Mechanize.new

# Begin scraping
a.get('http://www.marktplaats.nl/') do |page|
  groups = page.search('//*[(@id = "navigation-categories")]//a')

  groups.each_with_index do |group, index_1|
    a.get(group[:href]) do |page_2|
      categories = page_2.search('//*[(@id = "category-browser")]//a')

      categories.each_with_index do |category, index_2|
        @categories_hash['category']['id'] = "#{index_1}_#{index_2}"
        @categories_hash['category']['name'] = category.text
        @categories_hash['category']['group'] = group.text

        @hashes << @categories_hash['category']

        # Uncomment if you want to see what's being written
        puts @categories_hash['category'].to_json
      end
    end
  end
end

File.open("json/magic/#{Time.now.strftime '%Y%m%d%H%M%S'}_magic_categories.json", 'w') do |f|
  puts '# Writing category data to JSON file'
  f.write(@hashes.to_json)
  puts "|-----------> Done. #{@hashes.length} written."
end

puts '# Finished.'

但此代码返回一个仅填充最后一个类别数据的 JSON 文件。有关完整的 JSON 文件,请查看 here .这是一个示例:
[
   {
      "id":"36_17",
      "name":"Overige Diversen",
      "group":"Diversen"
   },
   {
      "id":"36_17",
      "name":"Overige Diversen",
      "group":"Diversen"
   },
   {
      "id":"36_17",
      "name":"Overige Diversen",
      "group":"Diversen"
   }, {...}
]

问题是,这是什么原因造成的,我该如何解决?

最佳答案

同一个对象,结果@categories_hash['category'] , 每次循环都会更新。

因此,该数组被相同的对象填充了 1747 次,并且该对象在稍后查看时反射(reflect)了在最后一个循环中完成的突变。

虽然修复可能是使用 @categories_hash[category_name]或类似(即每次循环获取/确保不同的对象),以下内容避免了所描述的问题和“类别”键的未使用/误用哈希。

categories.each_with_index do |category, index_2|
    # creates a new Hash object
    item = {
        id: "#{index_1}_#{index_2}",
        name: category.text,
        group: group.text
    }
    # adds the new (per yield) object
    @hashes << item
end

或者,更“实用”的方法可能是使用 map ,但它以同样的方式解决了这个问题——通过创建新的 [Hash] 对象。 (这可以扩展到还包括外循环,但它只是为了尝一尝。)
h = categories.each_with_index.map do |category, index_2|
    {
        id: "#{index_1}_#{index_2}",
        name: category.text,
        group: group.text
    }
end
@hashes.concat(h)

关于ruby - 为什么这个 JSON 文件填充了上次哈希数据的 1747 倍?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24296544/

相关文章:

Ruby:将字符串中的&符号替换为反斜杠与&符号

python - 如何将新的 json 对象插入现有的 json 文件(在对象中间)

perl - 如何使这个嵌套循环在 perl 中继续?

json - 使用 JSONPath 按名称过滤 json 属性

c# - Azure Function 不反序列化对象

python - 类型错误 : a float is required in sklearn. feature_extraction.FeatureHasher

c++ - 如何使用多个排序键对列表进行排序

ruby-on-rails - 超出范围错误,在 rspec 测试期间类型::整数

ruby - 如何将文件从 gem 复制到本地目录

ruby - 基于表达式评估将不同参数传递给方法的 Ruby 方法是什么?