diff --git a/Spotify Playlist Generator(Popular Tracks Analyzer).ipynb b/Spotify Playlist Generator(Popular Tracks Analyzer).ipynb new file mode 100644 index 0000000..b71cfad --- /dev/null +++ b/Spotify Playlist Generator(Popular Tracks Analyzer).ipynb @@ -0,0 +1,531 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "0f30fc7d", + "metadata": {}, + "source": [ + "# Spotify Playlist Generator" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "858ff7ff", + "metadata": {}, + "outputs": [], + "source": [ + "import requests\n", + "import base64\n", + "import hashlib\n", + "import os\n", + "import json\n", + "import spotipy\n", + "from spotipy.oauth2 import SpotifyOAuth" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "82e6de56", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Please authorize the application by visiting the following URL:\n", + "https://accounts.spotify.com/en/login?continue=https%3A%2F%2Faccounts.spotify.com%2Fauthorize%3Fscope%3Duser-library-read%2Buser-follow-read%2Bplaylist-modify-private%2Bplaylist-modify-public%2Bplaylist-read-private%2Buser-read-private%2Buser-read-email%26response_type%3Dcode%26redirect_uri%3Dhttps%253A%252F%252Fshegszz.github.io%252FSpotify-Playlist-Generator%252F%26code_challenge_method%3DS256%26client_id%3Da5203ec276044c97a6ec5389248f8b79%26code_challenge%3DXRo28PSiSIJfSKfxylh6Mza10eTZdEYdljyzVy2mUtE\n" + ] + } + ], + "source": [ + "# Spotify API credentials\n", + "client_id = 'your-cliend-id-here'\n", + "redirect_uri = 'your-redirect-uri-here'\n", + "\n", + "# Generate a random string as the code verifier for PKCE\n", + "code_verifier = base64.urlsafe_b64encode(os.urandom(32)).decode().rstrip('=')\n", + "code_challenge = base64.urlsafe_b64encode(hashlib.sha256(code_verifier.encode()).digest()).decode().rstrip('=')\n", + "\n", + "# Spotify authorization endpoint\n", + "authorization_url = 'https://accounts.spotify.com/authorize'\n", + "auth_params = {\n", + " 'client_id': client_id,\n", + " 'response_type': 'code',\n", + " 'redirect_uri': redirect_uri,\n", + " 'code_challenge_method': 'S256',\n", + " 'code_challenge': code_challenge,\n", + " 'scope': 'user-library-read user-follow-read playlist-modify-private playlist-modify-public playlist-read-private user-read-private user-read-email'\n", + "}#Add the scope based on the information you choose to share\n", + "authorization_response = requests.get(authorization_url, params=auth_params)\n", + "\n", + "# Redirect the user to Spotify for authorization\n", + "print(\"Please authorize the application by visiting the following URL:\")\n", + "print(authorization_response.url)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "e594a915", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Enter the authorization code from the redirected URL: AQDoLR1429o_gm8DtTa3coWUM10983SDqvuKJk6gC5y3DRttdjt6a8mUXgUsnjO3HbFLFWh82YHLAE9vNRaNEUCcOMhvkEsZ2LrpWUTR7uJ9UgAcKXud6AbV0PPIHVlltQvjK7l-yA3gZbV8qIRjU95v92j_wBzhRThpix2bKBrxIW7rNMS6foUyhswoMOqKhtxL9GMgFEogAeoaH4bx1kPxFxR_M9ie3iuxldP09aR5Ll4G6yP2Rldhh3Y2nI6fnENeiEgGY6Sun6Zy8ltGvwAvwOVtjpkpdTUYSRdPIU2d6uDstq2xLXEmxCrFYRfCs_QLGAeXTGCd5Fhwd7UPKQOdSm84nC4kBWSQ0Q5s8WrVvmi-7Ukbm9HfCGUVeyq8573xMl4dx_yVxkTnVrw5f-QDSRtzuvtFz1JEtKgNwYGt6N7pwyyH_-cuwXT9JO-mQn2vDgpJFspWlsKHEA\n" + ] + } + ], + "source": [ + "# After authorization, Spotify will redirect back to your redirect URI with the authorization code\n", + "authorization_code = input(\"Enter the authorization code from the redirected URL: \")\n", + "\n", + "# Exchange authorization code for access token using PKCE\n", + "token_url = 'https://accounts.spotify.com/api/token'\n", + "token_params = {\n", + " 'grant_type': 'authorization_code',\n", + " 'code': authorization_code,\n", + " 'redirect_uri': redirect_uri,\n", + " 'client_id': client_id,\n", + " 'code_verifier': code_verifier\n", + "}\n", + "token_response = requests.post(token_url, data=token_params)\n", + "\n", + "if token_response.status_code == 200:\n", + " access_token = token_response.json()['access_token']\n", + " refresh_token = token_response.json().get('refresh_token')\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "55c2ccda", + "metadata": {}, + "outputs": [], + "source": [ + "# Get all liked songs(handle pagination)\n", + "offset = 0\n", + "limit = 50 # Maximum limit per request is 50\n", + "\n", + "# Initialize an empty list to store all liked songs\n", + "all_liked_songs = []\n", + "\n", + "# Loop until all liked songs are fetched\n", + "while True:\n", + " liked_songs_response = requests.get(\n", + " 'https://api.spotify.com/v1/me/tracks',\n", + " headers={'Authorization': 'Bearer ' + access_token},\n", + " params={'limit': limit, 'offset': offset}\n", + " )\n", + " liked_songs_data = liked_songs_response.json()\n", + " if 'items' not in liked_songs_data or len(liked_songs_data['items']) == 0:\n", + " # No more songs left to fetch\n", + " break\n", + " all_liked_songs.extend(liked_songs_data['items'])\n", + " offset += limit\n", + "#print(all_liked_songs)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "a94cee30", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "import pandas as pd\n", + "# Extract relevant data from all liked songs\n", + "song_data = []\n", + "\n", + "for song in all_liked_songs:\n", + " Track_name = song['track']['name'] # Extract track name\n", + " Artist_names = [artist['name'] for artist in song['track']['artists']] # Extract artist names\n", + " Album_name = song['track']['album']['name'] # Extract album name\n", + " Popularity = song['track']['popularity'] # Extract popularity score\n", + " Track_id = song['track']['id'] # Extract track id\n", + " Date_Added = song['added_at'] # Extract date added\n", + " \n", + " song_data.append({\n", + " 'Track': Track_name,\n", + " 'Artist': Artist_names,\n", + " 'Album': Album_name,\n", + " 'Popularity': Popularity,\n", + " 'id': Track_id,\n", + " 'Date Added': Date_Added\n", + " })\n", + "\n", + "#Create DataFrame from song data\n", + "all_liked_songs_df = pd.DataFrame(song_data)\n", + "#print(song_data)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "264e1500", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Playlist 'My_Playlist_Project' created successfully!\n" + ] + } + ], + "source": [ + "# Sort the songs based on popularity\n", + "sorted_songs = sorted(song_data, key=lambda x: x['Popularity'], reverse=True)\n", + "\n", + "# Create a new playlist\n", + "playlist_name = 'My_Playlist_Project'\n", + "create_playlist_url = 'https://api.spotify.com/v1/me/playlists'\n", + "create_playlist_headers = {\n", + " 'Authorization': f'Bearer {access_token}',\n", + " 'Content-Type': 'application/json'\n", + "}\n", + "create_playlist_data = {\n", + " 'name': 'My_Playlist_Project',\n", + " 'public': True # Change to True if you want the playlist to be public\n", + " }\n", + "\n", + "#Convert create_playlist_data to Json format\n", + "create_playlist_data_json = json.dumps(create_playlist_data)\n", + "\n", + "#send request to create the playlist\n", + "create_playlist_response = requests.post(create_playlist_url, headers=create_playlist_headers, data=create_playlist_data_json)\n", + "\n", + "#check if the playlist was created successfully\n", + "if create_playlist_response.status_code == 201:\n", + " print(f\"Playlist '{playlist_name}' created successfully!\")\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "1cc33f89", + "metadata": {}, + "outputs": [], + "source": [ + "#Extract the playlist ID from the response\n", + "playlist_id = create_playlist_response.json()['id']\n", + " \n", + "# Add the top 100 songs by popularity to the new playlist\n", + "tracks_to_add = [song['id'] for song in sorted_songs[:100]]\n", + "\n", + "add_tracks_url = f'https://api.spotify.com/v1/playlists/{playlist_id}/tracks'\n", + "add_tracks_data = {\n", + " 'uris': [f'spotify:track:{track_id}' for track_id in tracks_to_add]\n", + "}\n", + "\n", + "add_tracks_response = requests.post(add_tracks_url, headers=create_playlist_headers, json=add_tracks_data)\n", + "if add_tracks_response.status_code == 201:\n", + " print(f\"Top 100 songs added to the playlist successfully!\")\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "3d2ba2b0", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + " | Track | \n", + "Artist | \n", + "Album | \n", + "Popularity | \n", + "id | \n", + "Date Added | \n", + "
---|---|---|---|---|---|---|
0 | \n", + "Beautiful Things | \n", + "[Benson Boone] | \n", + "Beautiful Things | \n", + "96 | \n", + "6tNQ70jh4OwmPGpYy6R2o9 | \n", + "2024-03-22T22:44:09Z | \n", + "
1 | \n", + "Like That | \n", + "[Future, Metro Boomin, Kendrick Lamar] | \n", + "WE DON'T TRUST YOU | \n", + "95 | \n", + "2tudvzsrR56uom6smgOcSf | \n", + "2024-04-01T06:47:28Z | \n", + "
2 | \n", + "euphoria | \n", + "[Kendrick Lamar] | \n", + "euphoria | \n", + "93 | \n", + "77DRzu7ERs0TX3roZcre7Q | \n", + "2024-05-01T07:22:08Z | \n", + "
3 | \n", + "FE!N (feat. Playboi Carti) | \n", + "[Travis Scott, Playboi Carti] | \n", + "UTOPIA | \n", + "92 | \n", + "42VsgItocQwOQC3XWZ8JNA | \n", + "2023-12-31T10:03:50Z | \n", + "
4 | \n", + "Push Ups | \n", + "[Drake] | \n", + "Push Ups | \n", + "91 | \n", + "3eh51r6rFWAlGQRlHx9QnQ | \n", + "2024-04-19T17:22:58Z | \n", + "
... | \n", + "... | \n", + "... | \n", + "... | \n", + "... | \n", + "... | \n", + "... | \n", + "
95 | \n", + "Jealous | \n", + "[Labrinth] | \n", + "Jealous - EP | \n", + "73 | \n", + "4G92yYrUs0cvY7G41YRI0z | \n", + "2023-07-01T04:19:58Z | \n", + "
96 | \n", + "Hours In Silence | \n", + "[Drake, 21 Savage] | \n", + "Her Loss | \n", + "73 | \n", + "0sSRLXxknVTQDStgU1NqpY | \n", + "2023-05-29T06:25:17Z | \n", + "
97 | \n", + "Way 2 Sexy (with Future & Young Thug) | \n", + "[Drake, Future, Young Thug] | \n", + "Certified Lover Boy | \n", + "73 | \n", + "0k1WUmIRnG3xU6fvvDVfRG | \n", + "2023-02-06T21:45:38Z | \n", + "
98 | \n", + "They Don't Care About Us | \n", + "[Michael Jackson] | \n", + "HIStory - PAST, PRESENT AND FUTURE - BOOK I | \n", + "73 | \n", + "3wuCCNCnBhJlwkIJTBZFiv | \n", + "2023-01-02T19:13:43Z | \n", + "
99 | \n", + "3001 | \n", + "[J. Cole] | \n", + "Might Delete Later | \n", + "72 | \n", + "7JRwdwgeTrYkJvwmecrPSW | \n", + "2024-04-07T10:43:25Z | \n", + "
100 rows × 6 columns
\n", + "