You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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。

代码修复建议

  1. 修正类实例化与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
  1. 确保scope包含必要权限:
scope = "user-top-read"  # 可按需添加其他权限,比如user-read-recently-played
  1. 速率限制处理:
    如果确认是速率限制导致的403,可以在请求前添加固定延迟,或是捕获403后根据响应头的Retry-After字段等待后重试。

内容的提问来源于stack exchange,提问作者BobbyArugola

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 20:40:29