蛇ノ目の記

技術のことも。そうでないことも。

ダウンロードリンクからCSVをスクレイピングしてDataFrameにする - Spotify Charts編

少し前にこのブログでも取り上げたSpotify Charts。各国のヒットチャート・バイラルチャートが公開されている見ていて飽きないWebサービス

Spotify ChartsではチャートをCSV形式でダウンロードできる。そのCSVスクレイピングしてDataFrameにしてみる。ついでに順位の推移ごとにグルーピングして可視化めいたこともやってみた。

Notebook

今回のコードはColaboratoryで閲覧できるようにしている。Colaboratory便利かよ……。

colab.research.google.com

DataFrame作成

今回は日本のSpotify最新ヒットチャートのダウンロードリンク(https://spotifycharts.com/regional/jp/daily/latest/download)を扱う。Notebookの実行では2016/06/02のチャートになっている。

import io

import pandas as pd
import requests

from bs4 import BeautifulSoup as bs

res = requests.get('https://spotifycharts.com/regional/jp/daily/latest/download')

content = res.content

df = pd.read_csv(io.BytesIO(content))

バイト列で取得されるCSVの中身をBytesIOを使ってファイルオブジェクトの代わりにしている。この手法は以下のブログを参考にした。

www.haya-programming.com

1行目には Note that these figures are generated using a formula that protects against any artificial inflation of chart positions. というメッセージが入っているので、スキップする。

f:id:Nao_Y:20190604191620p:plain

df = pd.read_csv(io.BytesIO(content), skiprows=[0])

これでチャートのDataFrame化は完了。簡単。

f:id:Nao_Y:20190604191733p:plain

順位の推移をDataFrameに加える

ここからは作成したDataFrameに情報を足してゆく。

Spotify Chartsでは順位の推移を表す記号が表示されているが、この情報はCSVに含まれていないのでスクレイピングしてDataFrameに追加する。

記号はSVGで描画されているので、BeautifulSoupでHTMLをパースして順位の推移を取得する。

res = requests.get('https://spotifycharts.com/regional/jp/daily/latest/')
soup = bs(res.content)

svg_tags = soup.find_all('svg')

get_status関数でSVGタグのブロックから上昇、下降、維持、新規を判定する。 polygon属性の値などはブラウザのDeveloperToolでのぞき見た。

def get_status(svg):
  up = '0 9 12 9 6 3 '
  down = '12 3 0 3 6 9 '
  if svg.find('polygon'):
    polygon = svg.find('polygon')['points']
    if polygon == up:
      return 'up'
    elif polygon == down:
      return 'down'
  elif svg.find('rect'):
    return 'keep'
  elif svg.find('circle'):
    return 'new'

status = []
for svg in svg_tags:
  status.append(get_status(svg))

そしてDataFrameに列を追加。

df['status'] = status

f:id:Nao_Y:20190604192528p:plain

Spotify IDをDataFrameに追加

Simple-Spoitfyを使って曲の特徴情報を取得したくなるかもしれないので楽曲ごとに固有のSpotify IDをDataFrameに追加する。

df['Spotify ID'] = df['URL'].apply(lambda x: x.split('/')[-1])

f:id:Nao_Y:20190604192912p:plain

順位の推移をグルーピングして可視化してみる

順位の推移(status)の値でグルーピングして、推移の仕方による順位のQuantileをまとめる。

グルーピングしてからQuantileを求める手法は以下を参考にした。

stackoverflow.com

status_group = df.groupby(by='status')
positions = status_group['Position'].quantile([0.05, 0.25, 0.5, 0.75, 0.9]).unstack()

最後に推移ごと(上昇, 下降, 維持, 新規)による順位の分布を折れ線グラフにする。

positions.T.plot(figsize=(15, 10), title='Distribution of position change at 2019/06/02');

f:id:Nao_Y:20190604193827p:plain

雑可視化からなんとなくわかること。

  • 順位の維持は100位以下の順位では起きていない

  • ランキング初登場の曲は175~200位の間にしかランクインしていない

  • 初登場で上位に食い込む曲は無い

  • 順位の上昇・下降の約25%は20~70位内で起きている

Spotify Charts面白い

2017/01/01からのチャートが蓄積されているので、その時々の流行りや根強く聴かれている曲を見つけることができ面白い。 ここ半年くらいの日本のチャートを見ると、あいみょん人気がやばいことがわかる。聴いたことないけど。

チャートは2種類あり、TOP 200 はストリーミング数の蓄積によるランキング。一方、VIRAL 50SNSの分析で集計しているランキングらしい。 VIRAL 50の集計方法については以下のフォーラムで議論されている。

community.spotify.com

Spotify Web APIを使えば楽曲の特徴情報が得られるので、人気のある曲が持つ特徴を可視化することもできる。 そこで活きてくるのがSpotify Web APIPythonで使いやすくすることを目的にしているSimple-Spotify(ダイマ)。