リンク切れのチェック

作成日 : 2012-11-11
最終更新日 :

head リクエストの活用

http では、リクエストの方法としては get と post がよく知られている。 そのほかに、head というリクエストがあるがこれはあまり知られていない。 head は該当 URL のヘッダのみを取り込むリクエストで、get や post に比べて取得するデータ量が少なくてよい。 その結果、WEB サーバに負担をかけずにすむ。今回はリンクのありなしと更新の有無を見るだけなので、 head リクエストが適切と判断した。

あるリンク切れチェッカー

私が以前書いたリンク切れチェッカーである。解説は後ほど追加する。

require 'net/http'
require 'uri'
require 'time'

timelag = 5 # timelag 秒以内の差であれば、不正確なlast-modifiedとみなす

origin = '1970-01-01T09:00:00+09:00'
hash = Hash.new

ARGF.each {|line|
  if (line =~ /^<tr><td><a href="(.*)".*/)
    url = $1
    uri = URI.parse(url)
    host = uri.host
    path = uri.path
#    print "<tr><td><a href=\"#{url}\">#{url}</a></td>"
    begin
      h = Net::HTTP.new(host, 80)
      resp = h.head2(path, nil)
      lm = resp['last-modified']
      dt = resp['date']
      ct = resp['content-length']
      lm = origin if lm == nil
      if (Time.parse(lm).to_i - Time.parse(dt).to_i).abs < timelag
        lm = origin
      end
#     print "<td>#{(Time.parse(lm)).iso8601}</td><td>#{resp.code}</td></tr>\n"
      # ハッシュの値は配列。
      hash[url] = [Time.parse(lm).to_i, resp.code, ct]
    rescue
      hash[url] = [0, 0, 0]
#    rescue SocketError
#      hash[url] = [0, 0, 0]
#    rescue NameError
#      hash[url] = [0, 1, 0]
    end

  elsif (line =~ /end of links/)
    sorted = hash.sort{|a,b| b[1][0] <=> a[1][0]}  # エポック秒が大きいものから
    sorted.each {|key, value|
       url = key
       print "<tr><td><a href=\"#{url}\">#{url}</a></td>"
       print "<td>#{Time.at(value[0]).iso8601}</td><td>#{value[1]}</td><td>#{value[2]}</td></tr>\n"
    }
    print line
  else
    puts line
  end
}

まりんきょ学問所Rubyの浮き輪 > リンク切れチェッカー


MARUYAMA Satosi