Python调用Spotify API遇随机403权限错误求助
排查Spotify API随机403错误的思路与修复
可能的原因及排查步骤
Token缓存冲突与有效期问题
Spotify的access token有效期仅1小时,Spotipy的prompt_for_user_token会默认将token缓存到本地文件(格式为.cache-{username})。你代码里硬编码了username="their_username",如果切换不同用户授权,缓存文件会被覆盖,导致后续请求使用错误的过期token。另外同一运行中第一次请求成功、第二次失败,可能刚好碰到token到期的临界点,或是缓存读取时出现异常。Scope权限缺失
获取用户top tracks必须申请user-top-read权限,检查你的scope变量是否包含该值。如果授权时用户未同意该权限,或是后续修改了scope但未重新授权,就会触发403。可以登录Spotify开发者后台,查看应用的授权记录,确认对应账号的权限是否正确。API速率限制触发
Spotify API对单个token的请求频率有严格限制(比如每分钟最多180次请求),如果你的代码短时间内重复调用接口,可能触发临时封禁。单次请求top tracks不会触发,但如果存在循环调用、重复实例化类发起请求的情况,就可能触及限制。可以查看响应头里的Retry-After字段,确认是否是速率限制导致的403。代码逻辑错误
你的TalkToSpotify类初始化代码存在明显问题:self.credentials = GetCredentials # 未实例化类,正确写法应为GetCredentials() self.access_token = GetCredentials.get_access_token(self)[0] # GetCredentials类未定义get_access_token方法这种错误会导致变量混乱,甚至错误使用无效的token或请求头,引发403。
代码修复建议
- 修正类实例化与token获取逻辑,确保每个用户使用独立缓存:
class GetCredentials(): def __init__(self, username): self.username = username def user_access(self): # 每个用户生成独立缓存文件,避免跨用户冲突 token = util.prompt_for_user_token(username=self.username, scope=scope, client_id=SPOTIPY_CLIENT_ID, client_secret=CLIENT_SECRET, redirect_uri=REDIRECT_URI) return token class TalkToSpotify: def __init__(self, username): self.credentials = GetCredentials(username) self.user_access_token = self.credentials.user_access() self.market = "CA" def get_user_toptracks_1mo(self): headers = { 'Accept': 'application/json', 'Content-Type': 'application/json', 'Authorization': f"Bearer {self.user_access_token}", } params = { "limit": 50, # 无需转字符串,直接传int类型即可 "time_range": "short_term", } response = requests.get('https://api.spotify.com/v1/me/top/tracks', headers=headers, params=params) # 打印详细响应信息,方便排查问题 print(f"状态码: {response.status_code}, 响应内容: {response.text}") # 若403是token过期,尝试重新获取token并重试 if response.status_code == 403: self.user_access_token = self.credentials.user_access() headers['Authorization'] = f"Bearer {self.user_access_token}" response = requests.get('https://api.spotify.com/v1/me/top/tracks', headers=headers, params=params) data = response.json() return data
- 确保scope包含必要权限:
scope = "user-top-read" # 可按需添加其他权限,比如user-read-recently-played
- 速率限制处理:
如果确认是速率限制导致的403,可以在请求前添加固定延迟,或是捕获403后根据响应头的Retry-After字段等待后重试。
内容的提问来源于stack exchange,提问作者BobbyArugola
相关产品推荐
相关产品推荐

