Help us understand the problem. What is going on with this article?

米津玄師の歌詞をWordCloudで可視化してみた。

More than 1 year has passed since last update.

きっかけ

えーみなさん、曲を聞いているときに歌詞を見たりしますか?
僕はよく見てます。でも歌詞って長くて読むの疲れちゃいますよね?
なので作詞家の言いたいことをスパッとまとめてみたいと思いました。
ズバリ「歌詞の可視化」です。
あ、いやまぁ研究をしているときに、聞いていた曲を一目で見てみたい!と思って、
「歌詞の可視化」に臨みました。はい、そうです。歌詞の可視化です。

自己紹介

smile.jpg

自己紹介ページ

環境情報
Python 3.6.5 |Anaconda, Inc.|
Windows10

本日のお品書き

今回はやることが多いですね。
・歌詞の収集(Webスクレイピング)
・歌詞を単語にする(形態素解析)
・可視化(WordCloud)
の3ステップです。

完成図

ちなみに作るのはこんな感じです。
wordcloud_sample.png

誰のなんの曲だかわかりますか?

注意

今回はJupyter Notebook上で実行しました。
Jupyter Notebookのインストールについては、Googleで調べてみてください。
文法などが一部、普通のPythonとは少し異なる部分もあるのでお気を付けください。

対象者

・Python3系を使っているユーザー(Anacondaでインストール)
・米津玄師のファン
・1を聞いて10を理解できるエンジニア
・Jupyter NoteBookを使ったことがある人
Windowsの人

非対象者

・Python2系を使っているユーザー
新米教師のファン
・説明下手な筆者を攻撃しようとするエンジニア
・Jupyter Notebookを使ったことがない人
Macの人

Cf.)Python2系とかPython3系の意味が分からない人へ!
Pythonには2系と3系があって、最近始めた人ならほとんどPython3系だと思います。一応バージョンを確認する方法を記載しておきます。
コマンドプロンプトでPythonのインタラクティブ(対話)モードを起動すればバージョン情報が表示されます。

$ Python
>Python 3.6.5 |Anaconda, Inc.| (default, Mar 29 2018, 13:32:41) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>

インタラクティブモードを辞めるにはexit()を入力しましょう!

Let's start

歌詞の収集

いちいちコピペするのは大変なので、一気にスクレイピングしましょう。
こちらのサイトを参考にいたしました。

Scrayping
import os
import re
import bs4
import time
import requests
import pprint

def load(url):
    res = requests.get(url)
    res.raise_for_status()

    return res.text

def pickup_tag(html, find_tag):
    soup = bs4.BeautifulSoup(str(html), 'html.parser')
    paragraphs = soup.find_all(find_tag)

    return paragraphs

def parse(html):
    soup = bs4.BeautifulSoup(str(html), 'html.parser')
    # htmlタグの排除
    kashi_row = soup.getText()
    kashi_row = kashi_row.replace('\n', '')
    kashi_row = kashi_row.replace(' ', '')

    # 英数字の排除
    kashi_row = re.sub(r'[a-zA-Z0-9]', '', kashi_row)
    # 記号の排除
    kashi_row = re.sub(r'[ <>♪`‘’“”・…_!?!-/:-@[-`{-~]', '', kashi_row)
    # 注意書きの排除
    kashi = re.sub(r'注意:.+', '', kashi_row)

    return kashi

def main():
    with open('yonedu_kashi.txt', 'a') as f:

        # アーティストページ(米津玄師)のアドレス
        url = 'https://www.uta-net.com/artist/12795/'

        # 曲ページの先頭アドレス
        base_url = 'https://www.uta-net.com'

        # ページの取得
        html = load(url)

        # 曲ごとのurlを格納
        musics_url = []
        # 歌詞を格納
        kashis = ''

        """ 曲のurlを取得 """
        # td要素の取り出し
        for td in pickup_tag(html, 'td'):
            # a要素の取り出し
            for a in pickup_tag(td, 'a'):
                # href属性にsongを含むか
                if 'song' in a.get('href'): 
                    # urlを配列に追加
                    musics_url.append(base_url + a.get('href'))


        """ 歌詞の取得 """
        for i, page in enumerate(musics_url):
            print('{}曲目:{}'.format(i + 1, page))
            html = load(page)
            for div in pickup_tag(html, 'div'):
                # id検索がうまく行えなかった為、一度strにキャスト
                div = str(div)
                # 歌詞が格納されているdiv要素か
                if r'itemprop="text"' in div:
                    # 不要なデータを取り除く
                    kashi = parse(div)
                    print(kashi, end = '\n\n')
                    # 歌詞を1つにまとめる
                    kashis += kashi + '\n'

                    # 1秒待機
                    time.sleep(1)
                    break
        # 歌詞の書き込み
        f.write(kashis)

if __name__ == '__main__':
    main()


# 出力結果はURLがたくさん並びます。
> 1曲目:https://www.uta-net.com/song/162135/
2曲目:https://www.uta-net.com/song/195154/
3曲目:https://www.uta-net.com/song/195149/
4曲目:https://www.uta-net.com/song/135723/
5曲目:https://www.uta-net.com/song/215592/
6曲目:https://www.uta-net.com/song/238731/
・・・(省略) 

参考サイトより
歌詞情報サイト歌ネット(utanet)から米津玄師さんの全73曲(2018.7.2現在)の歌詞を取得しました。
サーバに負荷を与えないため、1つの歌詞ごとに1秒待機するようにしています。今回は73曲なので1分ちょっとで終了しました。

※スクレイピングには注意が必要です。→過去記事
上記の方法ですべての歌詞を取得できます。

歌詞を単語にする(形態素解析)

形態素解析というものは、文章を切り分ける技術です。
ちなみに形態素というのは文章から、意味を持つように切り分けたときの最小単位です。
英語なら文章に空白が入っているので、形態素に切り分けやすいです。
I am SempleならIamSempleに分けることができます。

しかし日本語は英語と異なり、形態素には切り分けられません。
わたしはSempleですの場合はわたしSempleですに切り分ける必要があります。

そこでMeCabというツールを利用します。MeCabはいい感じに日本語を切り分けてくれます。

MeCabのインストールや形態素解析については今回は本筋から外れるので、詳細は面倒なので割愛いたします。まぁそういうものがあるんだなと思ってください。詳しく知りたい方がいたら、コメントください。要望があれば書きます。調べたほうが早いけどね…

MeCabの参考ページ

・インストール系
https://qiita.com/grachro/items/4fbc9bf8174c5abb7bdd
https://qiita.com/woody-kawagoe/items/09c0f89a55701bcf72eb#mecab
・使い方系
https://qiita.com/taroc/items/b9afd914432da08dafc8
様々な形態素解析器の紹介(Windows用ではないけど…。)

Morphological_analysis
import MeCab

#スクレイピングした歌詞のデータを取得
bindata = open("yonedu_kashi.txt", 'rb').read()
kashi = bindata.decode('cp932')

# 曲ごとに区切る
lines = kashi.split('\n')

mecab = MeCab.Tagger('-Ochasen')
mecab.parse('')

#一曲目を取得
node = mecab.parseToNode(lines[0])
output = []

#意味をなさないような単語を除外する。
stoplist=['「', '」', 'じゅう', 'そこら', 'れる', 'くい','ん','よう','の']

# 品詞に分解して、助詞や接続詞などは除外している。
while node:
    word_type = node.feature.split(",")[0]
    if word_type in ["名詞","形容詞","副詞","動詞"]:
        if not node.surface in stoplist and not node.surface.isdigit():
            output.append(node.surface.upper())
    node = node.next
print(output)

#出力結果 (ちなみになんの曲かわかる方いますかね…?いやまぁスクレイピングの部分のURL調べれば答え出てますけど…)
>['あたし', 'あなた', '会え', '本当に', '嬉しい', '前', 'それら', 'すべて', '悲しい', '今', '痛い', '幸せ', '思い出', 'いつか', '来る', '別れ', '育て', '歩く', '誰か', '居場所', '奪い', '生きる', 'もう', 'あたし', '石ころ', 'なれ', 'ならい', 'いなだ', 'し', '勘違い', '戸惑い', 'ない', 'そう', 'やっ', 'あなた', '知ら', 'まま', 'あなたに', 'あたし', '思い', '全部', '伝わっ', 'ほしい', '誰にも言えない', '秘密', 'あっ', '嘘', 'つい', 'しまう', 'あなた', '思え', '思う', 'いくつ', 'あたし', '意気地', 'ない', 'どうして', '消え', '悲しみ', '綻び', 'あなた', 'いれ', 'よかっ', '笑える', 'どんなに', '嬉しい', '目', '前', '全て', 'ぼやけ', '溶け', 'ゆく', '奇跡', 'あふれ', '足り', 'あたし', '名前', '呼ん', 'くれ', 'あなた', '居場所', '失', 'くし', '彷徨', 'もう', '誰か', '身代わり', 'なれ', '思う', '細やか', '確か', '見', 'ふり', 'きっと', '繰り返し', '笑い', '合う', '何', '度', '誓っ', '何', '度', '祈っ', '惨憺', '夢', '見る', '歪み', 'いつか', 'あなた', '呑ん', 'なくし', 'しまう', 'あなた', '思え', '思う', '大げさ', 'あたし', '不甲斐ない', 'どうして', 'お願い', 'いつまでもいつまでも', '超え', 'られ', '夜', '超えよ', '手', 'つなぐ', '日々', '続き', '閉じ', '瞼', '鮮やか', '彩る', 'ため', 'そのため', '何', 'できるかな', 'あなた', '名前', '呼ん', 'いい', '産まれ', 'き', '瞬間', 'あたし', '消え', 'しまい', '泣き', '喚い', 'それ', 'ずっと', '探し', 'いたん', 'いつか', '出会える', 'あなた', 'こと', '消え', '悲しみ', '綻び', 'あなた', 'いれ', 'よかっ', '笑える', 'どんなに', '嬉しい', '目', '前', '全て', 'ぼやけ', '溶け', 'ゆく', '奇跡', 'あふれ', '足り', 'あたし', '名前', '呼ん', 'くれ', 'あなた', '名前', '呼ん', 'いい']

kashiの部分のcp932はWindowsで使われている文字コードです。その程度の知識しかない。
詳しく知りたい方は調べて下さい。
そしてぜひ教えてください。

MeCab.Tagger('-Ochasen')については、MeCabはほかにもパラメータがあるので、いろいろ試してみてください。

可視化(WordCloud)

WordCloud
from wordcloud import WordCloud

#形態素解析された単語のリストをWordCloud用に処理している。
text = ' '.join(output)

#日本語はWindowsのフォントのパスを貼り付ける
fpath = "C:/Windows/Fonts/YuGothM.ttc"
wordcloud = WordCloud(background_color="white",
                      font_path = fpath, width=800,height=600).generate(text)
#WordCloudの画像は同じディレクトリ内に保存されます。
wordcloud.to_file("./wordcloud_sample.png")

WordCloud系の記事はたくさんあるので、その辺を参考にしながら作成しました。
日本語のフォントのパスをつけないと豆腐みたいになるので、お気を付けください。僕は豆腐になりました。
豆腐↓
wordcloud_sample.png
成功↓
wordcloud_sample.png

まぁ上でも見せてますが…一応。
WordCloudのパラメータをいじれば色とか変えられると思います。
この記事ではまぁFuture Workということで・・・。

参考記事

https://qiita.com/hirondine36/items/4a3bbc3c20a0fff21532#%E5%95%8F%E9%A1%8C1-%E6%96%87%E5%AD%97%E5%8C%96%E3%81%91

終わりに

とまぁ歌詞をWordCloudで可視化するのは、割と簡単にできて楽しかったです。
この記事自体はテンションで書ききったので、後日けっこう加筆修正を多分します。やらない
すべての曲をスクレイピングで取得したのに、一曲しか可視化してなくない?ってツッコミはやめましょう。
何度かグダグダしてしまいましたが、ここまでお読みいただきありがとうございます。

Senple
PythonとJavaScriptを少々…。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away