- 1. 概要
- 2. メイン
- 3. リンク URI を抽出する
- 4. リンク先をチェックする
- 5. # をチェック
- 6. ./ や ../ の編集
- 7. リンク先を取得
- 8. 現時点での実行結果
1. 概要
さて、前項、前々項の結果を踏まえて、1ページ分はおおよそチェックできるようになったので。
いったんここでメモとして残しておきます。
クラス分けが不適切だったり、ネーミングが不適切だったりするのはご愛敬としてお許しください。
2. メイン
メインは最初に作成したものとの変更はありません。
#!/usr/bin/env ruby
require './checkparent'
tree = { ARGV[0] => 'UNKNOWN' }
parent = CheckParent.new(ARGV[0])
parent.do(ARGV[0], tree)
3. リンク URI を抽出する
リンク先 URI を抽出する部分。
これも大きな変更はありません。
#!/usr/bin/env ruby
require './checkchild'
require 'open-uri'
require 'nokogiri'
class CheckParent
def initialize(original)
@check = Check.new(original)
end
def do(uri, tree)
begin
tree.each do | key, value |
if (key == uri)
if (value != 'UNKNOWN')
return;
end
end
end
tree[uri] = 'CHECKING'
originalURI = uri
uri = URI.encode(uri)
uri = URI.parse(uri)
html = open(uri).read
html.sub!(/^<!DOCTYPE html(.*)$/, '<!DOCTYPE html>')
doc = Nokogiri::HTML(html)
link = {}
doc.css('a').each do | anchor |
link[anchor[:href]] = nil
end
doc.css('input').each do | anchor |
if s = anchor[:onclick]
s = s[/\'.*\'/]
link[s.delete!("'")] = nil
end
end
doc.css('img').each do | anchor |
link[anchor[:src]] = nil
end
link = Hash[link.sort]
@check.do(originalURI, doc, link, tree)
rescue => error
puts "例外発生"
puts "#{error.backtrace}"
puts "[#{self.class.name}][#{error.message}]"
exit 1
end
end
end
4. リンク先をチェックする
リンク先をチェックする部分。
#!/usr/bin/env ruby
require 'open-uri'
require 'nokogiri'
require('./assemble')
require('./searchName')
require('./fetch')
class Check
def initialize(original)
protocol, userinfo, domain, other = URI.split(ARGV[0])
@top = "#{protocol}" + "://" + "#{domain}"
end
def do(parent, doc, child, tree)
# parent の URI の末尾を加工してインデックスまでを求める
@index = parent
split = parent.split('/')
last = split.last
if (last.include?('.'))
@index = parent[0,parent.length-last.length]
end
puts("インデックス = [#{@index}]")
##parent-placeholder-5e839161318976cf447add72765c4332## = parent
search = SearchName.new
assemble = Assemble.new
fetch = Fetch.new
child.each_key do | key |
full = key
kind = " "
res = '未チェック'
case key[0]
when '#'
kind = "ページ内リンク "
res = search.do(doc, key) # ページ内リンクなので html 内に id=key が存在すること
when 'h'
kind = "外部 リンク "
res, full = fetch.do(##parent-placeholder-5e839161318976cf447add72765c4332##, @top, key) # 外部リンクなので存在の有無のみ
when '.'
kind = "内部 . リンク "
# 内部リンクなのでたどりたい
res, full = fetch.do(##parent-placeholder-5e839161318976cf447add72765c4332##, @top, assemble.do(@index, key))
else
if (key[-3, 3] == 'png')
kind = "イメージファイル "
res, full = fetch.do(##parent-placeholder-5e839161318976cf447add72765c4332##, @top, key) # イメージなので存在の有無のみ
elsif key[-4, 4] == 'html' || key[-1, 1] == '/'
kind = "内部 リンク "
res, full = fetch.do(##parent-placeholder-5e839161318976cf447add72765c4332##, @top, key) # 内部リンクなのでたどりたい
else
kind = "その他のもの " # 上記以外なのでチェックしない
end
end
child[key] = { :リンク元 => ##parent-placeholder-5e839161318976cf447add72765c4332##, :種別 => kind, :リンク => key, :結果 => res, :URI => full }
end
child.each_value do | value |
puts("#{value[:種別]} → #{value[:リンク]} → #{value[:結果]} ")
end
rescue => error
puts "例外発生[#{error.class}]"
puts "#{error.backtrace}"
puts "[#{self.class.name}][#{error.message}]"
exit 1
end
end
19~26 行で現在チェック中の URL のインデックス部分を求めています。
これは、インデックス部分と「./」「.//」「#」を組み合わせて、リンク先の URI の文字列を組み立てるためのものです。
36~73 行でリンクを分類して分けたものごとにチェックを行っています。
75~77 行で結果を出力しています。
5. # をチェック
# で始まるリンク先は、ドキュメント内に「id=リンク先」の記述があれば OK とします。
#!/usr/bin/env ruby
#
# # で始まる要素はページ内の特定の場所へのリンク
# 本サイトでは <hx> タグ内に id="" の形式で記述してあるので
# ドキュメント内での記述をさがす
#
class SearchName
def initialize()
end
# 引数としてドキュメント自身が必要
def do(doc, id)
begin
# とりあえず h4 のみ探す
doc.css('h4').each do | anchor |
if ("#" + anchor[:id] == id)
return 'OK'
# 検出したら 'OK' を返す
end
end
rescue => error
puts "例外発生[#{error.class}]"
puts "#{error.backtrace}"
puts "[#{self.class.name}][#{error.message}]"
exit 1
end
return 'NG'
end
end
6. ./ や ../ の編集
「./」や「../」で始まるリンク先は、リンク元のドキュメントのルートやその上と組み合わせて、URI を再構築します。
#!/usr/bin/env ruby
class Assemble
def initialize()
end
#
# ./ や ../ で始まる URI を組み立て直す
#
def do(index, original)
uri = original;
begin
if (original[0, 2] == '..') # ../ インデックスのひとつ上に / 以降を加える
split = index.split('/')
uri = index[0, index.length-split.last.length+1] + original[2,original.length-2]
else # ./ インデックスに / 以降を加える
uri = index + original[2,original.length-2]
end
rescue => error
puts "例外発生[#{error.class}]"
puts "#{error.backtrace}"
puts "[#{self.class.name}][#{error.message}]"
exit 1
end
return uri
end
end
7. リンク先を取得
ドキュメント内の記述でないリンク先は取得してみます。
#!/usr/bin/env ruby
class Fetch
def initialize()
end
#
# 外部リンク・ドメイン内リンク・イメージファイルは open してみる
#
def do(top, parent, check)
begin
sharp = 0
case check[0]
when ('#') # # で始まっているものはページ内リンクなので親に配下をつける
sharp = 1
check = parent + check # ↑どうもこれでも例外が発生する
when ('/') # / で始まっているものはドメイン内リンクなのでドメインをつける
check = top + check
when ('.')
# ./ や ../ は組み立て直す
end
if (sharp) # # があるものを encode、parse すると落ちる!
uri = check
else
uri = URI.encode(check)
uri = URI.parse(uri)
end
open(uri)
rescue OpenURI::HTTPError => error
return 'NG', check
rescue => error
puts "例外発生[#{error.class}]"
puts "#{error.backtrace}"
puts "[#{self.class.name}][#{error.message}]"
exit 1
end
return 'OK', check
end
end
8. 現時点での実行結果
> ./ソースファイル名.rb http://freebsd.sing.ne.jp/windows/01/99.html
インデックス = [http://freebsd.sing.ne.jp/windows/01/]
ページ内リンク → #1 → OK
ページ内リンク → #2 → OK
ページ内リンク → #3 → NG
内部 . リンク → ../ → OK
内部 . リンク → ../02/01.html → OK
内部 . リンク → ../02/88.html → NG
内部 . リンク → ../88/ → NG
内部 . リンク → ./02/ → OK
内部 . リンク → ./03.html → OK
イメージファイル → /img/FreeBSD/adv/small01.png → NG
イメージファイル → /img/FreeBSD/adv/small03.png → NG
イメージファイル → /img/FreeBSD/windows/01/01/01.png → NG
イメージファイル → /img/FreeBSD/windows/01/01/0X.png → NG
イメージファイル → /img/adv/google01.png → NG
その他のもの → /php/count.php?df=freebsd&sh=F → 未チェック
内部 リンク → /tool/ → NG
内部 リンク → /toor/ → NG
外部 リンク → http://net-3.blogspot.jp/2013/03/blog-post_16.html → OK
外部 リンク → http://net-3.blogspot.jp/2013/03/blog-post_99.html → NG
|