Mthrfkr commited on
Commit
240688f
verified
1 Parent(s): fc11758

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +140 -65
app.py CHANGED
@@ -1,8 +1,11 @@
1
 
 
2
  import requests
 
3
  import time
4
- from collections import deque
5
- from datetime import datetime, timedelta
 
6
 
7
  # Lista de credenciales de API de Spotify
8
  client_ids =[
@@ -30,11 +33,8 @@ client_secrets = [
30
  '9fdfa58ea0a94ce7a0cb34fa19fb7d74'
31
  ]
32
  current_api_index = 0
33
- session = requests.Session()
34
-
35
- # Registro de peticiones en los 煤ltimos 60 minutos
36
- request_log = deque()
37
 
 
38
  def obtener_token(client_id, client_secret):
39
  print(f"Obteniendo token de Spotify con client_id: {client_id}")
40
  url = 'https://accounts.spotify.com/api/token'
@@ -48,71 +48,146 @@ def obtener_token(client_id, client_secret):
48
  print(f"Error al obtener token para client_id: {client_id}, status_code: {response.status_code}, response: {response.text}")
49
  return None
50
 
51
- def cerrar_y_reiniciar_sesion():
52
- global session
53
- if session:
54
- session.close()
55
- print("Sesi贸n cerrada.")
56
- session = requests.Session()
57
- print("Nueva sesi贸n creada.")
58
-
59
  def cambiar_api_key():
60
  global current_api_index
61
  current_api_index = (current_api_index + 1) % len(client_ids)
62
  print(f"Cambiando a la siguiente API Key, 铆ndice actual: {current_api_index}")
63
- return client_ids[current_api_index], client_secrets[current_api_index]
64
-
65
- def obtener_nuevo_token():
66
- cerrar_y_reiniciar_sesion()
67
- client_id, client_secret = cambiar_api_key()
68
- token = obtener_token(client_id, client_secret)
69
- print(f"Nuevo token obtenido: {token}")
70
- return token
71
-
72
- def registrar_peticion():
73
- ahora = datetime.now()
74
- request_log.append(ahora)
75
- # Remover peticiones que tienen m谩s de 60 minutos
76
- while request_log and (ahora - request_log[0]) > timedelta(minutes=60):
77
- request_log.popleft()
78
-
79
- def realizar_solicitud(url, params, token):
80
- headers = {'Authorization': f'Bearer {token}'}
81
- response = session.get(url, headers=headers, params=params)
82
- registrar_peticion()
83
- return response
84
-
85
- def realizar_solicitud_con_reintento(url, params):
86
- token = obtener_nuevo_token()
87
- espera = 1
88
-
89
- while True:
90
- response = realizar_solicitud(url, params, token)
91
- print(f"Solicitud realizada. C贸digo de estado: {response.status_code}")
92
-
93
- if response.status_code == 429:
94
- retry_after = int(response.headers.get('Retry-After', espera))
95
- espera *= 2 # Incremento exponencial
96
- print(f"L铆mite de peticiones alcanzado, esperando {retry_after} segundos antes de reintentar...")
97
- time.sleep(retry_after)
98
- token = obtener_nuevo_token() # Obtener un nuevo token despu茅s de esperar
99
- else:
100
- return response
101
 
102
- # Ejemplo de uso
103
- def main():
104
  url = 'https://api.spotify.com/v1/search'
105
- params = {'q': 'rancheras', 'type': 'playlist', 'limit': 40}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
106
 
107
- print("Realizando primera solicitud...")
108
- response = realizar_solicitud_con_reintento(url, params)
109
- print("Respuesta de la primera solicitud:", response.json())
110
 
111
- # Simular cambio de API key despu茅s de recibir un c贸digo 429
112
- if response.status_code == 429:
113
- print("L铆mite de peticiones alcanzado, cambiando API key y realizando una nueva solicitud...")
114
- response = realizar_solicitud_con_reintento(url, params)
115
- print("Respuesta de la segunda solicitud:", response.json())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
 
117
- if __name__ == "__main__":
118
- main()
 
 
 
 
 
 
 
 
 
 
 
 
1
 
2
+ import gradio as gr
3
  import requests
4
+ import pandas as pd
5
  import time
6
+ from tempfile import NamedTemporaryFile
7
+ from openpyxl import Workbook
8
+ import shutil
9
 
10
  # Lista de credenciales de API de Spotify
11
  client_ids =[
 
33
  '9fdfa58ea0a94ce7a0cb34fa19fb7d74'
34
  ]
35
  current_api_index = 0
 
 
 
 
36
 
37
+ # Funciones para Spotify
38
  def obtener_token(client_id, client_secret):
39
  print(f"Obteniendo token de Spotify con client_id: {client_id}")
40
  url = 'https://accounts.spotify.com/api/token'
 
48
  print(f"Error al obtener token para client_id: {client_id}, status_code: {response.status_code}, response: {response.text}")
49
  return None
50
 
 
 
 
 
 
 
 
 
51
  def cambiar_api_key():
52
  global current_api_index
53
  current_api_index = (current_api_index + 1) % len(client_ids)
54
  print(f"Cambiando a la siguiente API Key, 铆ndice actual: {current_api_index}")
55
+ return obtener_token(client_ids[current_api_index], client_secrets[current_api_index])
56
+
57
+ def manejar_errores(response):
58
+ if response.status_code == 429:
59
+ retry_after = int(response.headers.get('Retry-After', 1))
60
+ print(f"L铆mite de peticiones alcanzado. Reintentando en {retry_after} segundos.")
61
+ time.sleep(retry_after)
62
+ return True
63
+ return False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
 
65
+ def buscar_playlists_spotify(token, query, limit=50):
66
+ print("Buscando playlists en Spotify...")
67
  url = 'https://api.spotify.com/v1/search'
68
+ headers = {'Authorization': f'Bearer {token}'}
69
+ playlists = []
70
+
71
+ try:
72
+ if limit <= 50:
73
+ params = {'q': query, 'type': 'playlist', 'limit': limit}
74
+ response = requests.get(url, headers=headers, params=params)
75
+ if manejar_errores(response):
76
+ token = cambiar_api_key()
77
+ response = requests.get(url, headers={'Authorization': f'Bearer {token}'}, params=params)
78
+ playlists.extend(response.json().get('playlists', {}).get('items', []))
79
+ else:
80
+ offset = 0
81
+ while limit > 0:
82
+ params = {'q': query, 'type': 'playlist', 'limit': min(50, limit), 'offset': offset}
83
+ response = requests.get(url, headers=headers, params=params)
84
+ if manejar_errores(response):
85
+ token = cambiar_api_key()
86
+ response = requests.get(url, headers={'Authorization': f'Bearer {token}'}, params=params)
87
+ playlists.extend(response.json().get('playlists', {}).get('items', []))
88
+ limit -= min(50, limit)
89
+ offset += 50
90
+ time.sleep(5) # Pausa de 5 segundos entre las solicitudes para evitar el l铆mite de tasa
91
+ except Exception as e:
92
+ print(f"Error al buscar playlists: {e}")
93
 
94
+ return [{'playlist_id': playlist['id'], 'playlist_name': playlist['name']} for playlist in playlists]
 
 
95
 
96
+ def obtener_canciones_playlist_spotify(token, playlist_id, playlist_name):
97
+ print(f"Obteniendo canciones de la playlist {playlist_id} ({playlist_name}) de Spotify...")
98
+ url = f'https://api.spotify.com/v1/playlists/{playlist_id}/tracks'
99
+ headers = {'Authorization': f'Bearer {token}'}
100
+ canciones = []
101
+
102
+ try:
103
+ response = requests.get(url, headers=headers)
104
+ if manejar_errores(response):
105
+ token = cambiar_api_key()
106
+ response = requests.get(url, headers={'Authorization': f'Bearer {token}'})
107
+ if response.status_code == 200:
108
+ tracks = response.json().get('items')
109
+ for item in tracks:
110
+ track = item.get('track')
111
+ if track:
112
+ audio_features = obtener_caracteristicas_audio(token, track['id'])
113
+ canciones.append({
114
+ 'playlist_name': playlist_name,
115
+ 'artista': track['artists'][0]['name'] if track['artists'] else 'Desconocido',
116
+ 'titulo': track['name'],
117
+ 'isrc': track['external_ids'].get('isrc', 'No disponible'),
118
+ 'popularity': track.get('popularity', 'No disponible'),
119
+ 'valence': audio_features.get('valence', 'No disponible'),
120
+ 'danceability': audio_features.get('danceability', 'No disponible'),
121
+ 'energy': audio_features.get('energy', 'No disponible'),
122
+ 'tempo': audio_features.get('tempo', 'No disponible'),
123
+ 'speechiness': audio_features.get('speechiness', 'No disponible'),
124
+ 'instrumentalness': audio_features.get('instrumentalness', 'No disponible'),
125
+ 'duration': track.get('duration_ms', 'No disponible'),
126
+ 'release_year': track.get('album', {}).get('release_date', 'No disponible').split('-')[0] if track.get('album', {}).get('release_date') else 'No disponible',
127
+ 'record_label': obtener_record_label_spotify(track['album']['id'], token)
128
+ })
129
+ except Exception as e:
130
+ print(f"Error al obtener canciones de la playlist: {e}")
131
+
132
+ return canciones
133
+
134
+ def obtener_caracteristicas_audio(token, track_id):
135
+ url = f'https://api.spotify.com/v1/audio-features/{track_id}'
136
+ headers = {'Authorization': f'Bearer {token}'}
137
+ response = requests.get(url, headers=headers)
138
+ if manejar_errores(response):
139
+ token = cambiar_api_key()
140
+ response = requests.get(url, headers={'Authorization': f'Bearer {token}'})
141
+ return response.json() if response.status_code == 200 else {}
142
+
143
+ def obtener_record_label_spotify(album_id, token):
144
+ url = f'https://api.spotify.com/v1/albums/{album_id}'
145
+ headers = {'Authorization': f'Bearer {token}'}
146
+ response = requests.get(url, headers=headers)
147
+ if manejar_errores(response):
148
+ token = cambiar_api_key()
149
+ response = requests.get(url, headers={'Authorization': f'Bearer {token}'})
150
+ album_info = response.json() if response.status_code == 200 else {}
151
+ return album_info.get('label', 'No disponible')
152
+
153
+ # Funci贸n principal de la interfaz
154
+ def interface(project_name, query, num_spotify_playlists=50):
155
+ # Obtener tokens y claves
156
+ token_spotify = obtener_token(client_ids[current_api_index], client_secrets[current_api_index])
157
+ playlists_spotify = buscar_playlists_spotify(token_spotify, query, num_spotify_playlists)
158
+ canciones_spotify = []
159
+ for playlist in playlists_spotify:
160
+ songs = obtener_canciones_playlist_spotify(token_spotify, playlist['playlist_id'], playlist['playlist_name'])
161
+ canciones_spotify.extend(songs)
162
+ time.sleep(1) # Pausa de 1 segundo entre la obtenci贸n de canciones para evitar el l铆mite de tasa
163
+
164
+ # Crear DataFrame
165
+ df = pd.DataFrame(canciones_spotify)
166
+ df.rename(columns={'isrc': 'ISRCs'}, inplace=True)
167
+
168
+ # Ordenar por popularidad
169
+ df.sort_values(by=['popularity'], ascending=False, inplace=True)
170
+
171
+ # Guardar DataFrame en un archivo Excel
172
+ tmpfile = NamedTemporaryFile(delete=False, suffix='.xlsx')
173
+ df.to_excel(tmpfile.name, index=False)
174
+
175
+ # Renombrar el archivo con el nombre del proyecto
176
+ project_file_name = f"{project_name}.xlsx"
177
+ shutil.move(tmpfile.name, project_file_name)
178
+
179
+ return df, project_file_name # Devuelve el DataFrame y el enlace al archivo Excel
180
 
181
+ # Configuraci贸n de Gradio
182
+ iface = gr.Interface(
183
+ fn=interface,
184
+ inputs=[
185
+ gr.Textbox(label="Nombre del Proyecto"),
186
+ gr.Textbox(label="Keywords - Palabras Clave para tu b煤squeda"),
187
+ gr.Number(label="Numero de Playlists que vamos a buscar con estas Keywords", value=50, minimum=1, maximum=1000)
188
+ ],
189
+ outputs=[gr.Dataframe(), gr.File(label="Download Excel")],
190
+ title="Spotify Playlist Fetcher",
191
+ description="Enter a search query to fetch playlists and their songs from Spotify. Client credentials are pre-configured."
192
+ )
193
+ iface.launch()