From 9c2864000ef20c11d9f8cf4304befb5a679ffbe7 Mon Sep 17 00:00:00 2001 From: Yilak Kebede Date: Sat, 27 Sep 2025 21:56:12 +0200 Subject: [PATCH] Completed Spotify API exercises --- Lab_APIs.ipynb | 401 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 401 insertions(+) create mode 100644 Lab_APIs.ipynb diff --git a/Lab_APIs.ipynb b/Lab_APIs.ipynb new file mode 100644 index 0000000..e095da2 --- /dev/null +++ b/Lab_APIs.ipynb @@ -0,0 +1,401 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "3be359c2-6731-485f-a44c-3b91ae35d279", + "metadata": {}, + "source": [ + "# installment and import dependenceies" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "14301af7-e7a4-4e39-950f-cb9634f38478", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Collecting spotipy\n", + " Downloading spotipy-2.25.1-py3-none-any.whl.metadata (5.1 kB)\n", + "Collecting redis>=3.5.3 (from spotipy)\n", + " Downloading redis-6.4.0-py3-none-any.whl.metadata (10 kB)\n", + "Requirement already satisfied: requests>=2.25.0 in c:\\users\\kyila\\anaconda3\\lib\\site-packages (from spotipy) (2.31.0)\n", + "Requirement already satisfied: urllib3>=1.26.0 in c:\\users\\kyila\\anaconda3\\lib\\site-packages (from spotipy) (2.0.7)\n", + "Requirement already satisfied: charset-normalizer<4,>=2 in c:\\users\\kyila\\anaconda3\\lib\\site-packages (from requests>=2.25.0->spotipy) (2.0.4)\n", + "Requirement already satisfied: idna<4,>=2.5 in c:\\users\\kyila\\anaconda3\\lib\\site-packages (from requests>=2.25.0->spotipy) (3.4)\n", + "Requirement already satisfied: certifi>=2017.4.17 in c:\\users\\kyila\\anaconda3\\lib\\site-packages (from requests>=2.25.0->spotipy) (2024.7.4)\n", + "Downloading spotipy-2.25.1-py3-none-any.whl (31 kB)\n", + "Downloading redis-6.4.0-py3-none-any.whl (279 kB)\n", + " ---------------------------------------- 0.0/279.8 kB ? eta -:--:--\n", + " ----- --------------------------------- 41.0/279.8 kB 991.0 kB/s eta 0:00:01\n", + " ------------- -------------------------- 92.2/279.8 kB 1.1 MB/s eta 0:00:01\n", + " ------------------------ --------------- 174.1/279.8 kB 1.2 MB/s eta 0:00:01\n", + " --------------------------------------- 276.5/279.8 kB 1.6 MB/s eta 0:00:01\n", + " ---------------------------------------- 279.8/279.8 kB 1.3 MB/s eta 0:00:00\n", + "Installing collected packages: redis, spotipy\n", + "Successfully installed redis-6.4.0 spotipy-2.25.1\n" + ] + } + ], + "source": [ + "!pip install spotipy\n", + "import spotipy\n", + "from spotipy.oauth2 import SpotifyClientCredentials\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "658f83c8-a275-49ad-89ee-0020bb06793f", + "metadata": {}, + "outputs": [], + "source": [ + "# set up authentication \n", + "CLIENT_ID = \"4109b2d9f5014671863bb2df1d1fbdd3\"\n", + "CLIENT_SECRET = \"5cb719fae80c4191a9c0b288f51bfe50\"\n", + "\n", + "sp = spotipy.Spotify(auth_manager=SpotifyClientCredentials(client_id=CLIENT_ID,\n", + " client_secret=CLIENT_SECRET))\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "bd5da64e-692f-4caf-bb9f-4a01ae8b1e06", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Couldn't read cache at: .cache\n", + "Couldn't write token to cache at: .cache\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "dict_keys(['tracks'])\n", + "dict_keys(['album', 'artists', 'available_markets', 'disc_number', 'duration_ms', 'explicit', 'external_ids', 'external_urls', 'href', 'id', 'is_local', 'is_playable', 'name', 'popularity', 'preview_url', 'track_number', 'type', 'uri'])\n", + "Track Name: The Dead Dance\n", + "Artist: Lady Gaga\n" + ] + } + ], + "source": [ + "# serching for an artist\n", + "results = sp.search(q='Lady Gaga', limit=5)\n", + "print(results.keys()) # Shows 'tracks'\n", + "print(results[\"tracks\"][\"items\"][0].keys()) # Album, artists, id, name, popularity, etc.\n", + "\n", + "# Example: print track name and artists\n", + "track = results[\"tracks\"][\"items\"][0]\n", + "print(\"Track Name:\", track[\"name\"])\n", + "for artist in track[\"artists\"]:\n", + " print(\"Artist:\", artist[\"name\"])\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "a9356f22-6387-46a5-89fe-eabf0325af7f", + "metadata": {}, + "source": [ + "# Exercise 1: Top Tracks and Related Artists" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "b3584324-6f23-4076-afad-f58c158451af", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Couldn't read cache at: .cache\n", + "Couldn't write token to cache at: .cache\n", + "Couldn't read cache at: .cache\n", + "Couldn't write token to cache at: .cache\n", + "Couldn't read cache at: .cache\n", + "Couldn't write token to cache at: .cache\n", + "Couldn't read cache at: .cache\n", + "Couldn't write token to cache at: .cache\n", + "Couldn't read cache at: .cache\n", + "Couldn't write token to cache at: .cache\n", + "Couldn't read cache at: .cache\n", + "Couldn't write token to cache at: .cache\n", + "Couldn't read cache at: .cache\n", + "Couldn't write token to cache at: .cache\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[['Die With A Smile', 'The Dead Dance', 'Abracadabra', 'Poker Face', 'Just Dance'], ['Sapphire', 'Shape of You', 'Perfect', 'Azizam', 'Photograph'], ['Cold Heart - PNAU Remix', \"Don't Start Now\", 'Levitating (feat. DaBaby)', 'One Kiss (with Dua Lipa)', 'New Rules']]\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Couldn't read cache at: .cache\n", + "Couldn't write token to cache at: .cache\n", + "HTTP Error for GET to https://api.spotify.com/v1/artists/1HY2Jd0NmPuamShAr6KMms/related-artists with Params: {} returned 404 due to Not Found\n", + "Couldn't read cache at: .cache\n", + "Couldn't write token to cache at: .cache\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "No related artists found for Lady Gaga\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Couldn't read cache at: .cache\n", + "Couldn't write token to cache at: .cache\n", + "HTTP Error for GET to https://api.spotify.com/v1/artists/6eUKZXaKkcviH0Ku9w2n3V/related-artists with Params: {} returned 404 due to Not Found\n", + "Couldn't read cache at: .cache\n", + "Couldn't write token to cache at: .cache\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "No related artists found for Ed Sheeran\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Couldn't read cache at: .cache\n", + "Couldn't write token to cache at: .cache\n", + "HTTP Error for GET to https://api.spotify.com/v1/artists/6M2wZ9GZgrQXHCFfjv46we/related-artists with Params: {} returned 404 due to Not Found\n", + "Couldn't read cache at: .cache\n", + "Couldn't write token to cache at: .cache\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "No related artists found for Dua Lipa\n", + "[[], [], []]\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Couldn't read cache at: .cache\n", + "Couldn't write token to cache at: .cache\n", + "Couldn't read cache at: .cache\n", + "Couldn't write token to cache at: .cache\n", + "Couldn't read cache at: .cache\n", + "Couldn't write token to cache at: .cache\n", + "Couldn't read cache at: .cache\n", + "Couldn't write token to cache at: .cache\n", + "Couldn't read cache at: .cache\n", + "Couldn't write token to cache at: .cache\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Final playlist tracks:\n", + "['Die With A Smile', 'The Dead Dance', 'Abracadabra', 'Poker Face', 'Just Dance', 'Sapphire', 'Shape of You', 'Perfect', 'Azizam', 'Photograph', 'Cold Heart - PNAU Remix', \"Don't Start Now\", 'Levitating (feat. DaBaby)', 'One Kiss (with Dua Lipa)', 'New Rules']\n" + ] + } + ], + "source": [ + "# get top tracks funtion \n", + "def get_top_tracks(artist_name, top_n=5):\n", + " res = sp.search(q=artist_name, limit=1, type='artist')\n", + " artist_id = res['artists']['items'][0]['id']\n", + " top_tracks = sp.artist_top_tracks(artist_id)['tracks']\n", + " return [track['name'] for track in top_tracks[:top_n]]\n", + "\n", + "# Example usage\n", + "artists = [\"Lady Gaga\", \"Ed Sheeran\", \"Dua Lipa\"]\n", + "top_tracks_list = [get_top_tracks(a) for a in artists]\n", + "print(top_tracks_list)\n", + "\n", + "# find related artists function \n", + "from spotipy.exceptions import SpotifyException\n", + "\n", + "def find_related_artists(artist_name, top_n=5):\n", + " try:\n", + " res = sp.search(q=artist_name, limit=1, type='artist')\n", + " artist_id = res['artists']['items'][0]['id']\n", + " related_artists = sp.artist_related_artists(artist_id)['artists']\n", + " return [artist['name'] for artist in related_artists[:top_n]]\n", + " except (IndexError, SpotifyException):\n", + " print(f\"No related artists found for {artist_name}\")\n", + " return []\n", + "\n", + "# Example usage\n", + "artists = [\"Lady Gaga\", \"Ed Sheeran\", \"Dua Lipa\"]\n", + "related_artists_list = [find_related_artists(a) for a in artists]\n", + "print(related_artists_list)\n", + "\n", + "# combine for playlist\n", + "playlist_tracks = []\n", + "\n", + "# Add top tracks of main artists\n", + "for artist in artists:\n", + " playlist_tracks.extend(get_top_tracks(artist))\n", + "\n", + "# Add top tracks of related artists\n", + "for artist in related_artists_list:\n", + " for related_artist in artist:\n", + " playlist_tracks.extend(get_top_tracks(related_artist))\n", + "\n", + "print(\"Final playlist tracks:\")\n", + "print(playlist_tracks[:20]) # Show first 20 tracks\n" + ] + }, + { + "cell_type": "markdown", + "id": "bbd495da-8ed4-48e1-80ac-d1f3043921db", + "metadata": {}, + "source": [ + "# Exercise 2: Featured Playlists" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "17bbec91-8cff-4a39-92e9-a2be14553d72", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Couldn't read cache at: .cache\n", + "Couldn't write token to cache at: .cache\n", + "Couldn't read cache at: .cache\n", + "Couldn't write token to cache at: .cache\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1. BEST HITS 2025 πŸ”₯ Popular Songs 🎡 Top Music Hits 🎡 (ID: 5KJDMJe9EJ7QRz8FG2MIpI)\n", + "2. COUNTRY HITS 2025 πŸ”₯ New Country Songs + Top Hits (ID: 4Jb4PDWREzNnbZcOHPcZPy)\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Couldn't read cache at: .cache\n", + "Couldn't write token to cache at: .cache\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Name: BEST HITS 2025 πŸ”₯ Popular Songs 🎡 Top Music Hits 🎡 \n", + "Description: Best Hits 2025 | Popular Songs 2025 | Top Music Hits | Today Top Hits | Viral Hits | Radio Hits 2024/2025 | Summer Music Mix 2025 | Best Of 2025 | Summer Vibes | Deep House | Pop Vibes | Top Songs | Top Music | Global Hits | Best Songs| Clean | Pop Hits | Viral Pop - updated and active! :)\n", + "Total tracks: 146\n", + "{'Die With A Smile': ['Lady Gaga', 'Bruno Mars'], 'BIRDS OF A FEATHER': ['Billie Eilish'], 'Espresso': ['Sabrina Carpenter'], 'As It Was': ['Harry Styles'], \"I'm in Love\": ['ConKi'], 'Cruel Summer': ['Taylor Swift'], 'APT.': ['ROSΓ‰', 'Bruno Mars'], 'Beautiful Things': ['Benson Boone'], 'Messy': ['Lola Young'], 'Life': ['ConKi']}\n" + ] + } + ], + "source": [ + "# Search for playlists\n", + "\n", + "search_results = sp.search(q=\"Top Hits\", type=\"playlist\", limit=5)\n", + "\n", + "# Safely get playlist items\n", + "featured = search_results.get('playlists', {}).get('items', [])\n", + "\n", + "# Remove None entries\n", + "featured = [pl for pl in featured if pl is not None]\n", + "\n", + "if not featured:\n", + " print(\"No playlists found.\")\n", + "else:\n", + " # List the top playlists\n", + " for i, playlist in enumerate(featured, 1):\n", + " name = playlist.get('name', 'Unknown')\n", + " pid = playlist.get('id', 'Unknown')\n", + " print(f\"{i}. {name} (ID: {pid})\")\n", + "\n", + " # Choose one playlist (first one)\n", + " playlist_id = featured[0].get('id')\n", + " if playlist_id:\n", + " playlist_info = sp.playlist(playlist_id)\n", + " print(\"Name:\", playlist_info.get('name', 'Unknown'))\n", + " print(\"Description:\", playlist_info.get('description', 'No description'))\n", + " print(\"Total tracks:\", playlist_info.get('tracks', {}).get('total', 0))\n", + "\n", + " # Extract first 10 tracks\n", + " tracks = sp.playlist_tracks(playlist_id).get('items', [])[:10]\n", + " track_artist_dict = {}\n", + " for track_item in tracks:\n", + " track = track_item.get('track', {})\n", + " track_name = track.get('name', 'Unknown')\n", + " artists = [artist.get('name', 'Unknown') for artist in track.get('artists', [])]\n", + " track_artist_dict[track_name] = artists\n", + "\n", + " print(track_artist_dict)\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4b515220-48f0-42db-8527-257261b313ef", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3e7b5440-b8f6-4afc-87bc-00e56f0cd10d", + "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.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}