URL からページのタイトルを引いてくるスクリプト

ちょっと必要になって書いてみた。

  • リダイレクトを追うようにしている
  • 例外の処理の仕方がまだまだ汚い
fetch_title.rb
require 'net/http'
require 'net/https'
require 'uri'
require 'nkf'
Net::HTTP.version_1_2

USER_AGENT = 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; ja-JP-mac; rv:1.9.0.5) Gecko/2008120121 Firefox/3.0.5'
TIMEOUT = 5

def main
  DATA.readlines.each do |url|
    url = str2url(url.chomp)

    printf("%-40s", "#{url}:")

    begin
      title = fetch_title(url)
      puts NKF.nkf('-w', title)
    rescue TimeoutError
      puts 'Time out'
    rescue Exception => e
      puts "Cannot fetch: #{e}"
    end

    sleep 1
  end
end

def fetch_title(url, redirect_limit = 5)
  raise ArgumentError, 'http redirect too deep' if redirect_limit.zero?

  res = fetch(url)

  case res
  when Net::HTTPSuccess
    match = res.body.match(/<title.*?>(.+)<\/title>/i)

    if match
      match[1]
    else
      raise "Title is undeclared"
    end
  when Net::HTTPRedirection
    fetch_title(res['location'], redirect_limit - 1)
  else
    raise "<#{res.code} #{res.message}>"
  end
end

def fetch(url, options = {})
  uri = URI.parse(url)

  http = Net::HTTP.new(uri.host, uri.port)
  http.open_timeout = TIMEOUT
  http.read_timeout = TIMEOUT

  if uri.port == 443
    http.use_ssl = true
    http.verify_mode = OpenSSL::SSL::VERIFY_NONE
  end

  request = Net::HTTP::Get.new(uri.request_uri)
  request['User-Agent'] = USER_AGENT

  http.start
  response = http.request(request)
  http.finish

  response
end

def str2url(str)
  return str if URI.regexp =~ str

  "http://#{str}/"
end

main

__END__
http://google.co.jp
d.hatena.ne.jp
mixi.jp
実行結果
$ ruby fetch_title.rb
http://google.co.jp:                    Google
http://d.hatena.ne.jp/:                 はてなダイアリー - 無料で容量無制限、広告が出ないはてなのブログ(blog)
http://mixi.jp/:                        ソーシャル・ネットワーキング サービス [mixi(ミクシィ)]