有人知道为什么我使用下面的代码从Spotify播放列表中删除曲目时会收到403吗?

0 投票
2 回答
60 浏览
提问于 2025-04-14 17:20

注意:下面的代码中已经去掉了client_id、client_secret、username和playlist_id的声明。

# Number of songs to delete from the playlist
num_songs_to_delete = 5  # Change this to the desired number

# Encode client_id and client_secret for authentication
client_creds = f"{client_id}:{client_secret}"
#client_creds_b64 = base64.b64encode(client_creds.encode()).decode()
client_creds_b64 = base64.b64encode('{}:{}'.format(client_id, client_secret).encode())


# Get access token using client credentials flow
token_url = "https://accounts.spotify.com/api/token"
token_data = {
    "grant_type": "client_credentials"
}
#token_headers = {
#    "Authorization": f"Basic {client_creds_b64}"
#}
token_headers = {"Authorization": "Basic {}".format(client_creds_b64.decode())}


token_response = requests.post(token_url, data=token_data, headers=token_headers)
token_response_data = token_response.json()
access_token = token_response_data['access_token']

# Get playlist tracks using the access token
playlist_url = f"https://api.spotify.com/v1/playlists/{playlist_id}/tracks"
playlist_headers = {
    "Authorization": f"Bearer {access_token}"
}
playlist_response = requests.get(playlist_url, headers=playlist_headers)
playlist_data = playlist_response.json()

# Sort tracks by their added_at timestamp in descending order
tracks = playlist_data['items']
sorted_tracks = sorted(tracks, key=lambda x: x['added_at'], reverse=True)


# Extract track URIs
tracks_uris = [track['track']['uri'] for track in sorted_tracks]

# Delete the specified number of tracks from the playlist
tracks_to_delete = tracks_uris[:min(num_songs_to_delete, len(tracks_uris))]

# Delete tracks
delete_url = f"https://api.spotify.com/v1/playlists/{playlist_id}/tracks"
delete_data = {
    "tracks": [{"uri": uri} for uri in tracks_to_delete]
}
delete_response = requests.delete(delete_url, headers=playlist_headers, data=json.dumps(delete_data))

print(delete_response)

if delete_response.status_code == 200:
    print(f"{num_songs_to_delete} songs deleted from the playlist.")
else:
    print("Failed to delete songs from the playlist.")

我尝试使用requests和spotipy这两个库来连接Spotify的网络接口,想写一个程序来从指定的播放列表中删除歌曲,但运行代码时总是出现403错误。我的client_id和client_secret与开发者门户中的应用信息是匹配的。我查了很多资料,但还是找不到问题的根源。而且我的应用在Spotify开发者门户中创建得也没问题。

非常感谢任何帮助!

2 个回答

1

两个原因

#1 客户端凭证流程无法删除播放列表

你使用了 "grant_type": "client_credentials" 来获取访问令牌。

你应该使用 授权码流程

如果你查看Spotify的API文档,在“移除播放列表项目”部分,

https://developer.spotify.com/documentation/web-api/reference/remove-tracks-playlist

你可以看到 授权范围。这意味着你的访问令牌是通过 授权码流程 获取的。

这里输入图片描述

这意味着你需要运行本地服务器来处理重定向(回调)URL。
spotipy 可以很方便地为你提供帮助。

#2 [范围]很重要

如果你查看Spotify的范围文档,

https://developer.spotify.com/documentation/web-api/concepts/scopes

这两个范围是移除播放列表曲目所必需的。

playlist-modify-public
playlist-modify-private

这里输入图片描述

我修改了你的代码,并添加了 spotipy 的代码。

保存为 demo.py

import requests
import json
import spotipy
from spotipy.oauth2 import SpotifyOAuth

client_id = '<your client id>'
client_secret = '<your client secret>'
redirect_uri = '<your redirect uri>' # get from developer dash board
username = '<your user name>'        # get from user profile
SCOPEs = ['playlist-modify-private', 'playlist-modify-public']

playlist_id = '<your playlist ID>'     # You want to delete from this playlist ID
# Number of songs to delete from the playlist
num_songs_to_delete = 5  # Change this to the desired number

auth_manager = SpotifyOAuth(client_id=client_id, client_secret=client_secret, redirect_uri=redirect_uri, scope=SCOPEs, username=username)
sp = spotipy.Spotify(auth_manager=auth_manager)
token_info = sp.auth_manager.get_cached_token()
access_token = None
if (token_info is None):
    access_token = sp.auth_manager.get_access_token()
else:
    access_token = token_info['access_token']

# Get playlist tracks using the access token
playlist_url = f"https://api.spotify.com/v1/playlists/{playlist_id}/tracks"
playlist_headers = {
    "Authorization": f"Bearer {access_token}"
}
playlist_response = requests.get(playlist_url, headers=playlist_headers)
playlist_data = playlist_response.json()

# Sort tracks by their added_at timestamp in descending order
tracks = playlist_data['items']
sorted_tracks = sorted(tracks, key=lambda x: x['added_at'], reverse=True)


# Extract track URIs
tracks_uris = [track['track']['uri'] for track in sorted_tracks]

# Delete the specified number of tracks from the playlist
tracks_to_delete = tracks_uris[:min(num_songs_to_delete, len(tracks_uris))]

# Delete tracks
delete_url = f"https://api.spotify.com/v1/playlists/{playlist_id}/tracks"
delete_data = {
    "tracks": [{"uri": uri} for uri in tracks_to_delete]
}
delete_response = requests.delete(delete_url, headers=playlist_headers, data=json.dumps(delete_data))

print(delete_response)

if delete_response.status_code == 200:
    print(f"{num_songs_to_delete} songs deleted from the playlist.")
else:
    print("Failed to delete songs from the playlist.")

如何获取

client_idclient_secretredirect_uri

通过浏览器打开这个网址

https://developer.spotify.com/dashboard

这里输入图片描述

如何获取用户名

通过浏览器打开这个网址

https://open.spotify.com/

这里输入图片描述

安装依赖

pip install requests
pip install spotipy

运行之前

检查你的播放列表中的歌曲数量,运行前要有9首歌。

这里输入图片描述

运行它

python demo.py

这里输入图片描述

运行后

由于移除了5首歌,剩下4首歌。

这里输入图片描述

总结

我只是演示了如何从播放列表中移除歌曲,但我使用了混合的API调用,既请求了API又使用了Spotipy API。如果你使用 授权码流程,我建议只使用Spotipy API。

1

问题出在我在Spotify后台创建的应用上……我也不太清楚为什么,但当我重新创建了这个应用,并使用了新的客户端ID、密钥和重定向地址后,我就能顺利登录了,脚本也正常运行。

可能是因为我之前运行了其他脚本尝试登录,导致浏览器出现了一些缓存问题吧?

撰写回答