備忘録です

更新頻度は低め。

久しぶりの投稿

なんと前の投稿から7ヶ月近く経っていました。
近況報告としては4年生になって研究室活動が本格化してきて、院試受けました。
まだ、自大の院試は終わってないのですが、とりあえず合格もらった某大学院に進学するかなーと思ってます。
院試にかまけて色々サボってたので残り1ヶ月の夏休みは何か身になることをしたいものです。

Pythonでブルーグラスにおける頻出単語を調べる。

年末に大学の方でテキスト処理の実験を行い、Python形態素解析に触れた。その時「あれ、これを応用すればブルーグラスの歌詞に出てくる頻出単語を調べられるんじゃ...?」と思ったので年末年始のダラダラ防止も兼ねて、やってみることにした。あとこれをやろうと思ったのはこのサイト(西野カナの歌詞を分析して頻出単語を見てみた - Iruca Log)の影響もある。読んでみると結構面白い。
で、大まかなプランとして最初に浮かんだのが、

  1. ブルーグラスの歌詞をどこかから持ってきてテキスト化
  2. 全テキストに対して、カンマ、ピリオドの分離削除処理をする
  3. 形態素解析して動詞、形容詞、名詞だけもってくる
  4. 頻出単語をカウント

だった。最初に言っておくが実はまだ2の段階までしか終わっていない。お正月でしたので......

まずは1をどうしよう?ブルーグラスの歌詞がたくさん載っているサイト?どうやって歌詞のデータをもってくる?色々調べた結果PythonによるWebスクレイピングに至ったわけです。スクレイピングはWebサイトの必要な部分だけをデータとして抽出することで、これはPythonでプログラムを組んでできることが分かった。じゃあとりあえずスクレイピングするターゲットを決めよう。で、選ばれたのはこちらでした。

http://bluegrasslyrics.com/
f:id:asaaaai:20170112110859p:plain
このサイトではトップページに曲のリンクがずらーっとはってあって、任意の曲をクリックすると歌詞が書かれたページに飛ぶという形式。じゃあとりあえず曲が何曲あるか知らんけど、URL全部とってきて、そのURLに飛んでHTMLの歌詞の部分だけ取ってくるっていうの、for文とかで回せばいけそう!!!よく分かんないけど!!!っていう考えが浮かんだので、とりあえずページのHTMLを表示して見てみることに。
f:id:asaaaai:20170111161258p:plain
ははーんなるほど、

<li class="song">ここ</li>

が曲のURLだな〜。で、歌詞のページは?
f:id:asaaaai:20170111161927p:plain
は〜〜、

<p>ここ</p>

が歌詞ですね〜

で、作ったコードがこちら。

#-*- coding:utf-8 -*-
import urllib3
import bs4
import requests
import os
import glob

def getURL(soup): #曲のURLををとってくる
	urls = []
	urls_uniq = []

        #タグ指定でURLを取ってくる
	selectSoup = soup.find("ul", class_="list--songs")
	if(selectSoup):
		for link in soup.find_all("a"):
			if "song" in link.get("href"):
				urls.append(link.get("href"))
        
        #URLにダブりがあったのでそれを消す	
	for x in urls:
		if x not in urls_uniq:
				urls_uniq.append(x)

        #全曲のURLリストを返す
	return urls_uniq

def getLyrics(urls): #URLリストを与えて、それぞれのページの歌詞部分を取ってくる
	i = 0

        #ディレクトリを移動してそこに歌詞をぶち込む
	os.mkdir("./Lyrics")
	os.chdir("./Lyrics")
	for url in urls:
		lyrics = []
		lyrics_flat = []
		Lyrics = []
		res = requests.get(url)
		if res.status_code != requests.codes.ok:
			print('Error')
			exit(1)
		soup = bs4.BeautifulSoup(res.text,"html.parser")

                #タグ指定で歌詞を取ってくる
		for text in soup.find_all("p"):
			lyrics.append(text.get_text().split())

                #なぜかリストの二重構造になっていたのでそれを解消
		for x in lyrics:
			lyrics_flat.extend(x)

                #スペース区切りで単語リストをstr型に変換
                #カンマとピリオドを分離、削除
		s = ' '.join(lyrics_flat)
		for sep in [',','.']:
			s = s.replace(sep,' ')
		
                #上記の処理をした文章をまたスペース区切りでリストに変換
		Lyrics = s.split(' ')

                #ファイルに書き込み
		f = open(str(i) + '-lyrics.txt','w')
		for x in Lyrics:
			f.write(str(x) + ' ')
		f.close()
		del lyrics[:]
		del lyrics_flat[:]
		del Lyrics[:]
		i = i + 1

def main(url):
        #bluegrasslyrics.comのURLを与えて、それに対してスクレピングを行う
	res = requests.get(url)
	if res.status_code != requests.codes.ok:
		print('Error')
		exit(1)
	soup = bs4.BeautifulSoup(res.text,"html.parser")
	
	target_urls = []
	target_urls = getURL(soup)
	getLyrics(target_urls)

スクレイピングに関してはBeautiful Soupを使った。Beautiful Soup Python とかで調べると結構面白い。
で、めでたくLyricsディレクトリに1768曲分の歌詞のテキストファイルが生成された。(写真は一部)
f:id:asaaaai:20170112110403p:plain
適当に開いてみると
f:id:asaaaai:20170112101355p:plain
なんだが良さそう。あとはこれを形態素解析して動詞、形容詞、名詞だけもってくればよいな。
ここで、実験だと日本語テキストを処理したのでMeCabを使えばよかったのだけど、どうやら英語は他の方法を考える必要がありそう。調べてみた結果Tree Taggerというものがあるらしいのでそれを使っていこうと思う。
今の段階ではここまで。形態素解析するより、普通にカウントして冠詞とかそういうの無視すればいいかな?と思ったけど、なんかそれもスッキリしないのでこの方法で頑張ってみたい。なにかいい方法があればおしえてください。

そういえば最近、授業やら院生の方に頻出セットマイニングとか、非負値行列因子分解による特徴抽出とかそういった話を聞いたのでそっちに応用しても面白そうとおもった。