はじめに
12月14日に平成Ruby会議01に参加してきました。
「階層的クラスタリングをRubyで表現する」のセッションに影響されて、
普段、自然言語処理や統計などやっていない素人がやってみました。
環境
macOS Cataline 10.15.2
Ruby 2.5.3
Homebrew 2.2.1
インストール
MecabとMecabで使用する辞書をインストールします。
$ brew install mecab
$ brew install mecab-ipadic
$ mecab -v
mecab of 0.996
続いて、
MecabをRubyで扱うことのできるnattoをインストールします。
$ gem install natto
$ gem list natto
*** LOCAL GEMS ***
natto (1.1.2)
実装
今回歌詞を取得するため
歌ネット から nokogiri を使ってスクレイピングします。
今回nokogiri に関する説明は省略します。
欅坂46の歌詞の人気順のTOP10に絞って行いました。
https://www.uta-net.com/artist/19868/4/
まず人気一覧から各曲の歌詞ページの飛んで歌詞を取得し、
run_nattoに渡します。
require 'nokogiri'
require 'open-uri'
def run
doc = Nokogiri::HTML.parse(open('https://www.uta-net.com/artist/19868/4/'), nil, 'utf-8')
words = []
doc.css('.td1').each_with_index do |f, i|
link = f.children[0][:href]
url = "https://www.uta-net.com#{link}"
song = Nokogiri::HTML.parse(open(url), nil, 'utf-8')
title = song.css('.title > h2').text
run_natto(song, title, words)
break if i == 9
end
end
Natto::MeCab.newにノードフォーマットオプションを渡すことで
抽出する属性をカスタマイズすることができます。
今回は
「助詞」、「助動詞」、「記号」は除き、
形態素: ノードの品詞
の形で抽出しています。
人: 名詞
溢れ: 動詞
交差点: 名詞
どこ: 名詞
行く: 動詞
require 'natto'
def run_natto(song, title, words)
natto = Natto::MeCab.new('-F%m:\s%f[0]')
natto.enum_parse(song.css('#kashi_area').text).each do |n|
array = n.feature.split(': ')
if array[1] == '助詞' || array[1] == '助動詞' || array[1] == '記号'
next
else
words << array[0]
end
end
end
run_nattoで生成した配列から
形態素をkeyとして個数をvalueとするハッシュを生成し
CSVで出力しました。
require 'csv'
def run
...
hash = words.group_by(&:itself).map{ |key, value| [key, value.count] }.to_h
create_csv(hash)
end
def create_csv(hash)
CSV.open('file.csv', 'w') do |csv|
csv << %w[ワード カウント]
hash.each do |key, value|
csv << [key, value]
end
end
end
全体はこちらから。
https://github.com/kokinoue/analyze_lyrics_of_keyaki/blob/master/keyaki_songs.rb
結果
TOP10は以下のようになりました。
| ワード | カウント |
|---|---|
| ( | 68 |
| し | 50 |
| 僕 | 50 |
| ) | 45 |
| ん | 39 |
| れ | 37 |
| ない | 35 |
| 君 | 31 |
| 人 | 29 |
| 何 | 29 |
「僕」「君」は多いだろうなと思っていたので予想通りでしたが
「()」や「ん」「ない」などあまり参考にならないものが上位に来てしまい
改良の余地があるなと思いました…
ちなみに
| ワード | カウント |
|---|---|
| セゾン | 24 |
| Blah | 24 |
二人セゾンとアンビバレントですね
(セゾンこんな言ってるんだ…)
最後に
実際の発表ではさらに階層的クラスタリングを行っているのですが、
とりあえずは形態素解析まで行ってみました。
今回は秋元康でしたが別の作詞家でやってみると面白いかと思います!
参考
https://github.com/buruzaemon/natto
https://speakerdeck.com/ayumitamai97/implement-hierarchical-clustering-analysis-using-ruby
https://www.uta-net.com/
http://brainvalley.jp/blog/32
http://brainvalley.jp/blog/33