LoginSignup
2
1

More than 1 year has passed since last update.

Spotify APIを用いた、印象語による楽曲検索(距離計算編)

Last updated at Posted at 2021-06-10

上の続きです
スクリーンショット 2021-06-10 10.17.40.png

今回はimpressionのテーブルの定義とmain.pyの部分を記事にします
シェルスクリプトで関数を実行するために以下の記事を参考にしました

main.pyの中身はこうなっています

main.py
import argparse
import norm

#距離計算
# python main.py music_impression -i '{印象語}'

def music_impression(name):
    norm.distance(name)

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument('function_name',
                        type=str,
                        help='set fuction name in this file')
    parser.add_argument('-i', '--func_args',
                        nargs='*',
                        help='args in function',
                        default=[])
    args = parser.parse_args()

    # このファイル内の関数を取得
    func_dict = {k: v for k, v in locals().items() if callable(v)}
    # 引数のうち,数値として解釈できる要素はfloatにcastする
    func_args = [float(x) if x.isnumeric() else x for x in args.func_args]
    # 関数実行
    ret = func_dict[args.function_name](*func_args)

今回中にあるのはnorm.py(距離計算)だけです

実行環境
macOS Catlina 10.15.7
Python 3.7.5

impressionテーブル

main.pyはimpressionテーブル(以下impression)とmusicテーブル(以下music)の距離計算で上位10曲を表示するというものになっています
musicはSpotify APIを用いているのでimpressionの正確さが結果の正確さに直結します

ここに客観性かつ正確性を持たせるために現在思案中です
とりあえずは25人にそれぞれの印象に当てはまる曲を挙げてもらい、平均を出しました

fc=# select * from impression;
  word   | danceability | acousticness |  energy  | liveness | loudness  | speechiness |   tempo    | valence
---------+--------------+--------------+----------+----------+-----------+-------------+------------+----------
 excited |     0.559412 |     0.238991 | 0.753471 | 0.177212 | -6.361706 |      0.1073 | 128.399882 | 0.565765
 cool    |     0.533333 |     0.176618 | 0.796208 | 0.214154 | -5.769667 |      0.0718 | 124.457208 | 0.456937
 relax   |       0.5335 |     0.420415 | 0.604963 | 0.161387 | -7.346125 |    0.069258 | 121.235208 | 0.504838
 sad     |        0.509 |     0.403961 | 0.593177 | 0.183709 | -6.792652 |    0.046196 | 119.219565 | 0.408422
 fierce  |      0.53716 |     0.136491 | 0.823628 |   0.1822 |   -5.7808 |    0.099324 |  132.39152 | 0.505112

距離計算

norm.py
import psycopg2

def distance(name):
    conn = psycopg2.connect("host=" + "localhost" +
                            " dbname=" + {データベース名} +
                            " user=" + {自分のmacのユーザーネーム} +
                            " password=" + "")
    cur = conn.cursor()
    cur.execute("SELECT * FROM music")
    m = cur.fetchall()
    conn.commit()
    print("The number of music is ", len(m))
    conn.commit()
    cur.execute("SELECT music.name, music.artist, distance(music.danceability, music.acousticness, music.energy, music.liveness, music.loudness, music.speechiness, music.tempo, music.valence, impression.danceability, impression.acousticness, impression.energy, impression.liveness, impression.loudness, impression.speechiness, impression.tempo, impression.valence) AS score FROM music, impression WHERE impression.word = '{}' ORDER BY score ASC FETCH FIRST 10 ROWS ONLY".format(name))
    n = cur.fetchall()
    conn.commit()
    print()
    print(name)
    for n_ in n:
        print(n_)
    print()
    cur.close()
    conn.close()

    return

distanceという関数をsqlで定義しています
これは距離計算をする関数です

norm.sql
CREATE FUNCTION distance(float, float, float, float, float, float, float, float, float, float, float, float, float, float, float, float) RETURNS float 
AS 'SELECT sqrt(($1 - $9)^2 + ($2 - $10)^2 + ($3 - $11)^2 + ($4 - $12)^2 + ($5 - $13)^2 + ($6 - $14)^2 + ($7 - $15)^2 + ($8 - $16)^2 ) AS distance'
LANGUAGE 'sql';

実行結果(fierce)

こんな感じに結果が出てきます

~/music2imp$ python main.py music_impression -i 'fierce' 
The number of music is  2849

fierce
('Fxxker', 'CHANMINA', 0.4662540877118465)
('よー、そこの若いの', 'Takehara Pistol', 0.484637866437422)
('Tik Tik Tok (Rhythm of the Clock) - Original Mix', 'Kid Alina', 0.4947239347393736)
('Dark Horse', 'Katy Perry', 0.6637707380602147)
('ダンシング・ヒーロー(Eat You Up)', 'Yoko Oginome', 0.7221408093890002)
('インフルエンサー 〜off vocal ver.〜 - Off Vocal Version', 'Nogizaka46', 0.7878546612066344)
('pov', 'Ariana Grande', 0.7881882205317551)
('ONLY ONE', 'SPiCYSOL', 0.800737013372686)
('格好悪いふられ方', 'Senri Oe', 0.8075263077974683)
('19 GROWING UP -ode to my buddy-', 'PRINCESS PRINCESS', 0.8426145755830627)
2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1