駆け出しエンジニアの作業ノート

駆け出しエンジニアが作業ノート風にまとめるページ(関係無い事もしばしば)

FlaskでWebアプリを作る

お久しぶりです。だいぶ、日が空いてしまいましたが、相変わらず開発を続けています。

 

さて、GUIやクロスプラットプラットでのリリースを考えていましたが、自分自身の実力も踏まえWebアプリでのリリースとしました。

 

Webアプリにするにあたり、CUIより変更した部分があります。

 

1,ログイン機能

 

これは、SpotifyGoogleアカウントを使うので、アカウントの識別用として実装しました。

 

2,「嫌いな曲」登録機能

 

システムが生成したプレイリストの中に人によっては「嫌い」と思うような曲が含まれる場合があります。その場合に備え、嫌いな曲を除外してプレイリストを再生成する機能を実装しました。また、曲はDBに保存して2回目以降表示されないようにしています。

 

3,プレイリスト学習機能

 

本システムではLast.fmAPIを使用していますが、現状類似曲のデータが少ない問題があります。そこで、再生用プレイリストとして承認されたプレイリストを1つの固まりとみなして、Word2Vecを用いた学習を行う事にしました。

 

from flask import Flask, session, request, redirect, render_template, url_for
from spotify_token import Spotify_token
from gmusicapi import Mobileclient
import connect_lastfm_api
import sqlite3
import urllib.parse
import spotipy
import create_playlist_to_Spotify_etc
import spotify_auth

dbname = "account.db"

app = Flask(__name__)
last_fm_api_key = ""
app.config['SECRET_KEY'] = 'The secret key which ciphers the cookie'


@app.route("/")
def route():
return render_template('login.html')

@app.route("/create_account")
def create_account():
sql = "INSERT INTO account (user_name, password) values (?, ?)"
return render_template('create_account.html')

@app.route("/account_insert", methods=["GET", "POST"])
def account_insert():
res = request.form
user_name = res["user_name"]
password = res["password"]
sql = "INSERT INTO account (user_name, password) values (?, ?)"
data = (user_name, password)
conn = sqlite3.connect(dbname)
conn.cursor()
conn.execute(sql, data)
conn.commit()
conn.close()
return redirect(url_for("main_menu"))

@app.route("/error")
def error():
return render_template("error.html")

@app.route("/main_menu", methods=["GET", "POST"])
def main_menu():
res = request.form
user_name = res["user_name"]
password = res["password"]
if user_name is None or password is None:
return redirect(url_for("error"))
data = (user_name, password)
conn = sqlite3.connect(dbname)
cur = conn.cursor()
cur.execute("SELECT * FROM account WHERE user_name = ? AND password = ?", data)
list = cur.fetchall()
conn.close()
if list == []:
return redirect(url_for("error"))
else:
ID = list[0][0]
session["name"] = ID
return render_template('main_menu.html')

@app.route("/logout")
def logout():
session.pop("name", None)
return render_template("logout.html")

@app.route("/settings")
def settings():
return render_template('settings.html')

@app.route("/spotify_setting")
def spotify_setting():
return render_template("spotify_setting.html")

@app.route("/spotify_auth", methods=["GET", "POST"])
def spotify_auth():
res = request.form
print(res)
user_name = res["user_name"]
ID = session["name"]
service_name = "Spotify"
conn = sqlite3.connect(dbname)
cur = conn.cursor()
q = (ID, service_name)
cur.execute("SELECT * FROM service_account WHERE user_id = ? AND service = ?", q)
list = cur.fetchall()
if list == []:
url1 = "https://accounts.spotify.com/authorize?response_type=code&client_id="
my_client_id = "5e8438676fd741fd98475083c009b373"
url2 = "&scope="
scope = "user-read-private user-read-email"
scope = urllib.parse.quote(scope)
url3 = "&redirect_uri="
redirect_uri = "https://lastfm-playlist-generator-beta.herokuapp.com/"
redirect_uri = urllib.parse.quote(redirect_uri)
call_url = url1 + my_client_id + url2 + scope + url3 + redirect_uri
return redirect(url_for(call_url))

@app.route("/google_setting")
def google_setting():
return render_template("google_setting.html")

@app.route("/google_auth", methods=["GET", "POST"])
def google_auth():
res = request.form
gmail = res["gmail"]
password = res["password"]
ID = session["name"]
service_name = "Google"
conn = sqlite3.connect(dbname)
cur = conn.cursor()
q = (ID, service_name)
cur.execute("SELECT * FROM service_account WHERE user_id = ? AND service = ?", q)
list = cur.fetchall()
if list == []:
android_id = Mobileclient.FROM_MAC_ADDRESS
api = Mobileclient()
logged_in = api.login(email=gmail, password=password, android_id=android_id, locale="ja")
if logged_in == True:
data = (ID, service_name, gmail, password)
cur.execute("INSERT INTO service_account(user_id, service, user_name, password)VALUES(?, ?, ?, ?)", data)
conn.commit()
conn.close()
return redirect(url_for("account_success"))
else:
conn.close()
return redirect(url_for("account_faild"))
else:
conn.close()
return redirect(url_for("account_faild"))

@app.route("/account_success")
def account_success():
return render_template("account_success.html")

@app.route("/account_faild")
def account_faild():
return render_template("account_faild.html", list=list)

@app.route("/input_artist")
def input_artist():
return render_template('input_artist.html')

@app.route("/song_list", methods=["GET", "POST"])
def song_list():
res = request.form
artist = res["artist"]
session["artist"] = artist
session["count"] = 1
list = connect_lastfm_api.get_search_song_list(artist, last_fm_api_key, 1)
return render_template('song_list.html', list=list, number=len(list))

@app.route("/song_list/re", methods=["GET", "POST"])
def re_song_list():
artist = session["artist"]
count = session["count"]
count = count + 1
session["count"] = count
list = connect_lastfm_api.get_search_song_list(artist, last_fm_api_key, count)
return render_template('song_list.html', list=list, number=len(list))

@app.route("/playlist_generate", methods=["GET", "POST"])
def playlist_generate():
res = request.form
artist = session["artist"]
song = res["song"]
playlist = []
first_input = (artist, song)
playlist.append(first_input)
conn = sqlite3.connect(dbname)
cur = conn.cursor()
ID = session["name"]
service = "Last.fm"
q = (ID, service)
cur.execute("SELECT * FROM service_account WHERE user_id = ? AND service = ?", q)
list = cur.fetchall()
conn.close()
count = 0
playlist = genarate_playlist(artist, song, playlist, count)
session["playlist"] = playlist
return render_template("playlist_generate.html", playlist=playlist, number=len(playlist))

@app.route("/playlist_generate/re", methods=["GET", "POST"])
def replaylist_generate():
conn = sqlite3.connect(dbname)
cur = conn.cursor()
ID = session["name"]
res = request.form.getlist
track_list = res("track")
before_playlist = session["playlist"]
dislike_list = []
for i in range(len(track_list)):
track_number = track_list[i]
track_number = int(track_number)
dislike_list.append(before_playlist[track_number])
for j in range(len(dislike_list)):
remove_track = dislike_list[j]
before_playlist.remove(remove_track)
artist = remove_track[0]
song = remove_track[1]
data = (ID, artist, song)
cur.execute("INSERT INTO dislike_track(user_id, artist, song)VALUES(?, ?, ?)", data)
conn.commit()
session["playlist"] = before_playlist
playlist = before_playlist
track = playlist[len(playlist)-1]
artist = track[0]
song = track[1]
count = 0
playlist = genarate_playlist(artist, song, playlist, count)
session["playlist"] = playlist
return render_template("playlist_generate.html", playlist=playlist, number=len(before_playlist))



def genarate_playlist(artist, song, playlist, count):
song_count = len(playlist)
conn = sqlite3.connect(dbname)
cur = conn.cursor()
service = "Last.fm"
ID = session["name"]
q = (ID, service)
cur.execute("SELECT * FROM service_account WHERE user_id = ? AND service = ?", q)
list = cur.fetchall()
if list != []:
user_name = list[0][2]
recent_track_list = connect_lastfm_api.recent_play_song(last_fm_api_key, user_name)
else:
recent_track_list = []
similar_track_list = connect_lastfm_api.get_similar_track(artist, song, last_fm_api_key)
playlist_limit = 15
cur.execute("SELECT artist, song FROM dislike_track WHERE user_id = ?", (ID, ))
dislike_list = cur.fetchall()
if len(similar_track_list) == 0:
track = (artist, song)
if track in playlist:
pass
else:
playlist.append(track)
if len(playlist) >= playlist_limit:
get_playlist(playlist)
else:
page = 1
try:
list = connect_lastfm_api.get_search_song_list(artist, last_fm_api_key, page)
song_list = list[count]
song = song_list["name"]
count = count + 1
genarate_playlist(artist, song, playlist, count)
except KeyError:
artist = connect_lastfm_api.similar_artist_search(artist, last_fm_api_key)
count = 0
genarate_playlist(artist, song, playlist, count)
except IndexError:
artist = connect_lastfm_api.similar_artist_search(artist, last_fm_api_key)
count = 0
genarate_playlist(artist, song, playlist, count)
else:
for i in range(len(similar_track_list)):
track = similar_track_list[i]
if len(playlist) >= playlist_limit:
break
elif track in playlist:
continue
elif track in recent_track_list:
continue
elif track in dislike_list:
continue
else:
playlist.append(track)
if song_count == len(playlist):
similar_artist_list = connect_lastfm_api.get_similar_artist_list(artist, last_fm_api_key)
artist = similar_artist_list[0]
song_list = connect_lastfm_api.get_search_song_list(artist, last_fm_api_key, 1)
for i in range(len(song_list)):
list = song_list[i]
song = list["name"]
track = (artist, song)
if playlist not in track and recent_track_list not in track and dislike_list not in track:
break
else:
continue
count = count + 1
genarate_playlist(artist, song, playlist, count)
elif len(playlist) < playlist_limit:
search_data = playlist[len(playlist)-1]
artist = search_data[0]
song = search_data[1]
count = count + 1
genarate_playlist(artist, song, playlist, count)
else:
get_playlist(playlist)
return playlist

def get_playlist(playlist):
return playlist

@app.route("/playlist_generate/on_play", methods=["GET", "POST"])
def on_play_playlist():
playlist = session["playlist"]
ID = session["name"]
conn = sqlite3.connect(dbname)
cur = conn.cursor()
cur.execute("SELECT * FROM service_account WHERE user_id = ?", (ID, ))
account_list = cur.fetchall()
service_list = []
google_list = []
spotify_list = []
for i in range(len(account_list)):
account = account_list[i]
service = account[1]
user_name = account[2]
password = account[3]
service_list.append(service)
if service == "Spotify":
spotify_list.append(user_name)
elif service == "Google":
google_list.append(user_name)
google_list.append(password)
else:
continue
if service_list.count("Google") != 0 and service_list.count("Spotify") != 0:
return redirect(url_for("playlist_generate_which"))
elif service_list.count("Spotify") != 0:
result = get_empty_Spotify_playlist(first_input, playlist)
elif service_list.count("Google") != 0:
gmail = google_list[0]
g_password = google_list[1]
result = get_empty_google_music_playlist(playlist, gmail, g_password)
else:
return redirect(url_for("playlist_generate_end"))
if result is not None:
frg = 1
else:
frg = 0
print(frg)
session["frg"] = frg
return redirect(url_for("result"))


def get_empty_google_music_playlist(not_append_list, gmail, password):
android_id = Mobileclient.FROM_MAC_ADDRESS
name = "Spotifyから漏れた楽曲リスト"
api = Mobileclient()
logged_in = api.login(email=gmail, password=password, android_id=android_id, locale="ja")
playlist_id = api.create_playlist(name=name, description=None, public=False)
results = search_google(not_append_list, playlist_id, api)
return results

def search_google(playlist, playlist_id, api):
song_ids = []
not_append_list = []
file = open("playlist_log.txt", mode="a", encoding="utf-8")
for i in range(len(playlist)):
track_data = playlist[i]
s_artist = track_data[0]
s_song = track_data[1]
search_str = s_artist + " " + s_song
learn_str = s_artist + "_" + s_song
learn_str_en = urllib.parse.quote(learn_str)
file.write(learn_str_en)
file.write(" ")
search_data = api.search(query=search_str, max_results=None)
song_result = search_data["song_hits"]
try:
api_artist = song_result[0]["track"]["artist"]
api_song = song_result[0]["track"]["title"]
song_id = song_result[0]["track"]["storeId"]
similar_artist_list = connect_lastfm_api.get_similar_artist_list(s_artist, last_fm_api_key)
search_data = (s_artist, s_song)
api_data = (api_artist, api_song)
result = create_playlist_to_Spotify_etc.create_playlist(search_data, api_data, similar_artist_list)
if result == "add":
song_ids.append(song_id)
else:
not_append_song = (s_artist, s_song)
not_append_list.append(not_append_song)
except IndexError:
not_append_song = (s_artist, s_song)
not_append_list.append(not_append_song)
file.write("\n")
file.close()
results = google_playlist_input(playlist_id, song_ids, not_append_list, api)
return results

def google_playlist_input(playlist_id, song_ids, not_append_list, api):
results = api.add_songs_to_playlist(playlist_id=playlist_id, song_ids=song_ids)
if len(not_append_list) != 0:
print("以下のリストの曲はSpotify及びGoogle Play Musicで配信されていません")
print(not_append_list)
session.pop("playlist", None)
session["not"] = not_append_list
return results

@app.route("/result")
def result():
not_append_list = session["not"]
frg = session["frg"]
if frg == 0:
msg = "プレイリストが作成出来ませんでした"
else:
msg = "プレイリストが作成されました"
if len(not_append_list) == 0:
number = 0
msg2 = ""
else:
number = len(not_append_list)
msg2 = "以下の曲はストリーミング配信されていません"
return render_template("playlist_generate_success.html", not_append_list=not_append_list,
number=number, msg=msg, msg2=msg2)

if __name__ == "__main__":
# webサーバー立ち上げ
app.run()

 

 

では、プレイリストを乃木坂46シンクロニシティで作成してみます。

f:id:Psyduck_take_it_easy:20180531221548p:plain

f:id:Psyduck_take_it_easy:20180531221634p:plain

f:id:Psyduck_take_it_easy:20180531221750p:plain

最終的に調整をして以下のようにしました。

f:id:Psyduck_take_it_easy:20180531222013p:plain

f:id:Psyduck_take_it_easy:20180531225901p:plain

 

現状、Googleアカウントとしか連携出来ていませんが、プレイリスト作成には成功しています。

f:id:Psyduck_take_it_easy:20180531231517j:plain