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

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

仕様変更とリファクタリングをしました

仕様を大きく変更しました。前のコードではlast.fmAPIのデータを収録したDBを経由していましたが、メンテナンスコストが負担になっていたので、DBを経由せずにAPIを直接参照するように切り替えました。

 

また、API参照の部分をべた書きすると、今度は本体部分のメンテナンスがし辛くなってしまったので、API参照の部分は別ファイルを参照する方式にしました。

 

では、まずは本体部分です。

import spotipy
import re
import get_similar_track_sandbox
from spotify_token import Spotify_token

api_key =
username =

def input_artist():
artist = input("検索したいアーティスト名を入力して下さい")
page = 1
search_song_list(artist, page)

def search_song_list(artist, page):
list = get_similar_track_sandbox.get_search_song_list(artist, api_key, page)
for i in range(len(list)):
song_list = list[i]
song = song_list["name"]
print(song)
yes_or_no = input("この中に探したい曲はありましたか?(y/n)")
#yes_or_no = "y"
if yes_or_no == "y":
search_track(artist)
elif yes_or_no == "n":
page = page + 1
search_song_list(artist, page)
else:
print("正しい入力ではありません")

def search_track(artist):
song = input("曲名を入力して下さい")
create_playlist(artist, song)

def create_playlist(artist, song):
playlist = []
first_input = (artist, song)
playlist.append(first_input)
k = 0
genarate_playlist(first_input, artist, song, playlist, k)

def genarate_playlist(first_input, artist, song, playlist, k):
track = get_similar_track_sandbox.get_similar_track(artist, song, api_key)
similar_artist_list = get_similar_track_sandbox.similar_artist_search(artist, api_key)
playlist_limit = 15
for i in range(len(similar_artist_list)):
similar_artist = similar_artist_list[i]
for j in range(len(track)):
if len(playlist) >= playlist_limit:
break
else:
song_list = track[j]
similar_song = song_list["name"]
similar_song_artist = song_list["artist"]["name"]
match = song_list["match"]
match = float(match)
result = (similar_song_artist, similar_song)
if match < 0.1:
continue
elif result in playlist:
continue
elif similar_song_artist == similar_artist:
playlist.append(result)
else:
continue
try:
if len(playlist) < playlist_limit -1:
print(playlist)
k = k + 1
search_word = playlist[k]
artist = search_word[0]
song = search_word[1]
genarate_playlist(first_input, artist, song, playlist, k)
else:
print(playlist)
get_empty_Spotify_playlist(first_input, playlist)
except IndexError:
print(playlist)
page = 1
list = get_similar_track_sandbox.get_search_song_list(artist, api_key, page)
print(list)
song_list = list[0]
song = song_list["name"]
k = 1
search_word = (artist, song)
playlist.append(search_word)
genarate_playlist(first_input, artist, song, playlist, k)

def get_empty_Spotify_playlist(first_input, playlist):
playlist_name = first_input[0] + "の" + first_input[1] + "から始まるおすすめプレイリスト"
ST = Spotify_token(username)
token = ST.set()
sp = spotipy.Spotify(auth=token)
sp.trace = False
playlistts = sp.user_playlist_create(username, playlist_name)
playlist_id = playlistts["id"]
song_ids = []
for i in range(len(playlist)):
search_str = playlist[i]
s_artist = search_str[0]
s_song = search_str[1]
search_str = s_artist + " " + s_song
result = sp.search(search_str, limit=1)
for item in result["tracks"]["items"]:
print(item["artists"][0]["name"])
print(item["name"])
print(type(item["name"]))
print(item["id"])
api_song = item["name"]
api_song = re.sub("\t", "", api_song)
if api_song == s_song:
print("OK")
song_id = item["id"]
song_ids.append(song_id)
else:
continue
playlist_input(playlist_id, song_ids)

def playlist_input(playlist_id, song_ids):
ST = Spotify_token(username)
token = ST.set()
if token:
sp = spotipy.Spotify(auth=token)
sp.trace = False
results = sp.user_playlist_add_tracks(username, playlist_id, song_ids)
print(results)
else:
print("Can't get token for", username)

if __name__ == '__main__':
input_artist()

 

次に、API参照部分です。

 

import urllib.request
import urllib.parse
import json

def get_search_song_list(artist, api_key, page):
artist = urllib.parse.quote(artist)
artist_api1 = "http://ws.audioscrobbler.com/2.0/?method=artist.gettoptracks&artist="
artist_api2 = "&autocorrect=1&page="
page = str(page)
artist_api3 = "&api_key="
artist_api4 = "&format=json"
call_api = artist_api1 + artist + artist_api2 + page + artist_api3 + api_key + artist_api4
print(call_api)
address_json = urllib.request.urlopen(call_api)
data = json.loads(address_json.read())
track = data["toptracks"]
list = track["track"]
return list

def get_similar_track(artist, song, api_key):
artist = urllib.parse.quote(artist)
song = urllib.parse.quote(song)
track_api1 = "http://ws.audioscrobbler.com/2.0/?method=track.getsimilar&artist="
track_api2 = "&track="
track_api3 = "&autocorrect=1&api_key="
track_api4 = "&format=json"
call_api = track_api1 + artist + track_api2 + song + track_api3 + api_key + track_api4
print(call_api)
address_json = urllib.request.urlopen(call_api)
data = json.loads(address_json.read())
similartracks = data["similartracks"]
track = similartracks["track"]
return track

def similar_artist_search(artist, api_key):
artist = urllib.parse.quote(artist)
artist_api1 = "http://ws.audioscrobbler.com/2.0/?method=artist.getsimilar&artist="
artist_api2 = "&autocorrect=1&api_key="
artist_api3 = "&format=json"
call_api = artist_api1 + artist + artist_api2 + api_key + artist_api3
print(call_api)
address_json = urllib.request.urlopen(call_api)
data = json.loads(address_json.read())
similarartists = data["similarartists"]
artist_list = similarartists["artist"]
similar_artist_list = []
artist = urllib.parse.unquote(artist)
similar_artist_list.append(artist)
for i in range(len(artist_list)):
list = artist_list[i]
similar_artist = list["name"]
match = list["match"]
match = float(match)
if match > 0.1:
similar_artist_list.append(similar_artist)
else:
break
return similar_artist_list

 

では、ここに乃木坂46の新曲「シンクロニシティ」を入れてみます。

 

シンクロニシティ

シンクロニシティ

  • provided courtesy of iTunes

 

システムに基づくプレイリストは以下の通りです。

 

[('乃木坂46', 'シンクロニシティ'), ('乃木坂46', '制服のマネキン'), ('乃木坂46', '君の名は希望'), ('乃木坂46', '命は美しい'), ('HKT48', '桜、みんなで食べた'), ('HKT48', '12秒'), ('E-Girls', 'ごめんなさいのKissing You'), ('E-Girls', 'Mr.Snowman'), ('山本彩', '夢のdead body'), ('山本彩', 'ジャングルジム'), ('高橋みなみ', 'Jane Doe'), ('高橋みなみ', '右肩'), ('E-Girls', 'E.G. Anthem -WE ARE VENUS-'), ('AKB48', '希望的リフレイン'), ('AKB48', 'overture')] 

 

では、実際に出来たSpotifyプレイリストを見てみましょう。

 

f:id:Psyduck_take_it_easy:20180426235913p:plain

 

HKT48山本彩さんの楽曲が入っていません。これは、Spotifyでは配信されていない為です。E-girlsの「E.G. Anthem -WE ARE VENUS-」が入っていませんが、Spotifyでの表記が若干異なることから入らなかったようです。ちなみに、Google Play Musicではリスト曲全て配信されています。

 

自分としては、Google Play MusicAPIが出ることを切に願っています。

 

今後は24時間以内に再生した楽曲を除去する機能を搭載し、プレイリストの自動生成を何度も用いても同じ曲が再生されないような仕組み作りを行います。

Last.fmのデータを使って、Spotifyのプレイリストを作成するモジュールが出来た

Last.fmという音楽系のAPIがあります。オライリーの本で「Audioscrobbler」として紹介されているものです。このデータを用いてSpotifyのプレイリストを作成するモジュールが完成しました。

 

import psycopg2
import psycopg2.extras
import spotipy
import spotipy.util as util
import pprint
import re
from spotify_token import Spotify_token

host_name =
port_number =
dbname =
rolename =
passwd =

username =
# API式に切り替える時にアーティスト名から検索可能な曲名の一覧を出す

def get_artist_similar():
conn = psycopg2.connect(database=dbname, host=host_name, port=port_number, user=rolename, password=passwd)
cur = conn.cursor()
cur.execute("SELECT to_artist FROM similar_artist WHERE from_artist = %s AND match_index > 0.01 ORDER BY match_index DESC", (artist,))
'''conn.query("SELECT * FROM similar_artist")'''
similar_artist_list = cur.fetchall()
conn.close()
return similar_artist_list

def get_most_similar_song():
conn = psycopg2.connect(database=dbname, host=host_name, port=port_number, user=rolename, password=passwd)
cur = conn.cursor()
similar_artist_list = get_artist_similar()
playlist = []
playlist.append(first_input)
if similar_artist_list == []:
print("類似するアーティストが登録されていないか、打ち間違いの可能性があります。")
else:
cur.execute(
"SELECT to_artist, to_song FROM similar_track WHERE from_artist = %s AND from_song = %s AND match_index = 1.0",
first_input)
similar_tracklist = cur.fetchall()
if similar_tracklist == []:
cur.execute("SELECT from_artist, from_song FROM similar_track WHERE from_artist = ?", (artist,))
similar_tracklist = cur.fetchall()
similar_track = similar_tracklist[0]
playlist.append(similar_track)
return playlist
else:
similar_track = similar_tracklist[0]
playlist.append(similar_track)
return playlist
conn.close()

def generate_playlist():
conn = psycopg2.connect(database=dbname, host=host_name, port=port_number, user=rolename, password=passwd)
cur = conn.cursor()
similar_artist_list = get_artist_similar()
playlist = get_most_similar_song()
for i in range(len(similar_artist_list) - 1):
if len(playlist) == 10:
return playlist
else:
similar_artist = similar_artist_list[i]
search_word = (first_input[0], first_input[1], similar_artist[0])
cur.execute("SELECT to_artist, to_song FROM similar_track WHERE from_artist = %s AND from_song = %s AND to_artist = %s AND match_index > 0.01 ORDER BY match_index DESC", search_word)
similar_tracklist = cur.fetchall()
for j in range(len(similar_tracklist) - 1):
trackdata = similar_tracklist[j]
if trackdata in playlist:
continue
else:
playlist.append(trackdata)
print(playlist)
conn.close()

def playlist_print():
playlist = generate_playlist()
print(playlist)
get_empty_Spotify_playlist(playlist)
return playlist

def get_empty_Spotify_playlist(playlist):
playlist_name = artist + "の" + song + "から始まるおすすめプレイリスト"
ST = Spotify_token(username)
token = ST.set()
sp = spotipy.Spotify(auth=token)
sp.trace = False
playlistts = sp.user_playlist_create(username, playlist_name)
pprint.pprint(playlistts)
playlist_id = playlistts["id"]
print(playlist_id)
song_ids = []
for i in range(len(playlist)):
search_str = playlist[i]
s_artist = search_str[0]
s_song = search_str[1]
search_str = s_artist + " " + s_song
result = sp.search(search_str, limit=1)
print(result)
for item in result["tracks"]["items"]:
print(item["artists"][0]["name"])
print(item["name"])
print(item["id"])
api_song = item["name"]
api_song = re.sub("\t", "", api_song)
print(api_song)
song_id = item["id"]
print(song_id)
song_ids.append(song_id)
print(song_ids)
playlist_input(playlist_id, song_ids)

def playlist_input(playlist_id, song_ids):
ST = Spotify_token(username)
token = ST.set()
if token:
sp = spotipy.Spotify(auth=token)
sp.trace = False
results = sp.user_playlist_add_tracks(username, playlist_id, song_ids)
print(results)
else:
print("Can't get token for", username)

if __name__ == '__main__':
artist = input("検索したいアーティスト名を入力して下さい")
song = input("次にアーティストの楽曲名を入力して下さい")
first_input = (artist, song)
playlist_print()

 

 

なお、後半のSpotifyとの接続は以下の記事を参考にしました。

 

sakanaaas.hateblo.jp

 

現状、以下の現象を確認しています。

・DBに未収録の楽曲はプレイリストが出来ない

・入力を間違えるとエラーになる

Spotifyに配信されていない楽曲が混ざると、出来るプレイリストが想定と違う

 

なお、今後はDBでは無くAPIを直接参照するように改修します。また、アーティスト名を入れたあとに曲名を表示されるようにします。

 

フロントの作業は難しい

最近、フロント側のビュー画面の改修に関する仕事を引き受けているので雑感です。

 

ビュー部分はhtmlのタグのコーディングなので、ほかの言語と違いエラー文が出てきません。そのため、レイアウト崩壊が起きると、どこをどのように修正したら良いのか良く分からなくなります。

 

直感的には「こうしたい」という思いはあるけれど、それをどう実現させるのかが分からないという感じですね。

 

地道に本を使って頑張りたいと思います。

 

HTML5 & CSS3 デザインレシピ集

HTML5 & CSS3 デザインレシピ集

 

 

「Against」のPVを見て

先日、乃木坂46の「Against」のPVが公開されました。

(※以下のリンクは2018年4月25日のCD発売後リンク切れとなっている可能性があります。)

 


乃木坂46 『Against』

 

 1期生だけのPVですが、最後の「生生星」体制の曲となっています。生生星とは、1stシングル「ぐるぐるカーテン」から4thシングル「君の名は希望」まで続いた体制で(2ndシングル「おいでシャンプー」を除く)フロント3人の名前(生田絵梨花生駒里奈星野みなみ)を取ってそう呼ばれています。

 

デビュー時は3人とも中高生でしたが、最年少の星野みなみさんも20歳になりすっかり大人の雰囲気を出しています。

 

自分自身は生田さんをずっと推してきたので、生生星の並びがもう見られないのは寂しさがあります。

 

卒業記念のセンターを除き、センター経験者が初めて卒業することになった乃木坂46は大きな転換点を迎えている感じがします。シンクロニシティ以後どうなっていくのか、今後も注目していきたいと思います。

環境が変わって

4月よりがらっと環境が変わりましたので、備忘録的に書いておきます。

 

・受託には期日しか無いが、自社サービスの場合そうでないものもある(急ぎでは無いが、重要でも無い改修)

・同じ言語にじっくり取り組める(受託はプロジェクトが終わればそれまで)

・やっぱり都心部は色んな店がある

 

落ち着いたら、また勉強会に行ってレポート書いてみます。

「アイノラ交響楽団『第15回定期演奏会 “シベリウスと伊福部 昭の世界 ~ 北方の舞踏 ~”』」に行ってきました。

4月8日に「アイノラ交響楽団『第15回定期演奏会シベリウスと伊福部 昭の世界 ~ 北方の舞踏 ~”』」があったので行ってきました。

 

ainola.jp

 

マチュア・オーケストラのコンサートながら、フィンランド大使館等の後援が付いていたので気になって行ってみました。

 

曲目は

伊福部昭:マリンバとオーケストラのためのラウダ・コンチェルタータ 

シベリウス:音詩「エン・サガ」

シベリウス:交響曲第3番 ハ長調 作品52

でした。また、アンコールとして

シベリウス:舞踏間奏曲「パンとエコー」作品53a

シベリウス:アンダンテ・フェスティーヴォ

が演奏されました。

 

伊福部昭は日本を代表する作曲家で、映画「ゴジラ」のテーマ曲が大変有名です。前半はやや迫力に欠けるところがありましたが、終盤に掛けては非常に聴き応えがあったと思います。休憩を挟んで、フィンランドを代表する作曲家のシベリウスの「エン・サガ」と交響曲第3番の演奏がありました。自分としては、一番「エン・サガ」が印象に残りました。


エン・サガ

この曲は今まで触れた事がありませんでしたが、今後自分のお気に入り曲の1つとなる気がします。

 

また、楽器を再開しようと思いました。

「Google Homeを遊びたおす会」に行ってきました

3月28日に「Google Homeを遊びたおす会」があったので行ってきました。

 

kotodama.connpass.com

 

connpassのグループでは「スマートスピーカーを楽しむ会」にくくられていましたが、今回はいつもと主催者が異なっていました。

 

・「Google Homeでつくるスマートホーム」田中みそさん

speakerdeck.com


Google Homeでつくるスマートホーム DEMO

今回はこの方が主催されていました。本発表で注目すべきと思ったのが、ある日勝手にGoogle Homeが動作した形跡があり不正アクセスを疑って調べたところ、寝言でGoogle Homeが動作してしまったという事でした。寝言で動作する事は想定されていなかったと思います。ただ、実際に起きてしまった以上改善が必要になると思います。個人的には、夜間のスリープモードの実装が必要かなと思います。

 

・「(Office 365連携に関する発表)」Microsoft社 大田さん

当初はちょまどさんの発表の1コーナーのみの予定でしたが、急にちょまどさんのPCにトラブルがはっせいしたため、時間つなぎとして登壇しました。予定外の登壇でしたが、しっかりとお話しされていたのが印象的でした。自分もこのような状況になっても対応出来る人間になりたいと思いました。

 

・「Google Home 用のお遊びアプリをMicrosoft Azure使って作ってみた」Microsoft テクニカルエバンジェリスト ちょまど(千代田まどか)さん

5分間でしたがしっかり発表されていました。内容は前のイベントと同じだったと思います。

 

・「Actions on Googleでできること」グーグル パートナーデベロッパーアドボケイト 山口能迪さん

goo.gl

Googleの方の講演でした。結構、スマートスピーカー系の勉強会ではIFTTT連携に関するお話しが多い(本イベントでもあった)ですが、IFTTT連携を使わなくてもActions on Googleを使えば解決するというお話しでした。自分自身としてはIFTTT連携という事ばかり考えていましたが、違うアプローチを知ったという点では有用であると思います。

 

・「Dialogflow tips」fishさん

www.slideshare.net

Dialogflowを用いたスマートスピーカーのスキル開発に関するお話しでした。

 

 

懇親会では、ちょまどさんといつもの「スマートスピーカー勉強会」の主催者の方とお話し出来ました。

 

当初は、音楽プレイリスト生成のスマートスピーカーのスキル作成を目指してこの勉強会に参加しましたが、SpotifyAPIで大苦戦してしまい、いつの間にかスキル生成の部分は停滞気味になってしまいました。Google play musicをいつも使っているので、Spotifyで提供しているようなAPIGoogleでも出れば使うかなと思っています。それとも、全く別のサードパーティーAPIを提供するのか判りませんがいずれにせよ、音楽系のAPIの充実が図られる事を望みます。あとは、音楽系とレコメンデーション、スマートスピーカーのミックス的な話も聞いてみたいかなという感じです。

 


Google Homeを遊びたおす会①(Google Homeでつくるスマートホーム by 田中みそ)