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の浮き輪 > リンク切れチェッカー