Rubyで『集合知プログラミング』(2)

第3章「グループを見つけ出す」

3.2 単語ベクトル

"generatefeedvector.rb"を実装してみます。
RSSの解析にはRSS Parserを使います。

RSSフィードのタイトルと,単語のカウントを返すメソッドから。

require 'rss'
def get_word_counts(url)
  # RSSをParse
  rss_parse = open(url){|f| RSS::Parser.parse(f.read)}
  wc = Hash.new(0)
  # 全エントリから単語のリストを取り出す
  rss_parse.items.each do |e|
    words = get_words(e.title + ' ' + e.description)
    words.each{|w| wc[w] += 1}
  end
  return rss_parse.channel.title, wc
end

単語リストの取得。

def get_words(html)
  # タグを除去
  txt = html.gsub(/<[^>]>/, '')
  # 非アルファベットで分割
  txt.downcase.split(/[^A-Za-z]+/).reject{|w| w==''}
end

単語のカウントを計算します。と同時に,その単語が登場するRSSのカウントを取ります。

apcount = Hash.new(0)  # その単語が登場するRSSのカウント
word_counts = Hash.new(0)
# RSSのURLリストを取得
feed_list = open('feedlist.txt') do |f|
  f.readlines.map{|l| l.chomp}
end
# 各RSSについてタイトルと単語のカウントを取得
feed_list.each do |url|
  begin
    title, wc = get_word_counts(url)
    word_counts[title] = wc
    wc.each do |word, count|
      apcount[word] += 1 if count > 1
    end
  rescue
    puts("Failed to parse feed #{url}")
  end
end

単語を,その出現頻度により絞り込みます。

word_list = []
apcount.each do |w, bc|
  frac = bc.to_f / feed_list.length
  word_list.push(w) if 0.1 < frac and frac < 0.5
end

単語の出現数の表を作成します。

open('blogdata.txt', 'w') do |f|
  line = ['Blog'] + word_list
  f.puts line.join("\t")

  word_counts.each do |blog, wc|
    line = [blog] + word_list.map{|word| wc[word] || 0}
    f.puts line.join("\t")
  end
end

ここまで。
結果の'blogdata.txt'はかなり巨大なので,省略します。