| | import gradio as gr |
| | import requests |
| | import pandas as pd |
| | from tempfile import NamedTemporaryFile |
| | import shutil |
| | import os |
| |
|
| | |
| | def obtener_token(client_id, client_secret): |
| | print("Obteniendo token de Spotify...") |
| | url = 'https://accounts.spotify.com/api/token' |
| | headers = {'Content-Type': 'application/x-www-form-urlencoded'} |
| | payload = {'grant_type': 'client_credentials'} |
| | response = requests.post(url, headers=headers, data=payload, auth=(client_id, client_secret)) |
| | return response.json().get('access_token') |
| |
|
| | def buscar_playlists_spotify(token, query, limit=50): |
| | print("Buscando playlists en Spotify...") |
| | url = 'https://api.spotify.com/v1/search' |
| | headers = {'Authorization': f'Bearer {token}'} |
| | playlists = [] |
| |
|
| | if limit <= 50: |
| | params = {'q': query, 'type': 'playlist', 'limit': limit} |
| | response = requests.get(url, headers=headers, params=params) |
| | if response.status_code != 200: |
| | print(f"Error en la solicitud a Spotify: {response.status_code}") |
| | print(response.json()) |
| | return [] |
| | items = response.json().get('playlists', {}).get('items', []) |
| | items = [item for item in items if item is not None] |
| | playlists.extend(items) |
| | else: |
| | offset = 0 |
| | while limit > 0: |
| | params = {'q': query, 'type': 'playlist', 'limit': min(50, limit), 'offset': offset} |
| | response = requests.get(url, headers=headers, params=params) |
| | if response.status_code != 200: |
| | print(f"Error en la solicitud a Spotify: {response.status_code}") |
| | print(response.json()) |
| | break |
| | items = response.json().get('playlists', {}).get('items', []) |
| | items = [item for item in items if item is not None] |
| | playlists.extend(items) |
| | fetched = len(items) |
| | limit -= fetched |
| | offset += fetched |
| | if fetched == 0: |
| | break |
| |
|
| | valid_playlists = [] |
| | for playlist in playlists: |
| | if playlist is not None and 'id' in playlist and 'name' in playlist: |
| | valid_playlists.append({ |
| | 'playlist_id': playlist['id'], |
| | 'playlist_name': playlist['name'] |
| | }) |
| | return valid_playlists |
| |
|
| | def obtener_canciones_playlist_spotify(token, playlist_id, playlist_name): |
| | print(f"Obteniendo canciones de la playlist {playlist_id} de Spotify...") |
| | url = f'https://api.spotify.com/v1/playlists/{playlist_id}/tracks' |
| | headers = {'Authorization': f'Bearer {token}'} |
| | response = requests.get(url, headers=headers) |
| | canciones = [] |
| | if response.status_code == 200: |
| | tracks = response.json().get('items', []) |
| | for item in tracks: |
| | track = item.get('track') |
| | if track: |
| | artista_info = {} |
| | if track['artists']: |
| | artista_info = obtener_info_artista(track['artists'][0]['id'], token) |
| | record_label = obtener_record_label_spotify(track['album']['id'], token) if track.get('album') else 'No disponible' |
| | canciones.append({ |
| | 'playlist_name': playlist_name, |
| | 'artista': track['artists'][0]['name'] if track['artists'] else 'Desconocido', |
| | 'titulo': track['name'], |
| | 'isrc': track.get('external_ids', {}).get('isrc', 'No disponible'), |
| | 'popularity': track.get('popularity', 'No disponible'), |
| | 'track_id': track['id'], |
| | 'link': track.get('external_urls', {}).get('spotify', 'No disponible'), |
| | 'record_label': record_label, |
| | 'source': 'Spotify', |
| | 'genero_artista': ', '.join(artista_info.get('genres', [])) if artista_info else 'No disponible' |
| | }) |
| | return canciones |
| |
|
| | def obtener_caracteristicas_audio(token, track_ids): |
| | print("Obteniendo características de audio para las pistas...") |
| | url = f'https://api.spotify.com/v1/audio-features' |
| | headers = {'Authorization': f'Bearer {token}'} |
| | params = {'ids': ','.join(track_ids)} |
| | response = requests.get(url, headers=headers, params=params) |
| | return response.json().get('audio_features', []) if response.status_code == 200 else [] |
| |
|
| | def obtener_record_label_spotify(album_id, token): |
| | url = f'https://api.spotify.com/v1/albums/{album_id}' |
| | headers = {'Authorization': f'Bearer {token}'} |
| | response = requests.get(url, headers=headers) |
| | return response.json().get('label', 'No disponible') if response.status_code == 200 else 'No disponible' |
| |
|
| | def obtener_info_artista(artista_id, token): |
| | url = f'https://api.spotify.com/v1/artists/{artista_id}' |
| | headers = {'Authorization': f'Bearer {token}'} |
| | response = requests.get(url, headers=headers) |
| | return response.json() if response.status_code == 200 else {} |
| |
|
| | def interface(query, num_spotify_playlists=50, project_name="Proyecto"): |
| | client_id = os.getenv('Spotify_ID') |
| | client_secret = os.getenv('Spotify_client') |
| |
|
| | token_spotify = obtener_token(client_id, client_secret) |
| | if not token_spotify: |
| | raise gr.Error("Failed to obtain Spotify token. Check client ID and secret.") |
| |
|
| | playlists_spotify = buscar_playlists_spotify(token_spotify, query, num_spotify_playlists) |
| | canciones_spotify = [] |
| | track_ids = [] |
| | for playlist in playlists_spotify: |
| | songs = obtener_canciones_playlist_spotify(token_spotify, playlist['playlist_id'], playlist['playlist_name']) |
| | canciones_spotify.extend(songs) |
| | track_ids.extend([song['track_id'] for song in songs if song.get('track_id')]) |
| |
|
| | audio_features_list = obtener_caracteristicas_audio(token_spotify, track_ids) |
| | audio_features_dict = {af['id']: af for af in audio_features_list if af} |
| |
|
| | for song in canciones_spotify: |
| | audio_features = audio_features_dict.get(song['track_id'], {}) |
| | song.update({ |
| | 'valence': audio_features.get('valence', 'No disponible'), |
| | 'danceability': audio_features.get('danceability', 'No disponible'), |
| | 'energy': audio_features.get('energy', 'No disponible'), |
| | 'tempo': audio_features.get('tempo', 'No disponible'), |
| | 'speechiness': audio_features.get('speechiness', 'No disponible'), |
| | 'instrumentalness': audio_features.get('instrumentalness', 'No disponible') |
| | }) |
| |
|
| | df = pd.DataFrame(canciones_spotify) |
| | df.rename(columns={'isrc': 'ISRCs'}, inplace=True) |
| | df.sort_values(by=['popularity'], ascending=False, inplace=True) |
| |
|
| | with NamedTemporaryFile(delete=False, suffix='.xlsx') as tmpfile: |
| | df.to_excel(tmpfile.name, index=False) |
| | project_filename = f"{project_name}.xlsx" |
| | shutil.move(tmpfile.name, project_filename) |
| | return df, project_filename |
| |
|
| | iface = gr.Interface( |
| | fn=interface, |
| | inputs=[ |
| | gr.Textbox(label="Keywords o Títulos de Playlists"), |
| | gr.Number(label="Número de playlists que queremos buscar", value=50, minimum=1, maximum=1000), |
| | gr.Textbox(label="Nombre del proyecto") |
| | ], |
| | outputs=[gr.Dataframe(), gr.File(label="Descargar Excel")], |
| | title="Busca Playlists con Keywords", |
| | description="Ingresa tu búsqueda para encontrar playlists en Spotify con esas palabras en sus títulos." |
| | ) |
| | iface.launch() |