From 1e8202e4d2ae56398ac0d04221ec1babb755cba2 Mon Sep 17 00:00:00 2001 From: Segun Bakare Date: Sat, 11 May 2024 16:42:25 +0100 Subject: [PATCH] Add Spotify Playlist Generator code This Jupyter Notebook contains my Spotify Playlist Generator project code where I analyzed top tracks based on popularity, identified trends, and generated insights using Python. --- ...t Generator(Popular Tracks Analyzer).ipynb | 531 ++++++++++++++++++ 1 file changed, 531 insertions(+) create mode 100644 Spotify Playlist Generator(Popular Tracks Analyzer).ipynb 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", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
TrackArtistAlbumPopularityidDate Added
0Beautiful Things[Benson Boone]Beautiful Things966tNQ70jh4OwmPGpYy6R2o92024-03-22T22:44:09Z
1Like That[Future, Metro Boomin, Kendrick Lamar]WE DON'T TRUST YOU952tudvzsrR56uom6smgOcSf2024-04-01T06:47:28Z
2euphoria[Kendrick Lamar]euphoria9377DRzu7ERs0TX3roZcre7Q2024-05-01T07:22:08Z
3FE!N (feat. Playboi Carti)[Travis Scott, Playboi Carti]UTOPIA9242VsgItocQwOQC3XWZ8JNA2023-12-31T10:03:50Z
4Push Ups[Drake]Push Ups913eh51r6rFWAlGQRlHx9QnQ2024-04-19T17:22:58Z
.....................
95Jealous[Labrinth]Jealous - EP734G92yYrUs0cvY7G41YRI0z2023-07-01T04:19:58Z
96Hours In Silence[Drake, 21 Savage]Her Loss730sSRLXxknVTQDStgU1NqpY2023-05-29T06:25:17Z
97Way 2 Sexy (with Future & Young Thug)[Drake, Future, Young Thug]Certified Lover Boy730k1WUmIRnG3xU6fvvDVfRG2023-02-06T21:45:38Z
98They Don't Care About Us[Michael Jackson]HIStory - PAST, PRESENT AND FUTURE - BOOK I733wuCCNCnBhJlwkIJTBZFiv2023-01-02T19:13:43Z
993001[J. Cole]Might Delete Later727JRwdwgeTrYkJvwmecrPSW2024-04-07T10:43:25Z
\n", + "

100 rows × 6 columns

\n", + "
" + ], + "text/plain": [ + " Track \\\n", + "0 Beautiful Things \n", + "1 Like That \n", + "2 euphoria \n", + "3 FE!N (feat. Playboi Carti) \n", + "4 Push Ups \n", + ".. ... \n", + "95 Jealous \n", + "96 Hours In Silence \n", + "97 Way 2 Sexy (with Future & Young Thug) \n", + "98 They Don't Care About Us \n", + "99 3001 \n", + "\n", + " Artist \\\n", + "0 [Benson Boone] \n", + "1 [Future, Metro Boomin, Kendrick Lamar] \n", + "2 [Kendrick Lamar] \n", + "3 [Travis Scott, Playboi Carti] \n", + "4 [Drake] \n", + ".. ... \n", + "95 [Labrinth] \n", + "96 [Drake, 21 Savage] \n", + "97 [Drake, Future, Young Thug] \n", + "98 [Michael Jackson] \n", + "99 [J. Cole] \n", + "\n", + " Album Popularity \\\n", + "0 Beautiful Things 96 \n", + "1 WE DON'T TRUST YOU 95 \n", + "2 euphoria 93 \n", + "3 UTOPIA 92 \n", + "4 Push Ups 91 \n", + ".. ... ... \n", + "95 Jealous - EP 73 \n", + "96 Her Loss 73 \n", + "97 Certified Lover Boy 73 \n", + "98 HIStory - PAST, PRESENT AND FUTURE - BOOK I 73 \n", + "99 Might Delete Later 72 \n", + "\n", + " id Date Added \n", + "0 6tNQ70jh4OwmPGpYy6R2o9 2024-03-22T22:44:09Z \n", + "1 2tudvzsrR56uom6smgOcSf 2024-04-01T06:47:28Z \n", + "2 77DRzu7ERs0TX3roZcre7Q 2024-05-01T07:22:08Z \n", + "3 42VsgItocQwOQC3XWZ8JNA 2023-12-31T10:03:50Z \n", + "4 3eh51r6rFWAlGQRlHx9QnQ 2024-04-19T17:22:58Z \n", + ".. ... ... \n", + "95 4G92yYrUs0cvY7G41YRI0z 2023-07-01T04:19:58Z \n", + "96 0sSRLXxknVTQDStgU1NqpY 2023-05-29T06:25:17Z \n", + "97 0k1WUmIRnG3xU6fvvDVfRG 2023-02-06T21:45:38Z \n", + "98 3wuCCNCnBhJlwkIJTBZFiv 2023-01-02T19:13:43Z \n", + "99 7JRwdwgeTrYkJvwmecrPSW 2024-04-07T10:43:25Z \n", + "\n", + "[100 rows x 6 columns]" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#Create DataFrame from playlist created\n", + "My_Playlist_Project = sorted_songs[:100]\n", + "df = pd.DataFrame(My_Playlist_Project)\n", + "df" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "e08995ce", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "User Playlists:\n", + "Ughhh\n", + "My_Playlist_Project\n", + "Repeat Rewind\n", + "On Repeat\n", + "My recommendation playlist\n", + "Horladee + D_grey\n", + "Beast Mode Hip-Hop\n", + "My recommendation playlist\n", + "Most Streamed Rap Songs on Spotify\n", + "Dwizztheman\n", + "Get Turnt\n", + "Your Top Songs 2023\n", + "Motivation\n", + "Comedy\n", + "Jazz_Soul_Blues\n", + "Rap Workout\n", + "Blues Classics\n", + "Big Sean FT Jhene Aiko\n", + "Favorites\n", + "Billboard Hot 100\n", + "The GRAMMYs Official Playlist\n", + "I Love My '00s R&B\n", + "Gospel\n", + "RNB WORKOUT\n", + "Top 100 Nigeria on Apple Music\n", + "Power Soundtrack\n", + "J. Cole Mix\n", + "I Love My '90s Hip-Hop\n", + "Top 50 - Global\n" + ] + } + ], + "source": [ + "# Get user playlists\n", + "playlists_url = 'https://api.spotify.com/v1/me/playlists'\n", + "playlists_headers = {\n", + " 'Authorization': f'Bearer {access_token}'\n", + "}\n", + "playlists_response = requests.get(playlists_url, headers=playlists_headers)\n", + "\n", + "if playlists_response.status_code == 200:\n", + " playlists_data = playlists_response.json()\n", + " print(\"User Playlists:\")\n", + " for playlist in playlists_data['items']:\n", + " print(playlist['name'])\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6380fab7", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.5" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}