Spotify w Pythonie, część 1: Przetwarzanie wstępne
W tym artykule zaczniemy wprowadzać Twoje dane Spotify do Pythona. To będzie pierwszy artykuł z serii artykułów o Spotify w Pythonie.
W tym artykule będę:
- Pokażę, jak przenieść dane ze Spotify do Pythona.
- Załaduj listę odtwarzania Zapisane utwory do ramki danych.
- Wydobądź funkcje audio ze wszystkich zapisanych utworów.
- Dodaj gatunek (grupę) do każdego utworu.
- Podaj mały wniosek i porozmawiaj o kolejnych krokach.
Na początek potrzebne są dane uwierzytelniające użytkownika Spotify API.
Aby to zrobić, musisz wykonać następujące kroki:
- Przejdź do panelu programisty Spotify (https://developer.spotify.com/dashboard/applications) i zaloguj się na swoje konto Spotify.
- Kliknij przycisk „Utwórz aplikację”, aby utworzyć nową aplikację Spotify.
- Podaj wymagane informacje dotyczące aplikacji, takie jak nazwa, opis i witryna internetowa. Możesz ustawić pole „Redirect URIs” na adres URL, którego chcesz użyć jako adresu URL przekierowania.
- Po utworzeniu aplikacji otrzymasz wartości „Client ID” i „Client Secret”.
- Upewnij się również, że ustawiłeś „Redirect URIs” w swojej aplikacji Spotify tak, aby pasowało do podanego adresu URL „REDIRECT” .
Poświadczenia zapisałem w następujący sposób w pliku „credentials”:
UŻYTKOWNIK = „…”
CID = „…”
SEKRET = „…”
PRZEKIEROWANIE = „…”
W notatniku Jupiter można uruchomić następujący kod w celu utworzenia tokenu użytkownika przy użyciu poświadczeń:
#importing libraries
import credentials
import spotipy
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
# Retrieve user credentials from separate file
user = credentials.USER
cid = credentials.CID
secret = credentials.SECRET
redirect_uri = credentials.REDIRECT
# Define scope of access
scope = 'user-library-read' # user-library-read, user-read-recently-played
# Prompt for user token using credentials
token = spotipy.util.prompt_for_user_token(user, scope, client_id=cid, client_secret=secret, redirect_uri=redirect_uri)
# Create Spotify token and check if successful
if token:
sp = spotipy.Spotify(auth=token)
print('Token created for', user)
else:
print("Can't get token for", user)
# User data
user_data = sp.current_user()
print('My data:')
print('Name:', user_data['display_name'])
print('Followers:', user_data['followers']['total'])
print('Link:', user_data['external_urls']['spotify'])
Pobieranie zapisanych utworów z biblioteki Spotify
W poniższym kodzie zapisane utwory są pobierane z biblioteki Spotify. Piosenki są przechowywane w ramce danych pandy.
# Function to get all saved tracks
def get_saved_tracks():
results = sp.current_user_saved_tracks()
tracks = []
while results['next']:
tracks.extend(results['items'])
results = sp.next(results)
return tracks
# Converting tracks to dataframe
def deconstruct_tracks(tracks):
saved_tracks = []
for track in tracks:
saved_track = {
'added_at': track['added_at'],
'id': track['track']['id'],
'name': track['track']['name'],
'popularity': track['track']['popularity'],
'uri': track['track']['uri'],
'artist': track['track']['artists'][0]['name'],
'album': track['track']['album']['name'],
'release_date': track['track']['album']['release_date'],
'duration_ms': track['track']['duration_ms']
}
saved_tracks.append(saved_track)
return pd.DataFrame(saved_tracks)
tracks_called = get_saved_tracks()
tracklist = deconstruct_tracks(tracks_called)
#%%
tracklist.head(10)
Ładowanie funkcji audio
Aby przeprowadzić eksploracyjną analizę zapisanych utworów w Spotify, należy najpierw uzyskać pewne funkcje z utworów. Cechy, które zostaną wyprowadzone to:
Akustyka : Wartość od 0,0 do 1,0 wskazująca, czy ścieżka jest akustyczna, przy czym 1,0 oznacza wysokie zaufanie do natury akustycznej.
Danceability : Miara od 0,0 do 1,0 opisująca, jak utwór jest odpowiedni do tańca, w oparciu o takie elementy, jak tempo, stabilność rytmu, siła uderzenia i regularność, gdzie 0,0 oznacza najmniej taneczny, a 1,0 najbardziej taneczny.
Energia : Wartość od 0,0 do 1,0 reprezentująca intensywność i aktywność utworu, przy czym energiczne utwory wydają się szybkie, głośne i hałaśliwe. Cechy percepcyjne, takie jak zakres dynamiki, postrzegana głośność, barwa, szybkość początku i entropia, przyczyniają się do tego atrybutu.
Instrumentalność : przewidywanie, czy utwór zawiera wokale, przy czym wartości bliższe 1,0 wskazują na większe prawdopodobieństwo braku wokalu. Wartości powyżej 0,5 zazwyczaj reprezentują ścieżki instrumentalne, z większą pewnością, gdy wartość zbliża się do 1,0.
Żywotność : wartość wskazująca obecność publiczności w nagraniu, przy czym wyższe wartości oznaczają większe prawdopodobieństwo występu na żywo. Wartość powyżej 0,8 sugeruje duże prawdopodobieństwo wystąpienia utworu na żywo.
Głośność : Ogólna głośność ścieżki w decybelach (dB), uśredniona dla całej ścieżki i przydatna do porównywania względnej głośności ścieżek. Wartości zwykle mieszczą się w zakresie od -60 do 0 dB.
Speechiness : Miara wskazująca na obecność wypowiadanych słów w utworze, z wartościami bliższymi 1,0 sugerującymi bardziej nagrania przypominające mowę. Wartości powyżej 0,66 opisują utwory składające się wyłącznie ze słów mówionych, podczas gdy wartości od 0,33 do 0,66 mogą wskazywać na mieszankę muzyki i mowy, w tym muzyki rap. Wartości poniżej 0,33 reprezentują głównie utwory muzyczne i niemowa.
Tempo : Ogólne szacunkowe tempo utworu w uderzeniach na minutę (BPM), wskazujące prędkość lub tempo muzyki.
Metrum : termin muzyczny określający liczbę uderzeń w każdym takcie lub takcie.
Valence : Wartość od 0,0 do 1,0 opisująca muzyczną pozytywność przekazywaną przez utwór, przy czym wysoka wartościowość wskazuje na więcej pozytywnych emocji, takich jak szczęście, a niska wartościowość wskazuje na więcej negatywnych emocji, takich jak smutek.
Tryb : Wskaźnik modalności (główny lub drugorzędny) utworu, gdzie 1 oznacza dur, a 0 reprezentuje drugorzędny.
Klucz : Oszacowany ogólny ton ścieżki odwzorowany na liczby całkowite przy użyciu standardowej notacji Pitch Class (np. 0 = C, 1 = C♯/D♭, 2 = D itd.).
Użyj poniższego kodu, aby uzyskać wszystkie te funkcje.
# Function to get all audio features of the saved tracks
def get_track_features(id):
metadata = sp.track(id)
features = sp.audio_features(id)
# metadata
id = metadata['id']
name = metadata['name']
album = metadata['album']['name']
artist = metadata['album']['artists'][0]['name']
release_date = metadata['album']['release_date']
length = metadata['duration_ms']
popularity = metadata['popularity']
# audio features
acousticness = features[0]['acousticness']
danceability = features[0]['danceability']
energy = features[0]['energy']
instrumentalness = features[0]['instrumentalness']
liveness = features[0]['liveness']
loudness = features[0]['loudness']
speechiness = features[0]['speechiness']
tempo = features[0]['tempo']
time_signature = features[0]['time_signature']
valence = features[0]['valence']
mode = features[0]['mode']
key = features[0]['key']
track = [name, album, artist, release_date, length, popularity, danceability, acousticness, danceability, energy,
instrumentalness, liveness, loudness, speechiness, tempo, time_signature, valence, mode, key]
return track
print("Function defined")
# Loop through each track id and get the tracks features
for i in range(len(tracklist)):
try:
track = get_track_features(tracklist['id'][i])
tracklist.loc[i, 'name'] = track[0]
tracklist.loc[i, 'album'] = track[1]
tracklist.loc[i, 'artist'] = track[2]
tracklist.loc[i, 'release_date'] = track[3]
tracklist.loc[i, 'length'] = track[4]
tracklist.loc[i, 'popularity'] = track[5]
tracklist.loc[i, 'danceability'] = track[6]
tracklist.loc[i, 'acousticness'] = track[7]
tracklist.loc[i, 'danceability'] = track[8]
tracklist.loc[i, 'energy'] = track[9]
tracklist.loc[i, 'instrumentalness'] = track[10]
tracklist.loc[i, 'liveness'] = track[11]
tracklist.loc[i, 'loudness'] = track[12]
tracklist.loc[i, 'speechiness'] = track[13]
tracklist.loc[i, 'tempo'] = track[14]
tracklist.loc[i, 'time_signature'] = track[15]
tracklist.loc[i, 'valence'] = track[16]
tracklist.loc[i, 'mode'] = track[17]
tracklist.loc[i, 'key'] = track[18]
# Save to df
tracklist.to_csv('tracklist.csv', index=False, encoding='utf-8')
except:
print(f"Error with track {i}")
pass
print(f"Features of {len(tracklist)} tracks extracted and saved to tracklist.csv")
Dostałem jeden błąd w jednej piosence, ponieważ tak naprawdę nie była to piosenka, ale 2-godzinny miks Kerri Chandler. Oczywiście nie jest możliwe wyznaczenie jednej wartości dla wszystkich tych cech audio. Ta „piosenka” nie przechodzi zatem do następnego etapu przetwarzania.
Gatunek muzyczny
Spotify API nie zapewnia żadnego gatunku z utworami. To jest coś, nad czym musimy popracować. Możemy to zrobić za pomocą interfejsu API, który może uzyskać powiązane gatunki każdego artysty i dołączyć je do każdego utworu.
# Add all genres of the artists to the dataframe
genres = []
for i in range(len(data)):
artist = data['artist'][i]
artist_id = sp.search(artist, type='artist')['artists']['items'][0]['id']
artist_genres = sp.artist(artist_id)['genres']
genres.append(artist_genres)
data['genres'] = genres
data.head(10)
# Transform the genre column to extract specific genres
data['genres'] = data['genres'].astype(str)
data['genres'] = data['genres'].str.replace('[', '')
data['genres'] = data['genres'].str.replace(']', '')
data['genres'] = data['genres'].str.replace("'", '')
data['genres'] = data['genres'].str.replace('"', '')
data.head(10)
# Search for predefined genres in the genre column
strings = ['pop', 'techno', 'house', 'disco', 'electronic',
'trance', 'hip hop', 'rap', 'r&b', 'soul', 'rock',
'metal', 'punk', 'jazz', 'blues', 'country', 'folk',
'reggae', 'classical', 'indie', 'funk']
for string in strings:
data.loc[data['genres'].str.contains(string), 'genre_group'] = string
data.head(10)
Policz dla każdego gatunku:
# Check how many tracks are in each genre group
data['genre_group'].value_counts()
# Count missing values
data['genre_group'].isnull().sum()
print(f"{data['genre_group'].isnull().sum()} tracks are missing a genre group")
# visualize the distribution of the genres
plt.figure(figsize=(15, 10))
sns.countplot(y='genre_group', data=data, order=data['genre_group'].value_counts().index)
for i, genre in enumerate(data['genre_group'].value_counts().index):
count = data['genre_group'].value_counts()[genre]
plt.text(count + 10, i, f'{count}', ha='left', va='center', color='black')
plt.title('Distribution of genres with counts')
plt.show()
Widać, że często jestem w nastroju funky i housy, słuchając jednocześnie muzyki indie, disco i soul.
Uwaga: w przypadku 291 utworów brakuje gatunku (grupy). Jest to problem, którym zajmiemy się w części 2 tej serii.
Następne kroki
Zapisz tę ramkę danych w pliku CSV:
data.to_csv('tracklist.csv', index=False, encoding='utf-8')
W kolejnych artykułach zajmę się:
- Wykonaj eksploracyjną analizę danych.
- Pokaż, jak przypisać gatunki piosenkom, które ich nie mają.
- Twórz listy odtwarzania z zapisanych utworów, w których Twoja muzyka jest automatycznie sortowana za pomocą uczenia maszynowego.
- Zautomatyzuj ten proces.
Notatnik jest dostępny na moim GitHubie:
Wielkie podziękowania dla Nilsa Jennissena i Gabriela Ronnó, z którymi pracowałem nad tym projektem. Pamiętaj, aby obserwować go na ich Medium i GitHub:
- https://medium.com/@nilsjennissen
- https://github.com/nilsjenn
- https://medium.com/@gabriel_renno
- https://github.com/GabrielRenno
Wspaniałą ilustrację wykonała Kateryna Malachkova. Koniecznie zajrzyjcie na jej Medium i Instagram!
- https://medium.com/@malachkovak
- https://instagram.com/ph_malachkova?igshid=ZjE2NGZiNDQ=
- https://github.com/rubentak
- https://www.linkedin.com/in/ruben-tak-665b66194/

![Czym w ogóle jest lista połączona? [Część 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































