Nota: Doy una advertencia ⚠️ de que no soy programador como profesión, por lo que los términos que usaré no serán específicos.
Repaso rapidín
Spotipy es una librería de Python que nos facilita las peticiones y el manejo de la API de Spotify. Para poder usar la librería (y por ende la API), además de instalarla, hay que registrarnos como Developer y crear una App, para que de esa manera tengamos nuestras claves (Client ID y Client Secret). Para mayores detalles, te invito a leer el primer artículo de esta serie:
Spotipy: ¿Qué es? ¿Cómo se usa? ¿Con qué se come?
Isaac Arroyo ・ May 24 '22 ・ 4 min read
Introducción informal
En este tutorial vamos a indagar un poco más en el código, como funciona cada parte, explicar las funciones que usaremos así como entender como son los datos que vamos a recibir y como vamos a exportarlos como un archivo csv.
Continuando dónde lo dejamos y lo que teníamos pendiente, vamos a ir por partes.
Entrar a Spotify
A estas líneas de código les llamo Pedir permiso. Lo que estamos haciendo primero es importar la librería de Spotipy asi como nuestro manager de credenciales o claves.
import spotipy
from spotipy.oauth2 import SpotifyClientCredentials # Manager de credenciales
Seguidamente, a ese manager le damos nuestro Client ID y Client Secret
clientID = 'CLIENT_ID'
clientSecret = 'CLIENT_SECRET'
client_credential_manager = SpotifyClientCredentials(client_id=clientID, client_secret=clientSecret)
Con client_credential_manager
ya podemos "entrar a Spotify", es decir, ya tenemos los permisos para pedir datos
sp = spotipy.Spotify(client_credentials_manager=client_credential_manager)
Anatomía de los datos
Vamos a entender que es lo que obtenemos cuando pedimos las canciones de un album. Seguiremos usando el URI del album ✨ "Harry's House" por Harry Styles ✨
La función a usar es album_tracks()
, donde el parámetro a dar es el URI del album la respuesta que obtenemos es un diccionario de características del album
uri_harrys_house = 'spotify:album:5r36AJ6VOJtp00oxSkBZ5h'
dict_harrys_house = sp.album_tracks(uri_harrys_house)
print(dict_harrys_house.keys())
# OUTPUT
# dict_keys(['href', 'items', 'limit', 'next', 'offset', 'previous', 'total'])
A nosotros nos interesa la llave o key llamada 'limit'
, el item o elemento de esa llave es una lista que contiene las canciones:
list_harrys_house_canciones = dict_harrys_house['items']
print(f"El album tiene {len(list_harrys_house_canciones)} canciones")
# OUTPUT
# El album tiene 13 canciones
Cada elemento de esa lista es una canción cuya información esta almacenada en un diccionario:
dict_primera_cancion = list_harrys_house_canciones[0]
print(dict_primera_cancion.keys())
# OUTPUT
# dict_keys(['artists', 'available_markets', 'disc_number', 'duration_ms', 'explicit', 'external_urls', 'href', 'id', 'is_local', 'name', 'preview_url', 'track_number', 'type', 'uri'])
Las llaves que nos interesan para crear nuestro conjunto de datos son 'name'
, 'uri'
y 'duration_ms'
. Para ello vamos a crear una lista y almacenar esa información, para ello tendremos que iterar sobre la lista de canciones:
list_names_songs = []
list_uri_songs = []
list_duration_ms = []
for cancion in list_harrys_house_canciones:
list_names_songs.append(cancion['name'])
list_uri_songs.append(cancion['uri'])
list_duration_ms.append(cancion['duration_ms'])
Extraer las audio features
Con una lista de URIs, extraer las audio features es mucho más fácil.
La función que usaremos es audio_features()
la cual toma como parámetros la URI como una string (str
) o una lista de URIs, como lo que tenemos nosotros. Lo que nos va a regresar es una lista... de diccionarios.
list_audio_features_canciones = sp.audio_features(list_uri_songs)
Nota importante: Existe un límite de peticiones y es 100, es decir, el número máximo de URIs en una lista es de 100.
¿Qué llaves tienen los diccionarios que son parte de la list_audio_features_canciones
?
dict_primer_elemento_list_audio_features = list_audio_features_canciones[0]
print(dict_primer_elemento_list_audio_features.keys())
# OUTPUT
# dict_keys(['danceability', 'energy', 'key', 'loudness', 'mode', 'speechiness', 'acousticness', 'instrumentalness', 'liveness', 'valence', 'tempo', 'type', 'id', 'uri', 'track_href', 'analysis_url', 'duration_ms', 'time_signature'])
LAS AUDIO FEATURES, pero...
¿Que son las audio features?
Son propiedades que Spotify le da a las canciones, la cuales pueden ser muy técnicas (como el promedio de decibeles que emite la canción) así como un poco más elaboradas (como la energía de la canción). La lista es la siguiente:
Nombre | Descripción | Rango y tipo de dato |
---|---|---|
acousticness |
Es el nivel de confianza de que la canción sea acústica | va de 0 a 1 (float ) |
danceability |
Indica que tan bailable es una canción basándose en diferentes elementos musicales como tempo, ritmo, beat, entre otros. | va de 0 a 1 (float ) |
duration_ms |
El tiempo de duración de la canción en milisegundos. | float |
energy |
Valores altos de energía representan canciones rápidas, activas y ruidosas, de lo contrario la energía es baja. Toma en cuenta aspectos como rango dinámico, timbre, volumen percibido, entre otros. | va de 0 a 1 (float ) |
instrumentalness |
Predice si la canción no contiene vocales. Entre más instrumental sea la canción, más alto el valor de este atributo. Canciones del género de rap tienen un bajo valor. | va de 0 a 1 (float ) |
liveness |
Este valor indica la presencia de audiencia. Entre más audiencia detecta, más alto su valor y mayor probabilidad es de que la canción haya sido en vivo | va de 0 a 1 (float ) |
loudness |
La presencia de riudo en decibeles (dB), la amplitud de las ondas de la canción. Este valor es el promedio de la canción. | va de -60 a 0] (float ) |
speechiness |
Detecta la presencia de palabras. Muy altos niveles indican audiolibros, podcasts, entre otros; altos niveles pueden ser canciones del género rap, valores bajos indican poco aporte de palabras en la canción. | va de 0 a 1 (float ) |
tempo |
Los Beats Per Minute (BPM), la velocidad o el paso de una canción. | (float ) |
valence |
Describe la positividad de la canción. Valores altos indican mayor positividad (alegría, euforia, ánimos) y valores bajos indican más negatividad (tristeza, depresión, enojo). | va de 0 a 1 (float ) |
key |
Clasifica el pitch o las notas de la canción. Canciones con bajo pitch suenan más graves, mientras que con alto pitch suenan más agudos. Cuando no se conoce el valor se marca -1. | va de -1 a 11 (categoria) |
time_signature |
La notación convencional que indica cuantos beats hay en cada bar. Se escriben únicamente los numeradores, ya que el denominador es 4. Por ejemplo, "4/4" o "7/4" | va de 1 a 7 (categoria) |
mode |
Indica la modalidad (mayor o menor) de una canción, el tipo de escala del que se deriva su contenido melódico. La mayor se representa con 1 y la menor con 0. | 0 y 1 (categoria) |
Crear un data frame
Ya que sabemos cuenta que ahora que son las audio features y como están guardadas, es tiempo de llevar los valores de la lista de diccionarios a un pandas.DataFrame
. Para ello ejecutaremos las siguientes líneas de código:
1 - Vamos a crear un diccionario de listas vacías. Donde cada llave es un audio feature.
dict_canciones_caracteristicas = dict(
# Bueno, name no es lista vacia
# pero las demás si
name = list_names_songs,
danceability = [],
energy = [],
key = [],
loudness = [],
mode = [],
speechiness = [],
acousticness = [],
instrumentalness = [],
liveness = [],
valence = [],
tempo = [],
duration_ms = []
)
2 - Vamos a iterar a través de cada elemento (será un diccionario) de list_audio_features_canciones
. En esa iteración, vamos a iterar por las llaves de cada elemento y encontrar si alguna de ellas también está en nuestro diccionario (semi) vacío dict_canciones_caracteristicas
. Si la llave está, entonces se guarda ese audio feature de esa canción.
# Primera iteraciòn: a través de los elementos de la lista de audio features
for dict_audio_features_cancion in list_audio_features_canciones:
# Segunda iteración: a través de las llaves del diccionario
for llave in dict_audio_features_cancion:
# Revisamos si una de sus llaves esta en dict_canciones_caracteristicas
if llave in list(dict_canciones_caracteristicas.keys()):
# Si está, se guarda el audio feature en la llave correcta
dict_canciones_caracteristicas[llave].append(dict_audio_features_cancion[llave])
Con el diccionario lleno, es tiempo de volverlo un pandas.DataFrame
:
df = pd.DataFrame(dict_canciones_caracteristicas)
Y terminamos al exportarlo como un archivo csv:
df.to_csv("./harrys_house_spotify_audio_features.csv", index=False)
Conclusión y palabras finales
En este no tan corto tutorial, intenté ser lo más claro para que puedan extraer las características de las canciones del album de su artista favorito. Este proceso se puede repetir para playlist personales así como para playlist públicas.
Espero haber sido de ayuda. En los siguiente tutoriales veremos que hacer cuando son más de 100 canciones.
Para cualquier duda esta la sección de comentarios o mis DM en twitter (@unisaacarroyov) 🤓
Repositorio (jupyter notebook)
Da click aquí para poder ver la jupyter notebook de todo este proceso.
Discussion (2)
más de 100 canciones ?
Sip @carlospregunton , la API de Spotify solo te deja extraer 100 canciones por petición. Por lo que cuando son más, tienes que ir segmentando de 100 en 100 hasta el final.