##NokogiriとNattoについて
Rubyを使ってWebページの解析がしたいときは、NokogiriとNattoというgemが非常に便利です。
Nokogiriは、xml/htmlの解析モジュールで、libxml2が入ってないとインストールがうまくいきません。Xcodeにくっついてくるlibxml2はちょっと古いらしいので、homebrewで入れ直すのもアリかもしれません。
参考:nokogiriとlibxml2とhomebrew
Nattoは、形態素解析エンジンのMeCabをrubyから使うためのインタフェースです。MeCabがインストールされていることが前提になりますので、homebrewなどでインストールしてください。
参考:rubyのmecabバインディングnattoを使う
##Webページ内の単語を抽出する
実際に、NokogiriとNattoを使ってWebページ内に出現する名詞をカウントするサンプルを紹介します。
#coding:utf-8
require 'nokogiri'
require 'open-uri'
require 'natto'
nm = Natto::MeCab.new
wordHash = {}
doc = Nokogiri::HTML(open('http:/example.com')) do |config|
config.noblanks
end
doc.search("script").each do |script|
script.content = "" ##scriptタグの中身を空にする
end
doc.css('body').each do |elm|
text = elm.content.gsub(/(\t|\s|\n|\r|\f|\v)/,"")
nm.parse(text) do |n|
wordHash[n.surface] ? wordHash[n.surface] += 1 : wordHash[n.surface] = 1 if n.feature.match("名詞")
end
end
p wordHash
上から順番にいきます。まず、必要なgemをrequireしています。open-uri
は、Webページのデータを取得するのに必要です。
require 'nokogiri'
require 'open-uri'
require 'natto'
形態素解析をするためのNattoインスタンスと、単語をカウントするためのwordHashを作ります。
nm = Natto::MeCab.new
wordHash = {}
open-uriを使ってWebページを取得し、NokogiriのHTMLパース機能を使ってhtmlドキュメントを取得します。オプションで「空白だけのテキスト要素を抜く」的なものがあったので入れてみましたが、なくても多分大丈夫です。doc
の中には、NokogiriのXML/HTML要素インスタンス(Nokogiri::XML::Element, Nokogiri::HTML::Element など)が入ります。
doc = Nokogiri::HTML(open('http://example.com/')) do |config|
config.noblanks
end
取得したhtmlドキュメントの中には、scriptタグがあるかもしれません。邪魔なので中身を空にしてやります。search
メソッドを使って、ブロック引数script
のcontent
に空白文字を代入すればOKです。
doc.search("script").each do |script|
script.content = "" ##scriptタグの中身を空にする
end
仕上げです。css
メソッドを使って、body要素の中身を解析します。body内の子要素一つ一つをelm
に入れ、順番に処理します。タブ文字などの空白文字があると上手く形態素解析ができないため、gsub
ですべて空文字列に置き換えます。それをNattoインスタンスのnm
にparse
させ、名詞の場合のみカウントします。初出の名詞、つまりwordHash[n.surface]
が定義されていない場合はwordHash[n.surface]=1
で項目の初期化を、すでに一度出ている名詞ならばwordHash[n.surface]+=1
でカウンターの数を一つ増やすようにしています。
doc.css('body').each do |elm|
text = elm.content.gsub(/(\t|\s|\n|\r|\f|\v)/,"")
nm.parse(text) do |n|
wordHash[n.surface] ? wordHash[n.surface] += 1 : wordHash[n.surface] = 1 if n.feature.match("名詞")
end
end
これで、wordHash
の中にはページ内の名詞出現回数の解析結果が入っているはずです。
p wordHash
前はmecab-rubyが使いづらくてよく困ったものですが、だいぶ楽にできるようになって嬉しい限りです。