如何将数据保存到多维Ruby哈希,然后将哈希转换为单个JSON文件?
我正在开发一个网络刮板,它可以从网站上刮取以下数据如何将数据保存到多维Ruby哈希,然后将哈希转换为单个JSON文件?,ruby,hash,web-scraping,nokogiri,mechanize,Ruby,Hash,Web Scraping,Nokogiri,Mechanize,我正在开发一个网络刮板,它可以从网站上刮取以下数据 团体 类别 搜索属性 我使用以下代码将数据保存到三个单独的(一维)JSON文件中: require 'mechanize' @raw_groups_array = [] @raw_categories_array = [] @search_attributes = [] @groups_clean = [] @categories_clean = [] @categories_combined = [] @categories_ha
- 团体
- 类别
- 搜索属性
require 'mechanize'
@raw_groups_array = []
@raw_categories_array = []
@search_attributes = []
@groups_clean = []
@categories_clean = []
@categories_combined = []
@categories_hash = {}
# Initialize Mechanize object
a = Mechanize.new
# Begin magic
a.get('http://www.marktplaats.nl/') do |page|
groups = page.search('//*[(@id = "navigation-categories")]//a')
groups.each do |group|
@raw_groups_array.push(group)
@groups_clean.push(group.text)
a.get(group[:href]) do |page_2|
categories = page_2.search('//*[(@id = "category-browser")]//a')
categories.each do |category|
@raw_categories_array.push(category)
@categories_clean.push(category.text)
@categories_combined.push("#{group.text} | #{category.text}")
a.get(category[:href]) do |page_3|
search_attributes = page_3.search('//*[contains(concat( " ", @class, " " ), concat( " ", "heading", " " ))]')
search_attributes.each do |attribute|
@search_attributes.push("#{group.text} | #{category.text} | #{attribute.text}") unless attribute.text == 'Outlet '
# Uncomment the line below if you want to see what's going on.
# (it has minimal effect on performance)
puts "#{group.text} | #{category.text} | #{attribute.text}" unless attribute.text == 'Outlet '
end
end
end
end
end
end
# Write json files
File.open('json/prestige/prestige_groups.json', 'w') do |f|
puts '# Writing groups'
f.write(@groups_clean.to_json)
puts '|-----------> Done.'
end
File.open('json/prestige/prestige_categories.json', 'w') do |f|
puts '# Writing categories'
f.write(@categories_clean.to_json)
puts '|-----------> Done.'
end
File.open('json/prestige/prestige_combined.json', 'w') do |f|
puts '# Writing combined'
f.write(@categories_combined.to_json)
puts '|-----------> Done.'
end
File.open('json/prestige/prestige_search_attributes.json', 'w') do |f|
puts '# Writing search attributes'
f.write(@search_attributes.to_json)
puts '|-----------> Done.'
end
puts '# Finished.'
代码是有效的。但我很难重构它以创建以下格式的ruby哈希:
{
"category"=>{
"name"=>"#{category}",
"group"=>"#{group}",
"search_attributes"=>{
"1"=>"#{search_attributes[0]}",
"2"=>"#{search_attributes[1]}",
"."=>"#{search_attributes[.]}",
"i"=>"#{search_attributes[i]}", # depending on search_attributes.length
}
}
}
我试过这样的方法:
...
search_attributes.each do |attribute|
@categories_hash.store([:category][:name], category.text)
@categories_hash.store([:category][:group], group.text)
@categories_hash.store([:category][:search_attributes][:1], attribute.text)
end
...
但是不断地出现语法错误
任何帮助都将不胜感激
更新
Max建议我尝试Hash#[]
,但这将返回一个包含单个类别(最后一个)的哈希
我已经粘贴了完整的代码。您使用
Hash#store
有什么特别的原因吗?用那种方法是不容易的
我认为使用Hash#[]
要好得多
@categories_hash[:category] ||= {}
@categories_hash[:category][:search_attributes] ||= {}
@categories_hash[:category][:search_attributes][:1] = attribute.text
| |=
确保在您尝试在其中存储内容之前已初始化子烟灰。在的帮助下,我有完整的工作代码:
require 'mechanize'
@hashes = []
# 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|
a.get(category[:href]) do |page_3|
search_attributes = page_3.search('//*[contains(concat( " ", @class, " " ), concat( " ", "heading", " " ))]')
attributes_hash = {}
search_attributes.each_with_index do |attribute, index_3|
attributes_hash[index_3.to_s] = "#{attribute.text unless attribute.text == 'Outlet '}"
end
item = {
id: "#{index_1}.#{index_2}",
name: category.text,
group: group.text,
:search_attributes => attributes_hash
}
@hashes << item
# Uncomment this if you want to see what's being pushed
puts item
end
end
end
end
end
# Open file and begin
File.open("json/light/#{Time.now.strftime '%Y%m%d%H%M%S'}_light_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.'
要求“机械化”
@散列=[]
#初始化机械化对象
a=机械化
#开始刮
a、 得到('http://www.marktplaats.nl/"做|页|
groups=page.search('//*[(@id=“导航类别”)]///a')
组。每个带有|索引的|组,索引| 1|
a、 获取(组[:href])执行|第2页|
categories=page_2.搜索('//*[(@id=“category browser”)]///a')
类别。每个_都有_索引do |类别,索引_2|
a、 获取(类别[:href])执行|第3页|
search_attributes=page_3.search('/*[包含(concat(“,@class,”)和concat(“,”heading“,”)])
属性_hash={}
搜索属性。每个属性都有索引do,索引3|
attributes_hash[index_3.to_s]=“#{attribute.text,除非attribute.text=='Outlet'}”
结束
项目={
id:“#{index_1}.#{index_2}”,
名称:category.text,
group:group.text,
:search\u attributes=>attributes\u hash
}
@没有特别的原因。我只是尝试了几件事,但没用。是否可以使用Hash[]
或Ruby哈希来执行类似于Array#push
的方法?我不确定你的意思。在Ruby 1.9及更高版本中,密钥总是按照添加的顺序进行枚举,因此,[]
再次足以将密钥添加到哈希的“末尾”。我已经更新了原始问题。使用哈希#[]不会将新的键值对附加到哈希的末尾。代码运行后,@categories\u hash
只包含最后一个。有什么想法吗?我想你不明白散列是怎么工作的。散列中的每个键都必须是唯一的<代码>:类别
是一个符号,因此每次都会覆盖上一个值。基于您最初的尝试,您似乎对Ruby的语法没有很强的掌握,因此我要问这个问题。我需要帮助。这就是所谓的。我理解,但实际上它似乎太宽泛了。我不清楚你的误解在哪里,所以我想不出一个单一的答案来解决它。任何像样的Ruby教程都应该包含这样的基础知识。我认为我不应该使用符号,因为它们必须是独一无二的。我想迭代所有可用的类别,并将它们添加到哈希中。我看到您有一个变量category
。用category.text
代替:category
,怎么样?
require 'mechanize'
@hashes = []
# 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|
a.get(category[:href]) do |page_3|
search_attributes = page_3.search('//*[contains(concat( " ", @class, " " ), concat( " ", "heading", " " ))]')
attributes_hash = {}
search_attributes.each_with_index do |attribute, index_3|
attributes_hash[index_3.to_s] = "#{attribute.text unless attribute.text == 'Outlet '}"
end
item = {
id: "#{index_1}.#{index_2}",
name: category.text,
group: group.text,
:search_attributes => attributes_hash
}
@hashes << item
# Uncomment this if you want to see what's being pushed
puts item
end
end
end
end
end
# Open file and begin
File.open("json/light/#{Time.now.strftime '%Y%m%d%H%M%S'}_light_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.'