2014-06-18 60 views
0

我正在從網站上刮取以下數據的網絡抓取工具。如何將數據保存到多維Ruby哈希,然後將哈希轉換爲單個JSON文件?

  • 集團
  • 類別
  • 搜索屬性

我用下面的代碼保存數據爲三個獨立的(一維)JSON文件:

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 
... 

但不斷收到語法錯誤。

任何幫助,將不勝感激。

更新

馬克斯建議我嘗試Hash#[]但這返回一個哈希與單一類別(最後一個)。

search_attributes.each_with_index do |attribute, index| 
    @categories_hash[:category][:name] = category.text 
    @categories_hash[:category][:group] = group.text 
    @categories_hash[:category][:search_attributes][:"#{index}"] = attribute.text unless attribute.text == "Outlet " 
end 

我已粘貼完整密碼here

+0

我不認爲你瞭解混編工作。哈希中的每個密鑰必須是唯一的。 ':category'是一個Symbol,所以你每次都覆蓋最後一個值。根據你最初的嘗試,它看起來並不像你對Ruby的語法有很強的把握。 – Max

+0

因此我問的問題。我需要幫助。這是SO的目的。 – narzero

+0

我明白,但它看起來太寬泛了。我不清楚你的誤解在哪裏,所以我想不出一個解決它的單一答案。任何體面的Ruby教程都應該涵蓋這些基礎知識。 – Max

回答

0

的幫助從hereherehere我有充分的工作代碼:

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.' 
0

您是否有特殊原因使用Hash#store?這種方法沒有簡單的方法。我認爲使用Hash#[]更好。

@categories_hash[:category] ||= {} 
@categories_hash[:category][:search_attributes] ||= {} 
@categories_hash[:category][:search_attributes][:1] = attribute.text 

||=確保您嘗試存儲東西在它之前的蘇巴被初始化。

+0

沒有特別的理由。我只是在嘗試一些東西,但它不起作用。 是否有可能通過'Hash#[]'或Ruby Hashes方法來執行'Array#push'方法? – narzero

+0

我不確定你的意思。在Ruby 1.9及以上版本中,鍵總是按照它們添加的順序枚舉,所以'[]'足以將一個鍵添加到Hash的「結尾」。 – Max

+0

我已更新原始問題。使用散列#[]不會將新的鍵值對追加到散列的末尾。代碼運行後,'@ categories_hash'只包含最後一個。有任何想法嗎? – narzero

相關問題