4.4 ruby - ウェブスクレイピング - nokogiri リンクを取得

 
4.4.1 概要
4.4.2 <a href=""> を取得
4.4.3 <input onclick=""> を取得
4.4.4 イメージのリンクを取得
4.4.5 まとめて配列にぶち込む
4.4.6 分類する

4.4.1 概要

 実はこのあたりが最終目標へ向かう方法なのだ。  本項は以下のサイトを参考にさせていただきました。
[Ruby] Nokogiri を使って、ページ内全ての a タグの href 属性の値を取得する」
「nokogiri をつかってリンクを取得

4.4.2 <a href=""> を取得

 参考サイトに習って <a href=""> 内のリンク先を取得して表示してみます。

#!/usr/bin/env ruby

require 'open-uri'
require 'nokogiri'

url = ARGV[0]

html = open(url).read

html.sub!(/^<!DOCTYPE html(.*)$/, '<!DOCTYPE html>')

doc  = Nokogiri::HTML(html)

doc.css('a').each do |anchor|
    puts anchor[:href]
end
 実行してみます。

> ./ソースファイル名.rb http://freebsd.sing.ne.jp/lang/ruby/04/02.html
#4.2.1
#4.2.2
#4.2.3
http://keruuweb.com/ruby-openuri%E3%81%AE%E4%BD%BF%E3%81%84%E6%96%B9/
https://qiita.com/Linus_MK/items/94280dc000726f740c3c
http://mofuken.blogspot.jp/2012/12/ruby-open-uri-https-certificate-verify.html
https://gist.github.com/toshiharu/5539841
https://qiita.com/whiteleaf7@github/items/4504b208ad2eec1f9357
 をを、出てくる出てくる。

4.4.3 <input onclick=""> を取得

 本サイトの場合

<input type="submit" class="page" value="前 へ" onclick="location.href='./01.html'">
<input type="submit" class="page" value="戻 る" onclick="location.href='./'">
<input type="submit" class="page" value="次 へ" onclick="location.href='./03.html'">
 という書き方でページ送りをしているので「<input onclick="">」の「location.href=''」の中身もリンク先として取得したいのです。  さすがにここらで少しは頭を使わないとね。  前項の14行以降を書き換えるとして

doc.css('input').each do |anchor|	#	input の中身を取り出し
    s = anchor[:onclick]			#	onclick の中身を取り出し
    s = s[/\'.*\'/]					#	' で囲まれた部分を取り出し
    s.delete!("'")					#	' を削除
    puts s
end
 同様に実行してみると

> ./ソースファイル名.rb http://freebsd.sing.ne.jp/lang/ruby/04/02.html
./01.html
./
./03.html
 もっとスマートな書き方があるはずであるが先を急ぐのでここはよしとする。  ちょっと訂正、別のページでやったときに

> ./ソースファイル名.rb http://freebsd.sing.ne.jp/windows/01/01.html
./test08.rb:21:in `block in <main>': undefined method `[]' for nil:NilClass (NoMethodError)
        from /usr/local/lib/ruby/gems/2.4/gems/nokogiri-1.8.2/lib/nokogiri/xml/node_set.rb:190:in `block in each'
        from /usr/local/lib/ruby/gems/2.4/gems/nokogiri-1.8.2/lib/nokogiri/xml/node_set.rb:189:in `upto'
        from /usr/local/lib/ruby/gems/2.4/gems/nokogiri-1.8.2/lib/nokogiri/xml/node_set.rb:189:in `each'
        from ./test08.rb:19:in `<main>'
 こけちゃった。  これは「<input>」内で onclick がないものがあるので、そこでこけている。  onclick がある場合のみ処理を行います。

doc.css('input').each do |anchor|	#	input の中身を取り出し
    if s = anchor[:onclick]			#	onclick の中身を取り出し
    	s = s[/\'.*\'/]				#	' で囲まれた部分を取り出し
    	s.delete!("'")				#	' を削除
    	puts s
    end
end

4.4.4 イメージのリンクを取得

 次は、以下のように書いてある

</pre><div><a href="/img/FreeBSD/windows/01/01/01.png"><img src="/img/FreeBSD/windows/01/01/01.png" width="289" height="470" title="クリックでオリジナルのサイズで開きます"></a></div><pre>
 イメージファイルのリンクを取得します。  こちらは前項より簡単、同様に

doc.css('img').each do |anchor|
    puts anchor[:src]
end
 これで OK だな。  実行すると

> ./ソースファイル名.rb http://freebsd.sing.ne.jp/windows/01/01.html
/img/FreeBSD/adv/small01.png
/img/FreeBSD/adv/small03.png
/img/FreeBSD/windows/01/01/01.png
/img/FreeBSD/windows/01/01/02.png
/img/FreeBSD/windows/01/01/03.png
/img/FreeBSD/windows/01/01/04.png
/img/adv/google01.png
/img/FreeBSD/adv/middle02.png
/img/adv/admax02.png
/img/adv/google02.png
/img/adv/admax03.png
/img/adv/google04.png
/php/count.php?df=freebsd&sh=F
 予定通りです。

4.4.5 まとめて配列にぶち込む

 前項までのものをまとめて配列にぶち込みたいと思います。

#!/usr/bin/env ruby

require 'open-uri'
require 'nokogiri'

url = ARGV[0]

html = open(url).read

html.sub!(/^<!DOCTYPE html(.*)$/, '<!DOCTYPE html>')

doc  = Nokogiri::HTML(html)

link = []

doc.css('a').each do |anchor|
    link.push(anchor[:href])
end

doc.css('input').each do |anchor|
    if s = anchor[:onclick]
        s = s[/\'.*\'/]
        link.push(s.delete!("'"))
    end
end

doc.css('img').each do |anchor|
    link.push(anchor[:src])
end

puts link.sort
 これを実行すると

> ./ソースファイル名.rb http://freebsd.sing.ne.jp/windows/01/01.html
#1
#2
./
./02/
/img/FreeBSD/adv/middle02.png
/img/FreeBSD/adv/small01.png
/img/FreeBSD/adv/small03.png
/img/FreeBSD/windows/01/01/01.png
/img/FreeBSD/windows/01/01/01.png
/img/FreeBSD/windows/01/01/02.png
/img/FreeBSD/windows/01/01/02.png
/img/FreeBSD/windows/01/01/03.png
/img/FreeBSD/windows/01/01/03.png
/img/FreeBSD/windows/01/01/04.png
/img/FreeBSD/windows/01/01/04.png
/img/adv/admax02.png
/img/adv/admax03.png
/img/adv/google01.png
/img/adv/google02.png
/img/adv/google04.png
/php/count.php?df=freebsd&sh=F
http://net-3.blogspot.jp/2013/03/blog-post_16.html
 うむ、予定通り。

4.4.6 分類する

 前項までで収集したものを分類したいと思います。  末尾を変更します。

link.sort!

for item in link do
    case item[0]
    when '#'
            puts "ページ内リンク   => #{item}"

    when 'h'
            puts "外部    リンク   => #{item}"

    else
        if item[-3, 3] == 'png'
            puts "イメージファイル => #{item}"

        elsif item[-4, 4] == 'html' || item[-1, 1] == '/'
            puts "内部    リンク   => #{item}"

        else
            puts "                 => #{item}"

        end
    end
end
 これを実行すると

> ./ソースファイル名.rb http://freebsd.sing.ne.jp/windows/01/01.html
ページ内リンク   => #1
ページ内リンク   => #2
内部    リンク   => ./
内部    リンク   => ./02/
イメージファイル => /img/FreeBSD/adv/middle02.png
イメージファイル => /img/FreeBSD/adv/small01.png
イメージファイル => /img/FreeBSD/adv/small03.png
イメージファイル => /img/FreeBSD/windows/01/01/01.png
イメージファイル => /img/FreeBSD/windows/01/01/01.png
イメージファイル => /img/FreeBSD/windows/01/01/02.png
イメージファイル => /img/FreeBSD/windows/01/01/02.png
イメージファイル => /img/FreeBSD/windows/01/01/03.png
イメージファイル => /img/FreeBSD/windows/01/01/03.png
イメージファイル => /img/FreeBSD/windows/01/01/04.png
イメージファイル => /img/FreeBSD/windows/01/01/04.png
イメージファイル => /img/adv/admax02.png
イメージファイル => /img/adv/admax03.png
イメージファイル => /img/adv/google01.png
イメージファイル => /img/adv/google02.png
イメージファイル => /img/adv/google04.png
                 => /php/count.php?df=freebsd&sh=F
外部    リンク   => http://net-3.blogspot.jp/2013/03/blog-post_16.html