当我尝试使用 Spotify API 创建播放列表时,不断收到 403 禁止错误

问题描述 投票:0回答:1

我已经尝试了在互联网上可以找到的所有方法,但无法修复此错误。我的

spotify_search
access_token
工作得很好。我不明白为什么我可以使用我的代码创建播放列表。特别是考虑到当我使用 Spotify 测试网站创建播放列表时,创建播放列表是有效的。

这是我的代码(带有 Secret 的部分是明显的敏感信息隐藏):

import json
import requests
from bs4 import BeautifulSoup

URL = 'https://www.billboard.com/charts/hot-100/1998-02-28/'

# Obtaining the Top 100 Songs, based on the Year submitted
response = requests.get(URL)
response.raise_for_status()
soup = BeautifulSoup(response.text, 'html.parser')

song_list = [song.getText().strip() for song in 
             soup.select(selector='li h3', class_='c-title')[:100]]
artist_list = [song.getText().strip() for song in 
               soup.select(selector='li ul li span.c-label.a-no-trucate')]

spotify_EP = 'https://api.spotify.com/v1/'

client_ID = '***SECRET***'

#Spotify Documentation - Phase 0: Access Token
def access_token(): 
    token_URL = 'https://accounts.spotify.com/api/token'
    token_secret = '***SECRET***'
    
    
    
    header = {
        'Content-Type': 'application/x-www-form-urlencoded',
    }
    
    params = {
        'grant_type': 'client_credentials',
        'client_id': client_ID,
        'client_secret': token_secret
   }
    response = requests.post(token_URL, params=params, headers=header)
    response.raise_for_status()
    
    return response.json()['access_token']
    
access_token = access_token()

#Spotify Documentation - Phase 1: SEARCH for the Spotify Track and grab their urls
def spotify_search(access_token): 
    print("Searching for Songs...")
    song_urls = []
    for song in range(100): 
        search_sEP = f'{spotify_EP}search'
        search_params = {
            'q': f'{song_list[song]} {artist_list[song]}',
            'type': 'track',
            'limit': 1,
            }
        
        header = {
            'Authorization': f'Bearer {access_token}' 
            }
        
        response = requests.get(search_sEP, params=search_params, headers=header)
        response.raise_for_status()
        song_urls.append(response.json()['tracks']['items'][0]['uri'])
    print('\nSongs Successfully Collected.')
    return song_urls
    
# top100_tracks = spotify_search(access_token) 


#Spotify Documentation - Phase 2: Creating the Spotify Playlist 
def create_playlist():
   
    playlist_sEP = f'{spotify_EP}users/shakuryonsteward/playlists'
    data = {
        'name': "Top 100 Tracks from Birthday",
        'description': "Generated API Playlist as part of Coding Project xP",
        'public': True,
        'grant_type': 'client_credentials'
        }
    header = {
        'Authorization': f'Bearer {access_token}',
        'Content-Type': 'application/json',

        }
    
    response = requests.post(playlist_sEP, data=data, headers=header)
    response.raise_for_status()
    print(response.json())
    

create_playlist()

编辑:这是完整的错误代码:

Traceback (most recent call last):
  File "C:\Users\shaku\OneDrive\Docs\Spyder Projects\Spyder Projects\Spotify Playlist Top 100 Creator\main.py", line 90, in <module>
    create_playlist()
  File "C:\Users\shaku\OneDrive\Docs\Spyder Projects\Spyder Projects\Spotify Playlist Top 100 Creator\main.py", line 86, in create_playlist
    response.raise_for_status()
  File "C:\Users\shaku\AppData\Local\Programs\Python\Python311\Lib\site-packages\requests\models.py", line 1021, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 403 Client Error: Forbidden for url: https://api.spotify.com/v1/users/shakuryonsteward/playlists

我已经按照我的代码中列出的方式进行了尝试,通过 Spotify 可怕的 API 文档来了解正在发生的事情,但我无法找到任何解决方案来在我的用户名中创建新的 Spotify 播放列表。

python authorization spotify
1个回答
0
投票

这是我将歌曲添加到公告牌播放列表的方法。 即使由于 Spotify 中不存在某些歌曲而解析 100 首热门歌曲并且某些查询效果不佳(排名 9 和排名 10),我也获得了 50 首歌曲,但总体而言,这个概念是有效的。

概述

错误原因

403:禁止 client_credentials grant_type 可以搜索歌曲,但无法添加(或创建)播放列表,因为它是用户私人活动。 因此,您无法通过“client_credentials”获取的访问令牌创建播放列表

如果您想这样做,必须通过“授权代码流程”获取访问令牌 它需要您的登录步骤和重定向代码才能获取访问令牌。

更详细的信息在这里

这意味着您通过 Flask (Django) 运行本地服务器或使用 “spotipy” 这是使用 Flaskhere

的示例

spotipy 可以将歌曲添加到现有的播放列表中。这就是为什么我手动制作了一个播放列表。

演示代码

import requests
from bs4 import BeautifulSoup
import json
from urllib.parse import quote
import spotipy
from spotipy.oauth2 import SpotifyOAuth

# Spotify authentication details
SCOPE = ['playlist-modify-public', 'playlist-modify-private']
USER_ID = '[your USER_ID]'                  # Copy from your Spotify Edit Profile
REDIRECT_URI = '[your REDIRECT_URI]'        # Copy from your  Spotify for Developers's Dashboard
CLIENT_ID = '[your CLIENT_ID]'              # Copy from your  Spotify for Developers's Dashboard
CLIENT_SECRET = '[your CLIENT_SECRET]'      # https://developer.spotify.com/dashboard
PLAYLIST_ID = '[your PLAYLIST_ID]'          # copy from Spotify UI after create new playlist

auth_manager = SpotifyOAuth(
    scope=SCOPE,
    username=USER_ID,
    redirect_uri=REDIRECT_URI,
    client_id=CLIENT_ID,
    client_secret=CLIENT_SECRET)

def add_songs_to_playlist(playlist_id, track_ids):
    try:
        sp = spotipy.Spotify(auth_manager=auth_manager)
        sp.playlist_add_items(playlist_id, track_ids)
        print("Songs added to the playlist successfully.")
    except Exception as e:
        print('Failed to add songs to the playlist: ' + str(e))

def get_song_ids_from_json(file_path):
    try:
        with open(file_path, 'r') as file:
            data = json.load(file)
            track_ids = []
            for item in data:
                # Check if 'items' list is not empty
                if item['tracks']['items']:
                    track_id = item['tracks']['items'][0]['id']
                    track_ids.append(track_id)
            return track_ids
    except Exception as e:
        print('Failed to read from JSON file: ' + str(e))
        return []

# Function to get Spotify access token
def get_spotify_token(client_id, client_secret):
    auth_url = 'https://accounts.spotify.com/api/token'
    data = {
        'grant_type': 'client_credentials',
        'client_id': client_id,
        'client_secret': client_secret,
    }
    auth_response = requests.post(auth_url, data=data)
    access_token = auth_response.json().get('access_token')
    return access_token

# Function to search Spotify for a track and artist, and remove 'available_markets'
def search_spotify(access_token, rank, artist, track):
    headers = {"Authorization": "Bearer " + access_token}
    
    # # Encode the artist and track to handle special characters
    encoded_artist = quote(artist)
    encoded_track = quote(artist)

    query = f'artist:{encoded_artist} track:{encoded_track}'
    search_url = f'https://api.spotify.com/v1/search?q={query}&type=track&limit=1'
    result = requests.get(url=search_url, headers=headers).json()

    # Remove 'available_markets' from the result
    items = result.get('tracks', {}).get('items', [])
    if items:
        item = items[0]
        item.pop('available_markets', None)
        album = item.get('album', {})
        album.pop('available_markets', None)

    # Add rank to the result
    result['rank'] = rank
    return result

def save_songs_to_json(spotify_results, file_path):
    filtered_results = []

    for result in spotify_results:
        # Check if 'tracks' and 'items' are in the result and 'items' is not empty
        if 'tracks' in result and 'items' in result['tracks'] and result['tracks']['items']:
            filtered_results.append(result)

    try:
        with open(file_path, 'w') as file:
            json.dump(filtered_results, file, indent=4)
            print(f"Results saved to {file_path}")

    except Exception as e:
        print(f'Failed to save results to JSON: {str(e)}')

# Billboard Hot 100 scraping
def get_billboard_songs(url):
    response = requests.get(URL)
    soup = BeautifulSoup(response.text, 'html.parser')

    # Prepare lists to hold songs and artists
    rank = 1
    rank_list = []
    song_list = []
    artist_list = []
    songs = []

    # Find all list items that contain song and artist information
    entries = soup.find_all('li', class_='o-chart-results-list__item')

    for entry in entries:
        song_title_element = entry.find('h3', class_='c-title')
        if song_title_element:
            song_title = song_title_element.get_text(strip=True)

            artist_name_element = song_title_element.find_next_sibling('span')
            if artist_name_element:
                artist_name = artist_name_element.get_text(strip=True)
                rank_list.append(rank)
                song_list.append(song_title)
                artist_list.append(artist_name)
                songs.append({"rank" : rank, "song": song_title, "artist": artist_name})
                rank = rank + 1

    # Save the Spotify search results to a JSON file
    file_path = 'billboard_songs.json'
    with open(file_path, 'w', encoding='utf-8') as f:
        json.dump(songs, f, ensure_ascii=False, indent=4)

    return rank_list, artist_list, song_list

# Search each song on Spotify
def get_spotify_songs(rank_list, artist_list, song_list):
    spotify_results = []
    # Get Spotify access token
    spotify_token = get_spotify_token(CLIENT_ID, CLIENT_SECRET)
    for rank, artist, song in zip(rank_list, artist_list, song_list):
        result = search_spotify(spotify_token, rank, artist, song)
        spotify_results.append(result)

    return spotify_results

# Step 1  Get billboard songs and save 'billboard_songs.json'
URL = 'https://www.billboard.com/charts/hot-100/1998-02-28/'
rank_list, artist_list, song_list = get_billboard_songs(URL)

# Step 2  Get get_spotify songs
spotify_results = get_spotify_songs(rank_list, artist_list, song_list)

# Step 3  Get get_spotify songs
save_songs_to_json(spotify_results, 'spotify_songs.json')

# Step 4  Add songs to playlist
song_ids = get_song_ids_from_json('spotify_songs.json')
print(len(song_ids))
add_songs_to_playlist(PLAYLIST_ID, song_ids)

已保存“billboard_songs.json”

[
    {
        "rank": 1,
        "song": "My Heart Will Go On",
        "artist": "Celine Dion"
    },
    {
        "rank": 2,
        "song": "Nice & Slow",
        "artist": "Usher"
    },
    {
        "rank": 3,
        "song": "Gettin' Jiggy Wit It",
        "artist": "Will Smith"
    },
    {
        "rank": 4,
        "song": "Together Again",
        "artist": "Janet"
    },
    {
        "rank": 5,
        "song": "Truly Madly Deeply",
        "artist": "Savage Garden"
    },
    {
        "rank": 6,
        "song": "How Do I Live",
        "artist": "LeAnn Rimes"
    },
    {
        "rank": 7,
        "song": "I Don't Ever Want To See You Again",
        "artist": "Uncle Sam"
    },
    {
        "rank": 8,
        "song": "A Song For Mama",
        "artist": "Boyz II Men"
    },
    {
        "rank": 9,
        "song": "No, No, No",
        "artist": "Destiny's Child"
    },
    {
        "rank": 10,
        "song": "Been Around The World",
        "artist": "Puff Daddy & The Family (Feat. The Notorious B.I.G. & Mase)"
    },
    {
        "rank": 11,
        "song": "Too Much",
        "artist": "Spice Girls"
    },
    {
        "rank": 12,
        "song": "Swing My Way",
        "artist": "K.P. & Envyi"
    },
    {
        "rank": 13,
        "song": "What You Want",
        "artist": "Mase Featuring Total"
    },
    {
        "rank": 14,
        "song": "Gone Till November",
        "artist": "Wyclef Jean"
    },
    {
        "rank": 15,
        "song": "Deja Vu [Uptown Baby]",
        "artist": "Lord Tariq & Peter Gunz"
    },
    {
        "rank": 16,
        "song": "How's It Going To Be",
        "artist": "Third Eye Blind"
    },
    {
        "rank": 17,
        "song": "I Don't Want To Wait",
        "artist": "Paula Cole"
    },
    {
        "rank": 18,
        "song": "Kiss The Rain",
        "artist": "Billie Myers"
    },
    {
        "rank": 19,
        "song": "You Make Me Wanna...",
        "artist": "Usher"
    },
    {
        "rank": 20,
        "song": "Are You Jimmy Ray?",
        "artist": "Jimmy Ray"
    },
    {
        "rank": 21,
        "song": "Father",
        "artist": "LL Cool J"
    },
    {
        "rank": 22,
        "song": "Dangerous",
        "artist": "Busta Rhymes"
    },
    {
        "rank": 23,
        "song": "Candle In The Wind 1997/Something About The Way You Look Tonight",
        "artist": "Elton John"
    },
    {
        "rank": 24,
        "song": "Too Close",
        "artist": "Next"
    },
    {
        "rank": 25,
        "song": "Show Me Love",
        "artist": "Robyn"
    },
    {
        "rank": 26,
        "song": "Love You Down",
        "artist": "INOJ/LATHUN"
    },
    {
        "rank": 27,
        "song": "You're Still The One",
        "artist": "Shania Twain"
    },
    {
        "rank": 28,
        "song": "Tubthumping",
        "artist": "Chumbawamba"
    },
    {
        "rank": 29,
        "song": "Body Bumpin' Yippie-Yi-Yo",
        "artist": "Public Announcement"
    },
    {
        "rank": 30,
        "song": "Make Em' Say Uhh!",
        "artist": "Master P Feat. Fiend, Silkk The Shocker, Mia X & Mystikal"
    },
    {
        "rank": 31,
        "song": "If You Think I'm Jiggy",
        "artist": "The Lox"
    },
    {
        "rank": 32,
        "song": "All My Love",
        "artist": "Queen Pen Featuring Eric Williams"
    },
    {
        "rank": 33,
        "song": "We're Not Making Love No More",
        "artist": "Dru Hill"
    },
    {
        "rank": 34,
        "song": "I Do",
        "artist": "Lisa Loeb"
    },
    {
        "rank": 35,
        "song": "Am I Dreaming",
        "artist": "Ol Skool [Featuring Keith Sweat & Xscape]"
    },
    {
        "rank": 36,
        "song": "Pink",
        "artist": "Aerosmith"
    },
    {
        "rank": 37,
        "song": "My Body",
        "artist": "LSG"
    },
    {
        "rank": 38,
        "song": "Heaven",
        "artist": "Nu Flavor"
    },
    {
        "rank": 39,
        "song": "Sweet Surrender",
        "artist": "Sarah McLachlan"
    },
    {
        "rank": 40,
        "song": "Semi-Charmed Life",
        "artist": "Third Eye Blind"
    },
    {
        "rank": 41,
        "song": "Feel So Good",
        "artist": "Mase"
    },
    {
        "rank": 42,
        "song": "I Know Where It's At",
        "artist": "All Saints"
    },
    {
        "rank": 43,
        "song": "They Don't Know",
        "artist": "Jon B"
    },
    {
        "rank": 44,
        "song": "Quit Playing Games (With My Heart)",
        "artist": "Backstreet Boys"
    },
    {
        "rank": 45,
        "song": "All For You",
        "artist": "Sister Hazel"
    },
    {
        "rank": 46,
        "song": "What Would Happen",
        "artist": "Meredith Brooks"
    },
    {
        "rank": 47,
        "song": "I Will Come To You",
        "artist": "Hanson"
    },
    {
        "rank": 48,
        "song": "Light In Your Eyes",
        "artist": "Blessid Union Of Souls"
    },
    {
        "rank": 49,
        "song": "No Tengo Dinero",
        "artist": "Los Umbrellos"
    },
    {
        "rank": 50,
        "song": "Given To Fly",
        "artist": "Pearl Jam"
    },
    {
        "rank": 51,
        "song": "Spice Up Your Life",
        "artist": "Spice Girls"
    },
    {
        "rank": 52,
        "song": "Get At Me Dog",
        "artist": "DMX Featuring Sheek Of The Lox"
    },
    {
        "rank": 53,
        "song": "All I Do",
        "artist": "Somethin' For The People"
    },
    {
        "rank": 54,
        "song": "32 Flavors",
        "artist": "Alana Davis"
    },
    {
        "rank": 55,
        "song": "Romeo And Juliet",
        "artist": "Sylk-E. Fyne Featuring Chill"
    },
    {
        "rank": 56,
        "song": "Burn",
        "artist": "Militia"
    },
    {
        "rank": 57,
        "song": "Breaking All The Rules",
        "artist": "She Moves"
    },
    {
        "rank": 58,
        "song": "Going Back To Cali",
        "artist": "The Notorious B.I.G."
    },
    {
        "rank": 59,
        "song": "What If I Said",
        "artist": "Anita Cochran (Duet With Steve Wariner)"
    },
    {
        "rank": 60,
        "song": "At The Beginning",
        "artist": "Richard Marx & Donna Lewis"
    },
    {
        "rank": 61,
        "song": "Sock It 2 Me",
        "artist": "Missy \"Misdemeanor\" Elliott Featuring Da Brat"
    },
    {
        "rank": 62,
        "song": "Just Clownin'",
        "artist": "WC From Westside Connection"
    },
    {
        "rank": 63,
        "song": "Say You'll Stay",
        "artist": "KAI"
    },
    {
        "rank": 64,
        "song": "The Memory Remains",
        "artist": "Metallica"
    },
    {
        "rank": 65,
        "song": "If I Could Teach The World",
        "artist": "Bone Thugs-N-Harmony"
    },
    {
        "rank": 66,
        "song": "Strawberries",
        "artist": "Smooth"
    },
    {
        "rank": 67,
        "song": "One More Night",
        "artist": "Amber"
    },
    {
        "rank": 68,
        "song": "Don't Be Stupid (You Know I Love You)",
        "artist": "Shania Twain"
    },
    {
        "rank": 69,
        "song": "If I Never Stop Loving You",
        "artist": "David Kersh"
    },
    {
        "rank": 70,
        "song": "Nothin' Move But The Money",
        "artist": "Mic Geronimo Featuring DMX & Black Rob"
    },
    {
        "rank": 71,
        "song": "Life In Mono",
        "artist": "Mono"
    },
    {
        "rank": 72,
        "song": "Ain't That Just The Way",
        "artist": "Lutricia McNeal"
    },
    {
        "rank": 73,
        "song": "Lollipop (Candyman)",
        "artist": "Aqua"
    },
    {
        "rank": 74,
        "song": "I'm Not A Player",
        "artist": "Big Punisher"
    },
    {
        "rank": 75,
        "song": "Brian Wilson",
        "artist": "Barenaked Ladies"
    },
    {
        "rank": 76,
        "song": "Send My Love/Send One Your Love",
        "artist": "Born Jamericans"
    },
    {
        "rank": 77,
        "song": "Off The Hook",
        "artist": "Jody Watley"
    },
    {
        "rank": 78,
        "song": "So Help Me Girl",
        "artist": "Gary Barlow"
    },
    {
        "rank": 79,
        "song": "What If",
        "artist": "Reba McEntire"
    },
    {
        "rank": 80,
        "song": "Then What?",
        "artist": "Clay Walker"
    },
    {
        "rank": 81,
        "song": "I Can Love You Better",
        "artist": "Dixie Chicks"
    },
    {
        "rank": 82,
        "song": "Roxanne `97 - Puff Daddy Remix",
        "artist": "Sting & The Police"
    },
    {
        "rank": 83,
        "song": "4, 3, 2, 1",
        "artist": "LL Cool J Featuring Method Man, Redman, DMX, Canibus And Master P"
    },
    {
        "rank": 84,
        "song": "You're Not Alone",
        "artist": "Olive"
    },
    {
        "rank": 85,
        "song": "Love Of My Life",
        "artist": "Sammy Kershaw"
    },
    {
        "rank": 86,
        "song": "The Day That She Left Tulsa (In A Chevy)",
        "artist": "Wade Hayes"
    },
    {
        "rank": 87,
        "song": "Tuck Me In",
        "artist": "Kimberly Scott"
    },
    {
        "rank": 88,
        "song": "Young, Sad And Blue",
        "artist": "Lysette"
    },
    {
        "rank": 89,
        "song": "Something That We Do",
        "artist": "Clint Black"
    },
    {
        "rank": 90,
        "song": "The Note",
        "artist": "Daryle Singletary"
    },
    {
        "rank": 91,
        "song": "So Long (Well, Well, Well)",
        "artist": "Phajja"
    },
    {
        "rank": 92,
        "song": "I'm Afraid Of Americans",
        "artist": "David Bowie"
    },
    {
        "rank": 93,
        "song": "Tha Hop",
        "artist": "Kinsu"
    },
    {
        "rank": 94,
        "song": "The City Is Mine",
        "artist": "Jay-Z Featuring BLACKstreet"
    },
    {
        "rank": 95,
        "song": "You Know My Steez",
        "artist": "Gang Starr"
    },
    {
        "rank": 96,
        "song": "Tubthumping",
        "artist": "Chucklebutt"
    },
    {
        "rank": 97,
        "song": "So Good",
        "artist": "Davina"
    },
    {
        "rank": 98,
        "song": "Tic Tic Tac",
        "artist": "Fruit De La Passion"
    },
    {
        "rank": 99,
        "song": "In A Dream",
        "artist": "Rockell"
    },
    {
        "rank": 100,
        "song": "L-L-Lies",
        "artist": "Diana King"
    }
]

运行结果

Postman 的搜索示例

Spotipy API 用于将歌曲添加到播放列表

https://spotipy.readthedocs.io/en/2.16.1/?highlight=playlist_add_items#spotipy.client.Spotify.playlist_add_items
© www.soinside.com 2019 - 2024. All rights reserved.