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

Spotipy授权方式错误及播放列表分析403报错的解决求助

Spotipy授权方式错误及播放列表分析403报错的解决求助

我最近在练习用Spotify API提取音频特征,参考了一份Spotipy入门的notebook,但过程中遇到了两个问题,希望有经验的朋友能帮忙解答!

一、初始授权代码的AttributeError问题

最开始我用这段代码获取授权:

token = util.oauth2.SpotifyClientCredentials(client_id=CLIENT_ID, client_secret=CLIENT_SECRET)
cache_token = token.get_access_token()
sp = spotipy.Spotify(cache_token)

结果直接触发了AttributeError:

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[4], line 1
----> 1 token = util.oauth2.SpotifyClientCredentials(client_id=CLIENT_ID, client_secret=CLIENT_SECRET)
      2 cache_token = token.get_access_token()
      3 sp = spotipy.Spotify(cache_token)

AttributeError: module 'spotipy.util' has no attribute 'oauth2'

二、修改授权方式后出现403 Forbidden报错

后来我查了资料,把授权代码改成了Spotipy官方推荐的方式,授权这部分暂时没问题了,但当我调用自定义的analyze_playlist函数时:

playlist_df = analyze_playlist(playlist_creator, playlist_id)

又触发了403 Forbidden的HTTP错误,完整报错信息如下:

HTTPError                                 Traceback (most recent call last)
File ~\anaconda3\lib\site-packages\spotipy\client.py:275, in Spotify._internal_call(self, method, url, payload, params)
    270 response = self._session.request(
    271     method, url, headers=headers, proxies=self.proxies,
    272     timeout=self.requests_timeout, **args
    273 )
--> 275 response.raise_for_status()
    276 results = response.json()

File ~\anaconda3\lib\site-packages\requests\models.py:1021, in Response.raise_for_status(self)
   1020 if http_error_msg:
-> 1021     raise HTTPError(http_error_msg, response=self)

HTTPError: 403 Client Error: Forbidden for url: https://api.spotify.com/v1/audio-features/?ids=3AWDeHLc88XogCaCnZQLVI

During handling of the above exception, another exception occurred:

SpotifyException                          Traceback (most recent call last)
Cell In[60], line 1
--> 1 playlist_df = analyze_playlist(playlist_creator, playlist_id)

Cell In[59], line 21, in analyze_playlist(creator, playlist_id)
     19 playlist_features["track_id"] = track["track"]["id"]
     20 # Get audio features
--> 21 audio_features = sp.audio_features(playlist_features["track_id"])[0]
     22 for feature in playlist_features_list[4:]:
     23     playlist_features[feature] = audio_features[feature]

File ~\anaconda3\lib\site-packages\spotipy\client.py:1799, in Spotify.audio_features(self, tracks)
   1797 if isinstance(tracks, str):
   1798     trackid = self._get_id("track", tracks)
-> 1799     results = self._get("audio-features/?ids=" + trackid)
   1800 else:
   1801     tlist = [self._get_id("track", t) for t in tracks]

File ~\anaconda3\lib\site-packages\spotipy\client.py:327, in Spotify._get(self, url, args, payload, **kwargs)
    324 if args:
    325     kwargs.update(args)
--> 327 return self._internal_call("GET", url, payload, kwargs)

File ~\anaconda3\lib\site-packages\spotipy\client.py:297, in Spotify._internal_call(self, method, url, payload, params)
    290         reason = None
    292     logger.error(
    293         'HTTP Error for %s to %s with Params: %s returned %s due to %s',
    294         method, url, args.get("params"), response.status_code, msg
    295     )
--> 297     raise SpotifyException(
    298         response.status_code,
    299         -1,
    300         f"{response.url}:\n {msg}",
    301         reason=reason,
    302         headers=response.headers,
    303     )
    304 except requests.exceptions.RetryError as retry_error:
    305     request = retry_error.request

SpotifyException: http status: 403, code:-1 - https://api.spotify.com/v1/audio-features/?ids=3AWDeHLc88XogCaCnZQLVI:
 None, reason: None

我的完整代码

下面是我目前写的全部代码,麻烦大家帮我看看哪里出了问题:

import spotipy
from spotipy.oauth2 import SpotifyClientCredentials
import pandas as pd

CLIENT_ID = "myidfromapidashboard"
CLIENT_SECRET = "mysecretfromapidashboard"

# 注意:这段是我最初用的旧授权代码,实际运行时已经注释/替换为下面的新授权方式
# token = util.oauth2.SpotifyClientCredentials(client_id=CLIENT_ID, client_secret=CLIENT_SECRET)
# cache_token = token.get_access_token()
# sp = spotipy.Spotify(cache_token)

# 新的授权代码
client_credentials_manager = SpotifyClientCredentials(client_id=CLIENT_ID, client_secret=CLIENT_SECRET)
sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager)

playlist_creator = "spotify"
playlist_id = "37i9dQZF1DX5IDTimEWoTd"

def analyze_playlist(creator, playlist_id):
    
    # Create empty dataframe
    playlist_features_list = ["artist", "album", "track_name", "track_id", 
                             "danceability", "energy", "key", "loudness", "mode", "speechiness",
                             "instrumentalness", "liveness", "valence", "tempo", "duration_ms", "time_signature"]
    playlist_df = pd.DataFrame(columns = playlist_features_list)
    
    # Create empty dict
    playlist_features = {}
    
    # Loop through every track in the playlist, extract features and append the features to the playlist df
    playlist = sp.user_playlist_tracks(creator, playlist_id)["items"]
    for track in playlist:
        # Get metadata
        playlist_features["artist"] = track["track"]["album"]["artists"][0]["name"]
        playlist_features["album"] = track["track"]["album"]["name"]
        playlist_features["track_name"] = track["track"]["name"]
        playlist_features["track_id"] = track["track"]["id"]
        # Get audio features
        audio_features = sp.audio_features(playlist_features["track_id"])[0]
        for feature in playlist_features_list[4:]:
            playlist_features[feature] = audio_features[feature]
        
        # Concat the dfs
        track_df = pd.DataFrame(playlist_features, index = [0])
        playlist_df = pd.concat([playlist_df, track_df], ignore_index = True)
        
    return playlist_df

playlist_df = analyze_playlist(playlist_creator, playlist_id)

我已经卡在这好一会儿了,有没有朋友能帮我排查下问题所在?非常感谢!

备注:内容来源于stack exchange,提问作者ariel23

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.15 03:19:45