「Rubyで特定URLの画像パス一覧を表示する」をちゃんとしてみました

Rubyでどう書く?:Rubyで特定URLの画像パス一覧を表示する - builder by ZDNet Japan」という記事を読みました。「どう書く?」と問うているだけに、はてなブックマークの方にezookojoさんがそのものずばりなものを回答されておりますが、どう書くかはともかく、まずはもう少し基本的なところをちゃんとした方が良いのではないでしょうか。

  • rescue して case というのはあまりに無駄過ぎではないかと思います
  • map を使いましょう
  • 正規表現、見た目の綺麗さに問題があるのはともかくとして、内容が駄目ではないでしょうか。例えば
<img src="1.jpg" /><img src="2.jpg" />

のような場合、うまくscan出来ないと思います。

というわけで、以下のようにちゃんとしてみました。

require 'open-uri'
require 'timeout'

module ImageUrl
  RE = /img[^>]+src=[\"|\']?(#{URI::REGEXP::PATTERN::URIC}*)/i

  def self.get_image_urls(url)
    timeout(1) do
      URI(url).read.scan(RE).map{|img|
        URI.join(url, img[0]).to_s
      }.select{|path|
        [".jpg", ".jpeg", ".png", ".gif", ".bmp"].include? File.extname(path)
      }.uniq
    end
  rescue TimeoutError
    puts "読み込みに時間がかかりすぎたため、処理を終了しました。"
  rescue OpenURI::HTTPError
    puts "ページが見つかりません。"
  rescue URI::InvalidURIError
    puts "URLが不正です。"
  rescue OpenSSL::SSL::SSLError
    puts "危険がいっぱい!"
  rescue => e
    puts "#{e} (#{e.class})"
  end
end

puts ImageUrl.get_image_urls(ARGV[0])

あと、

URIスキームがhttpの場合のみ画像を抽出したいので、判定文を加えました。open-uriSSLで自己証明証を使用しているURLにはアクセスできないため、残念ながらhttpsは該当URIスキームからは外しました。

というのは、残念ではなくて、接続先が確認できない以上アクセスしなくて良いのだと思います。だからそういう判定文を入れるのではなく、そのまま例外処理しちゃえばいいのだと思います。