LoginSignup
42
43

More than 5 years have passed since last update.

NokogiriとNattoで、Webページ内の単語を抽出する

Last updated at Posted at 2014-05-17

NokogiriとNattoについて

Rubyを使ってWebページの解析がしたいときは、NokogiriNattoというgemが非常に便利です。

Nokogiriは、xml/htmlの解析モジュールで、libxml2が入ってないとインストールがうまくいきません。Xcodeにくっついてくるlibxml2はちょっと古いらしいので、homebrewで入れ直すのもアリかもしれません。
参考:nokogiriとlibxml2とhomebrew

Nattoは、形態素解析エンジンのMeCabをrubyから使うためのインタフェースです。MeCabがインストールされていることが前提になりますので、homebrewなどでインストールしてください。
参考:rubyのmecabバインディングnattoを使う

Webページ内の単語を抽出する

実際に、NokogiriとNattoを使ってWebページ内に出現する名詞をカウントするサンプルを紹介します。

main.rb
#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
require 'nokogiri'
require 'open-uri'
require 'natto'

形態素解析をするためのNattoインスタンスと、単語をカウントするためのwordHashを作ります。

morpheme
nm = Natto::MeCab.new
wordHash = {}

open-uriを使ってWebページを取得し、NokogiriのHTMLパース機能を使ってhtmlドキュメントを取得します。オプションで「空白だけのテキスト要素を抜く」的なものがあったので入れてみましたが、なくても多分大丈夫です。docの中には、NokogiriのXML/HTML要素インスタンス(Nokogiri::XML::Element, Nokogiri::HTML::Element など)が入ります。

html_parse
doc = Nokogiri::HTML(open('http://example.com/')) do |config|
  config.noblanks
end

取得したhtmlドキュメントの中には、scriptタグがあるかもしれません。邪魔なので中身を空にしてやります。searchメソッドを使って、ブロック引数scriptcontentに空白文字を代入すればOKです。

blank_script_tag
doc.search("script").each do |script|
  script.content = "" ##scriptタグの中身を空にする
end

仕上げです。cssメソッドを使って、body要素の中身を解析します。body内の子要素一つ一つをelmに入れ、順番に処理します。タブ文字などの空白文字があると上手く形態素解析ができないため、gsubですべて空文字列に置き換えます。それをNattoインスタンスのnmparseさせ、名詞の場合のみカウントします。初出の名詞、つまりwordHash[n.surface]が定義されていない場合はwordHash[n.surface]=1で項目の初期化を、すでに一度出ている名詞ならばwordHash[n.surface]+=1でカウンターの数を一つ増やすようにしています。

count_words
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の中にはページ内の名詞出現回数の解析結果が入っているはずです。

preview
p wordHash

前はmecab-rubyが使いづらくてよく困ったものですが、だいぶ楽にできるようになって嬉しい限りです。

42
43
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
42
43