4. ruby - リンクチェック - checkparent.rb ドキュメントからリンク先を抽出

 
4.1 ドキュメントからリンク先を抽出

4.1 ドキュメントからリンク先を抽出

 上から渡された、URI のドキュメントを読みこんでリンク先を抽出してチェックするクラスへ渡します。  ここが再帰呼び出しの起点になります。
=begin

指定の URI を取得して、ドキュメント内のリンク先を抽出する

=end

require('pry')
require('checkchild')
require('exceptlog.rb')
require('open-uri')
require('nokogiri')

class CheckParent
  def initialize(original)
    @check = Check.new(original)
  end

  def execute(uri, tree, checked)
    begin

      tree.each do | key, value |
        if (key == uri)
          if (value != 'UNKNOWN')
            return;
          end
        end
      end

      tree[uri] = 'CHECKING'

      originalURI = uri

      now = Time::now()
      nowtime = sprintf("%02d",now.hour)+":"+sprintf("%02d",now.min)+":"+sprintf("%02d",now.sec)
      print("#{nowtime} #{originalURI} ")

      uri = URI.encode(uri)
      uri = URI.parse(uri)

      print(".")

      html = open(uri).read
      html.sub!(/^<!DOCTYPE html(.*)$/, '<!DOCTYPE html>')
      doc  = Nokogiri::HTML(html)

      link = {}

      doc.css('a').each do | tag |            # <a href="URI"> の URI の部分を取得
        link[tag[:href]] = nil
      end

      doc.css('input').each do | tag |        # <input onclick="location.href='URI'"> の URI の部分を取得
        if (!tag.kind_of?(Hash))
          next                                # Hash でないとき以下を処理すると落ちるよ
        end
        if tag.has_key?(:onclick)
          if s = tag[:onclick]
            s = s[/\'.*\'/]
            link[s.delete!("'")] = nil
          end
        end
      end

      doc.css('img').each do | tag |          # <img src="URI"> の URI の部分を取得
        link[tag[:src]] = nil
      end

      # 何故か nil をキーに持つものが発生することがある
      # nil をキーに持つものがあると sort 時に例外が発生するので delete する
      # nil をキーに持つものがなぜできるかは別途調査が必要かも・・・

      link.delete(nil)

      link = Hash[link.sort]

      @check.execute(originalURI, doc, link, tree, checked)

    rescue OpenURI::HTTPError => error
      #binding.pry
      puts("  #{uri} ")
      puts("例外発生[#{error.class}]")
      #$result[uri] = { :リンク元 => parent, :種別 => '不明', :リンク => uri, :結果 => 'unknown' }
      return 'unknown'

    rescue SocketError => error
      puts("  #{uri} ")
      puts("例外発生[#{error.class}]")
    rescue Errno::ECONNRESET => error
      puts("  #{uri} ")
      puts("例外発生[#{error.class}]")
    rescue Errno::ECONNREFUSED => error
      puts("  #{uri} ")
      puts("例外発生[#{error.class}]")
    rescue => error
      exeptlog = ExceptLog.new
      binding.pry
      exeptlog.execute(self, error)
      exit 1
    end
  end
end