更新(2021/04/29)
サイトの構造が変わっていたため別の記事でコードを更新しました。本記事より汎用性が高いためそちらを使う方が良いかもしれません。
更新済みサイト
目的
歌詞の分析をしようと思ったのですが、歌詞を集めるのが大変だな、と言うことでスクレイピングに初挑戦してみました。
正直、HTMLもまともに書いたことがないためやや不安はありましたがやりたいことはできたためまとめてみたいと思います。
アドバイスやミス表記は教えていただけると幸いです。
こちらが今回参考にさせていただいた記事です。
この記事では歌詞をテキストファイルとして入手することができます。
今回はこのコードを参考に書き換えさせてもらいました。
今回取得していくのは
- 曲名
- アーティスト名
- 作詞家
- 作曲家
- 歌詞
以上の5つです。
出力形式はcsvにしました。
また、今回スクレイピングしたサイトは「歌ネット: 歌詞検索サービス」です。
ライブラリ
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も変更しやすいようにしてみました。
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)
出力結果
今回取得した楽曲のデータはこちらです。
これで好きなだけ楽曲の分析ができるようになりました。
余談よりのまとめ(?)
自分の意図した通りに動くものを作るのは楽しいな、と感じました。
自己満要素の強い記事になってしまっているので後ほど更新していきたいなと思います。
(コードの説明もコメントアウトだけなので、、、)
Qiitaの書き方も自分なりに統一していきたいです。
次は自然言語処理やってみようかなと思います。