歌詞分析するためにWebScrapingしてみた。

# 更新(2021/04/29)
サイトの構造が変わっていたため別の記事でコードを更新しました。本記事より汎用性が高いためそちらを使う方が良いかもしれません。
[更新済みサイト](https://qiita.com/Yodaka_ay/items/2da4680917784eb91f49)

# 目的
歌詞の分析をしようと思ったのですが、歌詞を集めるのが大変だな、と言うことでスクレイピングに初挑戦してみました。
正直、HTMLもまともに書いたことがないためやや不安はありましたがやりたいことはできたためまとめてみたいと思います。
アドバイスやミス表記は教えていただけると幸いです。

こちらが今回参考にさせていただいた記事です。
>[「米津玄師どこにも行けない説」をword2vecと歌詞を駆使して「どこへ行きたい」か探ってみた](https://qiita.com/k_eita/items/456895942c3dda4dc059#%E6%AD%8C%E8%A9%9E%E3%81%AE%E3%82%B9%E3%82%AF%E3%83%AC%E3%82%A4%E3%83%94%E3%83%B3%E3%82%B0)

この記事では歌詞をテキストファイルとして入手することができます。
今回はこのコードを参考に書き換えさせてもらいました。

今回取得していくのは
>1. 曲名
2. アーティスト名
3. 作詞家
4. 作曲家
5. 歌詞

以上の5つです。
出力形式はcsvにしました。

また、今回スクレイピングしたサイトは[「歌ネット: 歌詞検索サービス」](https://www.uta-net.com/)です。


# ライブラリ
~~~python
import re
import time
import requests
import pandas as pd
from bs4 import BeautifulSoup

#webサイトを取得し、テキスト形式で出力
def load(url):
    res = requests.get(url)
    #HTTPリクエストが失敗したステータスコードを返した場合、HTTPErrorを送出
    res.raise_for_status()
    #レスポンスボディをテキスト形式で入手
    return res.text

#htmlタグの取得
def get_tag(html, find_tag):
    soup = BeautifulSoup(str(html), 'html.parser')
    tag = soup.find(find_tag)
    return tag

#htmlタグの取得
def get_tags(html, find_tag):
    soup = BeautifulSoup(str(html), 'html.parser')
    tag = soup.find_all(find_tag)
    return tag

#htmlのid取得
def get_id(html, find_id):
    soup = BeautifulSoup(str(html), 'html.parser')
    html_id = soup.select(find_id)
    return html_id

#プログラムで扱えるデータ構造に変換
def parse(html):
    soup = BeautifulSoup(html, 'html.parser')
    #htmlタグの削除
    simple_row = soup.getText()
    simple_row = simple_row.replace('　', '')    
    return simple_row

def parse_lyric(html):
    soup = BeautifulSoup(html, 'html.parser')
    #htmlタグの削除
    simple_row = soup.get_text(separator=" ").strip()
    simple_row = simple_row.replace('　', ' ')

    return simple_row

#それぞれ歌の情報の取得
def get_info(url):
    base_url = 'https://www.uta-net.com/'
    html = load(url)
    #曲ごとのurlを格納
    song_url = []
    #歌を格納
    song_info = []
    songs_info=[]

    #曲のurlを取得
    #tdのurlを格納
    for td in get_tags(html, 'td'):
        #a要素の取得
        for a in get_tags(td, 'a'):
            #href属性にsongを含むか否か
            if 'song' in a.get ('href'):
                #urlを配列に追加
                song_url.append(base_url + a.get('href'))

    #曲の情報の取得
    for i, page in enumerate(song_url):
        print('{}曲目:{}'.format(i + 1, page))
        html = load(page)
        song_info = []

        #Song
        for tag in get_tag(html, 'h2'):
            #id検索を行うため、一度strにキャスト
            tag = str(tag)
            simple_row = parse(tag)
            song_info.append(simple_row)                

        #Artist
        for tag in get_tags(html, 'h3'):
            tag = str(tag)
            if r'itemprop="byArtist name"' in tag:
                simple_row = parse(tag)
                song_info.append(simple_row)

        #Lyricist
        for tag in get_tags(html, 'a'):
            tag = str(tag)
            if r'itemprop="lyricist"' in tag:
                simple_row = parse(tag)
                song_info.append(simple_row)

        #Composer
        for tag in get_tags(html, 'a'):
            tag = str(tag)
            if r'itemprop="composer"' in tag:
                simple_row = parse(tag)
                song_info.append(simple_row)

        #Lyric
        for id_ in get_id(html, '#kashi_area'):
            id_ = str(id_)
            if r'id="kashi_area"' in id_:
                simple_row = parse_lyric(id_)
                song_info.append(simple_row)
                songs_info.append(song_info)

                #1秒待機(サーバの負荷を軽減)
                time.sleep(1)
                break

    return songs_info

def create_df(file_name, url):
    # データフレームを作成
    #df = pd.DataFrame('Song_Title', 'Artist', 'Lyricist', 'Composer', 'Lyric')
    df = pd.DataFrame(get_info(url))
    df = df.rename(columns={0:'Song_Title', 1:'Artist', 2:'Lyricist', 3:'Composer', 4:'Lyric'})
    # CSVファイル出力
    csv = df.to_csv("csv/{}.csv".format(file_name))
    return csv
~~~

上記のコードを実行することでスクレイピングの準備が整います。
下記のコードを実行することで実際に歌詞などを取得することができます。
今回は美波さんの楽曲を取得させていただきました。
また、ファイル名とurlも変更しやすいようにしてみました。

~~~python
file_name = 'sample'
url = 'https://www.uta-net.com/artist/26099/'
#url = 'https://www.uta-net.com/user/ranking/daily.html'
#url = 'https://www.uta-net.com/user/ranking/monthly.html'
create_df(file_name, url)
~~~

# 出力結果
今回取得した楽曲のデータはこちらです。
これで好きなだけ楽曲の分析ができるようになりました。
<img width="956" alt="Screen Shot 2020-05-13 at 5.45.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533798/56e13842-e58a-14cc-12c5-1e9a4b2106f7.png">

# 余談よりのまとめ（？）
自分の意図した通りに動くものを作るのは楽しいな、と感じました。
自己満要素の強い記事になってしまっているので後ほど更新していきたいなと思います。
(コードの説明もコメントアウトだけなので、、、)
Qiitaの書き方も自分なりに統一していきたいです。
次は自然言語処理やってみようかなと思います。