Transitioning from Scrubyt to Nokogiri- Write to XML or Hash?

1.1k Views Asked by At

I'm trying to transition this bit of code from scrubyt to nokogiri, and am stuck trying to write my results to either a hash or xml. In scrubyt it looks like the following:

require 'rubygems'
  require 'scrubyt'

  result_data = Scrubyt::Extractor.define do
    fetch "http://www.amazon.com/gp/offer-listing/0061673730"
    results "//div[@class='resultsset']" do
       item "//tbody/tr" do
          condition "//div[@class = 'Condition']"
          price "//span[@class = 'price']"
          shipping "//span[@class = 'price_shipping']"
       end
   end
  end
  @description = result_data.to_xml
  return @description
end

With nokogiri I can parse out the information I want, but there doesn't seem to be a quick way to return items in a hash or xml document. Here's all I have in nokogiri.

require 'rubygems'
require 'nokogiri'
require 'open-uri'
doc = Nokogiri::HTML(open('http://www.amazon.com/gp/offer-listing/0061673730'))

doc.css('div.condition, span.price, span.price_shipping ').each do |item|
puts item.content
end 

How would one return item information to either xml or a hash?

4

There are 4 best solutions below

0
On BEST ANSWER

You can use the Builder to build XML.

builder = Nokogiri::XML::Builder.new do |xml|
  xml.root {
    xml.items {
      doc.css('div.condition, span.price, span.price_shipping').each do |o|
        xml.item_content = o
      end
    }
  }
end

puts builder.to_xml
0
On

you may want to omit "=" in xml.price = p.content

0
On

Thanks! That's exactly what I need. I'm having trouble looping correctly, though.

require 'rubygems'
require 'nokogiri'
require 'open-uri'
doc = Nokogiri::HTML(open('http://www.amazon.com/gp/offer-listing/0061673730'))
builder = Nokogiri::XML::Builder.new do |xml|
  xml.root {
    xml.item {
      doc.css('span.price').each do |o|
        xml.price = o
      doc.css('span.price_shipping').each do |o|

      end
      end
    }
  }
end

puts builder.to_xml

That returns this:

<?xml version="1.0"?>
<root>
  <item>
    <price=>&lt;span class="price"&gt;$6.09&lt;/span&gt;</price=>
    <price=>&lt;span class="price"&gt;$6.48&lt;/span&gt;</price=>
    <price=>&lt;span class="price"&gt;$11.95&lt;/span&gt;</price=>
    <ship=>&lt;span class="price_shipping"&gt;+ $3.99&lt;/span&gt;</ship=>
    <ship=>&lt;span class="price_shipping"&gt;+ $3.99&lt;/span&gt;</ship=>
    <ship=>&lt;span class="price_shipping"&gt;+ $3.99&lt;/span&gt;</ship=>

  </item>
</root>

How would I rewrite my code to return something like this:

<?xml version="1.0"?>
<root>
  <item>
    <price=>&lt;span class="price"&gt;$6.09&lt;/span&gt;</price=>
    <ship=>&lt;span class="price_shipping"&gt;+ $3.99&lt;/span&gt;</ship=>
  </item>
  <item>
    <price=>&lt;span class="price"&gt;$6.48&lt;/span&gt;</price=>
    <ship=>&lt;span class="price_shipping"&gt;+ $3.99&lt;/span&gt;</ship=>
  </item>
  <item>
    <price=>&lt;span class="price"&gt;$11.95&lt;/span&gt;</price=>
    <ship=>&lt;span class="price_shipping"&gt;+ $3.99&lt;/span&gt;</ship=>
  </item>  
</root>
0
On

Figured it out...

require 'rubygems'
require 'nokogiri'
require 'open-uri'

doc = Nokogiri::HTML(open('http://www.amazon.com/gp/offer-listing/0061673730'))
builder = Nokogiri::XML::Builder.new do |xml|
xml.root {
doc.xpath('//tbody[@class="result"]').each do |res|
    xml.result {
    res.css('span.price').each do |p|
      xml.price = p.content
    end
    res.css('span.price_shipping').each do |s|
      xml.ship = s.content
    end
    }
    end
}
end
puts builder.to_xml

Results:

<?xml version="1.0"?>
<root>
  <result>
    <price=>$6.09</price=>
    <ship=>+ $3.99</ship=>
  </result>
  <result>
    <price=>$6.48</price=>
    <ship=>+ $3.99</ship=>
  </result>
  <result>
    <price=>$7.12</price=>
    <ship=>+ $3.99</ship=>
  </result>
  <result>
    <price=>$7.31</price=>
    <ship=>+ $3.99</ship=>
  </result>
  <result>
    <price=>$7.52</price=>
    <ship=>+ $3.99</ship=>
  </result>
  <result>
    <price=>$7.52</price=>
    <ship=>+ $3.99</ship=>
  </result>
  <result>
    <price=>$11.53</price=>
  </result>
  <result>
    <price=>$7.56</price=>
    <ship=>+ $3.99</ship=>
  </result>
  <result>
    <price=>$7.61</price=>
    <ship=>+ $3.99</ship=>
  </result>
  <result>
    <price=>$7.61</price=>
    <ship=>+ $3.99</ship=>
  </result>
  <result>
    <price=>$7.95</price=>
    <ship=>+ $3.99</ship=>
  </result>
  <result>
    <price=>$7.95</price=>
    <ship=>+ $3.99</ship=>
  </result>
  <result>
    <price=>$8.59</price=>
    <ship=>+ $3.99</ship=>
  </result>
  <result>
    <price=>$8.99</price=>
    <ship=>+ $3.99</ship=>
  </result>
  <result>
    <price=>$10.05</price=>
    <ship=>+ $3.99</ship=>
  </result>
  <result>
    <price=>$10.32</price=>
    <ship=>+ $3.99</ship=>
  </result>
  <result>
    <price=>$10.32</price=>
    <ship=>+ $3.99</ship=>
  </result>
  <result>
    <price=>$10.55</price=>
    <ship=>+ $3.99</ship=>
  </result>
  <result>
    <price=>$10.56</price=>
    <ship=>+ $3.99</ship=>
  </result>
  <result>
    <price=>$11.42</price=>
    <ship=>+ $3.99</ship=>
  </result>
  <result>
    <price=>$11.59</price=>
    <ship=>+ $3.99</ship=>
  </result>
  <result>
    <price=>$11.90</price=>
    <ship=>+ $3.99</ship=>
  </result>
  <result>
    <price=>$11.95</price=>
    <ship=>+ $3.99</ship=>
  </result>
  <result>
    <price=>$12.07</price=>
    <ship=>+ $3.99</ship=>
  </result>
  <result>
    <price=>$12.35</price=>
    <ship=>+ $3.99</ship=>
  </result>
</root>