Never been to DZone Snippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

Ruby library for Web site thumbnailer service (See related posts)

Today I found a really cool and flexible Web page thumbnailing service at http://bluga.net/webthumb/ with a nice API.. so I wrote a Ruby library for it. It works well. The service lets you do 250 free requests per month, but over that the price seems very reasonable (compared with the dire alternatives I found).

require 'net/http'
require 'rubygems'
require 'xmlsimple'

class Nailer

  @@api_baseurl = 'http://webthumb.bluga.net/api.php'
  @@api_key = 'PUT YOUR API KEY HERE'
  
  attr_accessor :collection_time, :job_id, :ok

  def initialize(url, width = 1024, height = 768)
    api_request = %Q{<webthumb><apikey>#{@@api_key}</apikey><request><url>#{url}</url><width>#{width}</width><height>#{height}</height></request></webthumb>}

    result = do_request(api_request)

    if result.class == Net::HTTPOK
      result_data = XmlSimple.xml_in(result.body)
      @job_id = result_data['jobs'].first['job'].first['content']
      @collection_time = Time.now.to_i + result_data['jobs'].first['job'].first['estimate'].to_i
      @ok = true
    else
      @ok = false
    end
  end

  def retrieve(size = :small)
    api_request = %Q{<webthumb><apikey>#{@@api_key}</apikey><fetch><job>#{@job_id}</job><size>#{size.to_s}</size></fetch></webthumb>}
    result = do_request(api_request)
    result.body
  end

  def retrieve_to_file(filename, size = :small)
    File.new(filename, 'w+').write(retrieve(size.to_s))
  end

  def ready?
    return unless Time.now.to_i >= @collection_time

    api_request = %Q{<webthumb><apikey>#{@@api_key}</apikey><status><job>#{@job_id}</job></status></webthumb>}
    result = do_request(api_request)

    if result.class == Net::HTTPOK
      @ok = true
      result_data = XmlSimple.xml_in(result.body)
      begin
        @result_url = result_data['jobStatus'].first['status'].first['pickup']
        @completion_time = result_data['jobStatus'].first['status'].first['completionTime']
      rescue
        @collection_time += 60 
	      return false
      end
    else
      @ok = false
    end

    true
  end

  def ok?
    @ok == true
  end

  def wait_until_ready
    sleep 1 until ready?
  end

  private

  def do_request(body)
    api_url = URI.parse(@@api_baseurl)
    request = Net::HTTP::Post.new(api_url.path)
    request.body = body
    Net::HTTP.new(api_url.host, api_url.port).start {|h| h.request(request) }
  end
end
  


url = 'http://www.rubyinside.com/'
t = Nailer.new(url)

if t.ok?
  t.wait_until_ready
  t.retrieve_to_file('out1.jpg', :small)
  t.retrieve_to_file('out2.jpg', :medium)
  t.retrieve_to_file('out3.jpg', :medium2)
  t.retrieve_to_file('out4.jpg', :large)
  puts "Thumbnails saved"
else
  puts "Error"
end

Comments on this post

danwade posts on Mar 18, 2007 at 16:36
Thanks for the snippet. So many of these page-grab libraries just don't cut the mustard, but this one works well. I'm having trouble with your code, though. The images save to disk OK, but when I open them up, each of them has been corrupted and has only random junk in the image file. Ive tried it a few times with different URLs (checking that they work correctly on bluga.net, which they do) and I get the same result. Any ideas?

Thanks
Dan
Bounga posts on Mar 23, 2007 at 05:33
You're maybe using windows.

If you're using it, you should change :
File.new(filename, 'w+').write(retrieve(size.to_s))
to:
File.new(filename, 'wb+').write(retrieve(size.to_s))

in retrieve_to_file method
danwade posts on Mar 23, 2007 at 07:31
Bingo! That worked, thanks :)
ltmon posts on Jul 09, 2007 at 20:42
I found that replacing the file writing code with:

data = retrieve(size.to_s)
File.open(filename, 'wb') do |f|
  f.binmode
  f.write data
end


works somewhat better for me. Otherwise I was getting empty, corrupted and partially corrupted images being written to the file.
tilsammans posts on Jul 25, 2007 at 12:53
This script works great, but ampersands in the url must be replaced.

Put this immediately after the line with `def initialize`:
url = url.gsub(/&/, '&amp;')
thumbnailspro posts on Aug 26, 2007 at 11:35
Check out Thumbnailspro.com, they are FREE while in beta any allow to request thumbnails directly from your website, any size you want up to 1000pixels! WOW! thats Thumbnailspro.com
tresudek posts on Jan 25, 2008 at 15:37
So far, this script is working well. I am experiencing some major performance issues though.
Has anyone else noticed that your server will basically stall until the screenshot(s) have finished running? in my case, I am seeing about 20 seconds / screenshot.

Is this just my server, or is there some way of modifying the script so that it runs more "in the background" while still allowing other processes to run?
peter posts on Jan 27, 2008 at 18:34
That's what wait_until_ready? is doing, tresudek. You don't have to run that. That's just something for this demo so it sits and waits. You can just use ready? instead to check whenever you want.
foxxx posts on Feb 25, 2008 at 02:38
Can you elaborate that wait 1 until ready? statement? please?

when we change it to ready? it still waits for the api to take the shot and add it to the system, would rather it do this in the background...
socmoth posts on Feb 27, 2008 at 18:01
  def retrieve_to_file(filename, size = :small)
    f = File.new(filename, 'w+')
    size = f.write(retrieve(size.to_s))
    f.close
    return size
  end


explicitly close the file or it will miss the last couple bytes sometimes.

You need to create an account or log in to post comments to this site.


Click here to browse all 4858 code snippets

Related Posts