Rubyのライブラリ「Nokogiri」を使って、HTML parsingをやってみることにします。
<僕が使っている環境>
ruby 2.0.0p247 (32bit)
DevKit-mingw64-32-4.7.2-20130224-1151-sfx (32bit)
nokogiri (1.6.0 x86-mingw32)
Windows7 (64bit)
(1)はじめに
もともと僕は、ruby 2.0.0p247 (64bit)を使っていました。ですが、64bit版を使っていると、Nokogiriのインストールで以下のようなエラーが発生して、うまくいきませんでした。
>gem install nokogiri Fetching: mini_portile-0.5.2.gem (100%) Successfully installed mini_portile-0.5.2 Fetching: nokogiri-1.6.0.gem (100%) Temporarily enhancing PATH to include DevKit... Building native extensions. This could take a while... ERROR: Error installing nokogiri: ERROR: Failed to build gem native extension. C:/work_Apps/Ruby/ruby-2.0.0-p247-x64-mingw32/bin/ruby.exe extconf.rb checking for libxml/parser.h... no ----- libxml2 is missing. please visit http://nokogiri.org/tutorials/installing_nokogiri.html for help with installing dependencies. ----- *** extconf.rb failed *** Could not create Makefile due to some reason, probably lack of necessary libraries and/or headers. Check the mkmf.log file for more details. You may need configuration options. Provided configuration options: --with-opt-dir --without-opt-dir : : (中略) Gem files will remain installed in C:/work_Apps/Ruby/ruby-2.0.0-p247-x64-mingw32/lib/ruby/gems/2.0.0/gems/nokogiri-1.6.0 for inspection. Results logged to C:/work_Apps/Ruby/ruby-2.0.0-p247-x64-mingw32/lib/ruby/gems/2.0.0/gems/nokogiri-1.6.0/ext/nokogiri/gem_make.out
libxml2が見つからないというエラーだったので、libxml2のインストール方法などなどを調べてみたものの、結局、解決しませんでした。
で、別の方向でいろいろ調べていたら、
Nokogiri does not yet support the 64-bit version of Ruby 2.0.0.
という情報を発見。
(参考) http://stackoverflow.com/questions/17280884/cant-install-nokogiri-for-ruby-in-windows
(参考) http://stackoverflow.com/questions/15320462/error-installing-nokogiri
そこで、32bit版のRuby2.0.0にしてみたら、Nokogiriのインストールがうまくいきました。
僕が使っているのは、「One-Click Ruby Installer for Windows」版です。
(2)Nokogiriのインストール
gemでインストールします。
すると、以下の2つのライブラリがインストールされました。
mini_portile (0.5.2)
nokogiri (1.6.0 x86-mingw32)
> gem install nokogiri Fetching: mini_portile-0.5.2.gem (100%) Successfully installed mini_portile-0.5.2 Fetching: nokogiri-1.6.0-x86-mingw32.gem (100%) Successfully installed nokogiri-1.6.0-x86-mingw32 Parsing documentation for mini_portile-0.5.2 Installing ri documentation for mini_portile-0.5.2 Parsing documentation for nokogiri-1.6.0-x86-mingw32 unable to convert "\x90" from ASCII-8BIT to UTF-8 for lib/nokogiri/1.9/nokogiri.so, skipping unable to convert "\x90" from ASCII-8BIT to UTF-8 for lib/nokogiri/2.0/nokogiri.so, skipping Installing ri documentation for nokogiri-1.6.0-x86-mingw32 2 gems installed > gem list *** LOCAL GEMS *** bigdecimal (1.2.0) io-console (0.4.2) json (1.7.7) mini_portile (0.5.2) minitest (4.3.2) nokogiri (1.6.0 x86-mingw32) psych (2.0.0) rake (0.9.6) rdoc (4.0.0) test-unit (2.0.0.0)
(3)使ってみる
とりあえず、Twitterのつぶやきを取ってみようかと思います。誰でもいいんだけど、今回は、孫正義さんのツイートにしてみます。
URLは、https://twitter.com/masason となり、HTTPSでアクセスすることになります。
しかし、
page=open('https://twitter.com/masason')
として、アクセスすると、SSLのエラーが発生します。
SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed (OpenSSL::SSL::SSLError)
そのため、今回は、「証明書を検証をしない」設定でアクセスすることにしました。
(参考) mofu犬blog: [Ruby] open-uri の HTTPS リクエストで certificate verify failed:
(参考) mofu犬blog: [Ruby] デフォルトの CA 証明書ファイルを変更しても、証明書の検証に失敗する:
あと、文字コードも指定しています。
require 'nokogiri' require 'open-uri' require 'openssl' page=open('https://twitter.com/masason', :ssl_verify_mode => OpenSSL::SSL::VERIFY_NONE) html = Nokogiri::HTML(page.read, nil, 'UTF-8')
次に、取得したいツイート内容が、HTMLソースの中でどうなっているか見てみます。
ツイッターのWeb画面のHTMLソースから、ツイート1件分のところを見てみると、以下のような感じになっています。
<div class=”content”> タグの中に、ツイートの時刻と本文が収まっています。
その中の、<small class=”time”>タグの中の、<a>タグの中の、title属性に、時刻が入っています。
そして、<p class=”js-tweet-text tweet-text”>タグの中に、ツイート本文が入っています。
これらを踏まえてコーディングするとこんな感じ。
html.search('div.content').each do |content| # tweet時間の表示 a=content.css('small.time a').first puts a.attribute("title").value # tweet本文の表示 p=content.css('p.js-tweet-text.tweet-text').first puts p.content end
(4)コーディングまとめ
最終的に作成したコードは、以下のようになりました。
僕の場合、AptanaStudioで動かしてるので、1行目の「#!/usr/bin/ruby」は適当です。
#!/usr/bin/ruby # -- coding: utf-8 require 'nokogiri' require 'open-uri' require 'openssl' page=open('https://twitter.com/masason', :ssl_verify_mode => OpenSSL::SSL::VERIFY_NONE) html = Nokogiri::HTML(page.read, nil, 'UTF-8') html.search('div.content').each do |content| puts "-" * 30 # tweet時間の表示 a=content.css('small.time a').first puts a.attribute("title").value # tweet本文の表示 p=content.css('p.js-tweet-text.tweet-text').first puts p.content end
実行するとこんな感じで、標準出力に返ってきます。
------------------------------ 2013年10月22日 - 7:39 昨日、我が社の笠井(76歳)さんが亡くなられた。 笠井さんは、私の父の様な兄の様な方。企業買収や投資に必要な財務戦略や、資金調達に多大な力を発揮。笠井さん無しに今日のソフトバンクは存立していない。心より感謝し、ご冥福をお祈りいたします。 ------------------------------ 2013年10月15日 - 6:18 夢さえあれば朝起きるのが楽しい。 ------------------------------ 2013年10月14日 - 7:42 物事の解決策は常に複数ある。 一つにこだわり過ぎてはならない。 : :