I’m trying to run this ruby script from a magazine, so there are no typoes,
etc. Here’s the error I get…
D:>ruby test.rb
test.rb:29:in get_rank_for': Couldn't find sales rank in page (RuntimeError) from test.rb:61:in
value’
from test.rb:61
from test.rb:61:in `collect’
from test.rb:61
···
and here’s the code
#!/usr/bin/eval ruby -w
require 'net/http’
require ‘uri’
URLS = [
[“www.amazon.com”, “/exec/obidos/ASIN/020161622X/o” ],
[“www.amazon.com”, “/exec/obidos/ASIN/0201710897” ],
[“www.amazon.co.jp”, “/exec/obidos/ASIN/0201710897” ],
[“www.amazon.co.jp”, “/exec/obidos/ASIN/4894714531” ],
[“www.amazon.co.jp”, “/exec/obidos/ASIN/4894712741” ]
]
Use HTTP to fetch the page. Most of the code is redirect handling
def get_rank_for(host, path, port=80)
loop do
http = Net::HTTP.new(host, port)
resp = http.get2(path)
case resp.code
when "200"
data = resp.body
return $1 if data =~ /Sales Rank:.*?\n?([0-9,]+)/
return $1 if data =~ /Amazon.co.jp.*?:.*?\n([0-9,]+)/
raise "Couldn't find sales rank in page"
when "301", "302", "303" # retry
uri = URI.parse(resp['location'])
host = uri.host if uri.host
port = uri.port if uri.port
new_path = uri.path if uri.path
if new_path[0,1] == '/'
path = new_path
else
path = File.join(File.dirname(path), path)
end
http.finish if http.active?
else
raise "Error #{resp.code} from #{host}#{path}"
end
end
end
Fire off a thread for each request
threads = URLS.collect do |url|
Thread.new(*url) do |*a_url|
get_rank_for(*url)
end
end
Collect the results as the threads finish
ranks = threads.collect {|t| t.value }
print Time.now.strftime("%Y/%m/%d %H:%M “)
ranks.each {|r| printf(”%7s", r) }
puts