我已经尝试了在互联网上可以找到的所有方法,但无法修复此错误。我的
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 播放列表。
这是我将歌曲添加到公告牌播放列表的方法。 即使由于 Spotify 中不存在某些歌曲而解析 100 首热门歌曲并且某些查询效果不佳(排名 9 和排名 10),我也获得了 50 首歌曲,但总体而言,这个概念是有效的。
403:禁止 client_credentials grant_type 可以搜索歌曲,但无法添加(或创建)播放列表,因为它是用户私人活动。 因此,您无法通过“client_credentials”获取的访问令牌创建播放列表
如果您想这样做,必须通过“授权代码流程”获取访问令牌 它需要您的登录步骤和重定向代码才能获取访问令牌。
更详细的信息在这里
这意味着您通过 Flask (Django) 运行本地服务器或使用 “spotipy” 这是使用 Flask 和 here
的示例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)
[
{
"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"
}
]
运行结果
https://spotipy.readthedocs.io/en/2.16.1/?highlight=playlist_add_items#spotipy.client.Spotify.playlist_add_items