Windows + Ruby でマルコフ連鎖
マルコフ連鎖で日本語をもっともらしく要約する - ザリガニが見ていた...。 を見ていて面白そうだと思ったので、手元にあった Windows PC でやってみました。環境は以下のとおり。
以下、メモがわりに手順を書いておきます。
1) 形態素解析エンジン MeCab の Windows バイナリをダウンロードしてインストールします。(文字コードは Shift_JIS にしました)
2) 言語処理関連のプログラム類 の "windowsのrubyからlibmecab.dllを呼び出す" より mecab.rb をダウンロードします。
3) RubyGems から HTML 解析ライブラリ Nokogiri をインストールします。
gem install nokogiri
4) マルコフ連鎖で日本語をもっともらしく要約する - ザリガニが見ていた...。 にあるサンプルコードのうち以下を変更します。
また、44行目で生成した要約文を表示していますが、自分の場合 Kconv で Shift_JIS に変換する必要がありました。
puts Kconv.tosjis new_text.gsub!(/EOS$/,''))
以上を行った結果、以下のようなコードとなりました。これを markov.rb として保存します。
require 'Mecab' require 'rubygems' require 'nokogiri' require 'open-uri' # ヘッドラインの1行目の記事を取得する url = 'http://www.asahi.com/' text = String.new nokogiri = Nokogiri::HTML.parse(open(url)) li = nokogiri.xpath('//div[@id="HeadLine"]/ul[@class="Lnk FstMod"]/li[1]/a') nokogiri = Nokogiri::HTML.parse(open(url + li[0].attribute('href'))) nokogiri.xpath('//div[@class="BodyTxt"]/*').each do |body| text = text + body.text end text.gsub!(/\n/,'') # mecabで形態素解析して、 参照テーブルを作る mecab = Mecab.new("-Owakati") data = Array.new mecab.sparse_tostr(text + "EOS").split(" ").each_cons(3) do |a| data.push h = {'head' => a[0], 'middle' => a[1], 'end' => a[2]} end # マルコフ連鎖で要約 t1 = data[0]['head'] t2 = data[0]['middle'] new_text = t1 + t2 while true _a = Array.new data.each do |hash| _a.push hash if hash['head'] == t1 && hash['middle'] == t2 end break if _a.size == 0 num = rand(_a.size) # 乱数で次の文節を決定する new_text = new_text + _a[num]['end'] break if _a[num]['end'] == "EOS" t1 = _a[num]['middle'] t2 = _a[num]['end'] end # EOSを削除して、結果出力 puts Kconv.tosjis new_text.gsub!(/EOS$/,''))
あとは markov.rb と mecab.rb を同じディレクトリにおいて、
ruby markov.rb
とすると実行されます。
参考