集合知プログラミングっぽいことををRejectセキュリティ&プログラミングキャンプでやろうかなーと思ってるんですが、データ操作とかは当日やりたくないのでぼちぼち準備とかしてみました。
apiとか使ってごにょごにょでもいいんですが、とりあえず自分が購読しているBlogをかたっぱしから集めてきて、MeCabで分解、分類みたいなことをやってみようかなーと思いました。そういうわけで
- Rubyでスクレイピング
- (Rubyにより)MeCabで名詞を抽出
- Rで集計
というのをやっておきました。下拵えをやっておけば、たぶん面白いところに時間をかけられるはず。
単語の集計
こんな感じで指定したurlのrssに登場する単語数を数えてみました。単語とみなせないものは後でフィルタリングをかける。> url <- "http://d.hatena.ne.jp/syou6162/rss2" > word <- table(extract_meisi_from_blog(url)) > head(word[order(word,decreasing=TRUE)],30) . =" > < / span class 839 711 692 565 511 466 394 </ " cgi - p hatena a 366 276 260 259 238 227 226 :// http "> li d jp ne 222 222 216 216 215 215 213 >< img src bin alt mimetex synSpecial 183 136 136 134 133 130 130 tex 1 130 116
で、opmlからblogのurlを引っ張ってきて、listにぶちこんでいます。
urls <- as.character(get_blogs_from_opml()$V2) blogs_words <- list() for(i in seq(urls)){ blogs_words[[i]] <- table(extract_meisi_from_blog(urls[i])) }
400個くらい購読しているBlogがあるんですが、その中の名詞は10万個くらい、という結果になりました。というわけで、400×100000くらいの行列を作れば、類似度とかその辺の計算はできるでしょう。
> length(names(unlist(blogs_words,recursive=FALSE))) [1] 101926
でーたまにゅぴゅれーしょん疲れます。。。
スクレイピングとかのコード
今回はさすがにRubyで分けたほうがいいような気がしてきたんですが、そうしたら負けか。csvとかの中間ファイルはさすがに使ってもいいかなと思い始めた。よく分からないエラーで悩まされたりするし(textConnectionの付近)。extract_meisi_from_blog <- function(url){ ruby <- paste(" require %q[rubygems] require %q[open-uri] require %q[hpricot] require %q[MeCab] require %q[kconv] url = %q[",url,"] description = %q[] begin doc = Hpricot(open(url).read) rescue => ex exit end (doc/:item).each {|item| description = description + (item/:description).inner_text } begin c = MeCab::Tagger.new(%q[-Ochasen]) n = c.parseToNode(description) list = Array.new while n do f = n.feature.split(/,/) if /名詞/ =~ f[0] list.push(n.surface) end n = n.next end list.each{|x| puts x} rescue exit end ",sep="") return(system(paste("echo '",ruby,"'"," | /opt/local/bin/ruby ",sep=""),intern=TRUE)) } get_blogs_from_opml <- function(){ ruby <- paste(" # -*- coding: utf-8 -*- #!/usr/bin/ruby -Ke require %q[rubygems] require %q[open-uri] require %q[hpricot] require %q[MeCab] require %q[kconv] require %q[csv] opml = %q[/Users/yasuhisa/Downloads/google-reader-subscriptions.xml] doc = Hpricot(open(opml).read) blogs = [] (doc/:outline).each {|item| hash = Hash.new hash[:title] = item[:title] hash[:url] = item[:xmlurl] blogs.push hash } blogs.reject!{|blog| blog[:url].nil?} CSV::Writer.generate($stdout) do |writer| blogs.each{|blog| writer << [blog[:title],blog[:url]] } end ",sep="") vec <- system(paste("echo '",ruby,"'"," | /opt/local/bin/ruby ",sep=""),intern=TRUE) text <- textConnection(vec) return(read.csv(text,header=FALSE)) close(text) }