Spotipy获取的歌曲popularity值与Spotify API返回值不一致求助
问题:Spotify播放列表曲目popularity值异常(部分返回0)
现象
- 部分曲目获取到的popularity值错误,比如The Killers的《Somebody Told Me》脚本返回0,但在Spotify开发者控制台查询到的实际值是75,其他低热度曲目也存在类似问题
- 多数曲目数值正常,但新建播放列表添加歌曲数量超过10首后,后续部分歌曲的popularity值会出错
原脚本
import spotipy from spotipy.oauth2 import SpotifyClientCredentials # Set up API credentials client_id = 'CLIENT-ID-HERE' client_secret = 'CLIENT-SECRET-HERE' client_credentials_manager = SpotifyClientCredentials(client_id=client_id, client_secret=client_secret) sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager) # Define playlist ID playlist_id = 'PLAYLIST-ID-HERE' # Get tracks in the playlist results = sp.playlist_tracks(playlist_id) tracks = results['items'] while results['next']: results = sp.next(results) tracks.extend(results['items']) counter = 0 for track in tracks: # Get track details track_info = sp.track(track['track']['id']) track_name = track_info['name'] track_artists = [artist['name'] for artist in track_info['artists']] track_release_date = track_info['album']['release_date'] # Get audio features audio_features = sp.audio_features(track['track']['id'])[0] try: track_genre = sp.artist(track_info['artists'][0]['id'])['genres'][0] except: print(f"Track name: {track_name}") print("----------------------------") continue track_bpm = audio_features['tempo'] track_energy = audio_features['energy'] track_danceability = audio_features['danceability'] track_loudness = audio_features['loudness'] track_valence = audio_features['valence'] track_length = audio_features['duration_ms'] / 1000 track_acousticness = audio_features['acousticness'] track_speechiness = audio_features['speechiness'] track_popularity = track_info['popularity'] # Print track information print(f"Track name: {track_name}") print(f"Artists: {', '.join(track_artists)}") print(f"Genre: {track_genre}") print(f"Release date: {track_release_date}") print(f"BPM: {track_bpm}") print(f"Energy: {track_energy}") print(f"Danceability: {track_danceability}") print(f"Loudness: {track_loudness}") print(f"Valence: {track_valence}") print(f"Length: {track_length}") print(f"Acousticness: {track_acousticness}") print(f"Speechiness: {track_speechiness}") print(f"Popularity: {track_popularity}") print("----------------------------") counter+=1
问题原因
- API请求限流:Spotify API有严格的速率限制,原脚本在循环中逐个调用
sp.track()、sp.audio_features()、sp.artist(),短时间内大量请求会触发限流,导致部分请求返回不完整数据(比如popularity为0) - 冗余请求:
playlist_tracks()返回的track['track']对象本身已经包含了popularity、name、artists、album等基础信息,完全不需要额外调用sp.track()获取,这既浪费请求配额又增加了触发限流的概率
解决方案
优化点:
- 直接使用
playlist_tracks()返回的track数据中的基础字段,减少冗余请求 - 批量调用API(Spotify API支持批量传入多个ID),大幅降低请求次数
- 添加少量请求延迟,避免触发限流
修改后的脚本
import spotipy from spotipy.oauth2 import SpotifyClientCredentials import time # Set up API credentials client_id = 'CLIENT-ID-HERE' client_secret = 'CLIENT-SECRET-HERE' client_credentials_manager = SpotifyClientCredentials(client_id=client_id, client_secret=client_secret) sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager) # Define playlist ID playlist_id = 'PLAYLIST-ID-HERE' # Get tracks in the playlist results = sp.playlist_tracks(playlist_id) tracks = results['items'] while results['next']: results = sp.next(results) tracks.extend(results['items']) # Extract necessary IDs in batches track_ids = [t['track']['id'] for t in tracks if t['track']['id']] artist_ids = [t['track']['artists'][0]['id'] for t in tracks if t['track']['artists']] # Batch get audio features (supports up to 100 IDs per request) audio_features_map = {} for i in range(0, len(track_ids), 100): batch_ids = track_ids[i:i+100] features_batch = sp.audio_features(batch_ids) for feat in features_batch: if feat: audio_features_map[feat['id']] = feat time.sleep(0.1) # Add small delay to avoid rate limit # Batch get artist genres (supports up to 50 IDs per request) artist_genre_map = {} for i in range(0, len(artist_ids), 50): batch_ids = artist_ids[i:i+50] artists_batch = sp.artists(batch_ids) for artist in artists_batch['artists']: if artist['genres']: artist_genre_map[artist['id']] = artist['genres'][0] else: artist_genre_map[artist['id']] = 'Unknown' time.sleep(0.1) counter = 0 for track in tracks: track_data = track['track'] if not track_data: continue # Use existing data from playlist_tracks to avoid redundant requests track_name = track_data['name'] track_artists = [artist['name'] for artist in track_data['artists']] track_release_date = track_data['album']['release_date'] track_popularity = track_data['popularity'] # Directly use from playlist track data # Get audio features from pre-fetched map audio_features = audio_features_map.get(track_data['id']) if not audio_features: print(f"Missing audio features for: {track_name}") print("----------------------------") continue # Get genre from pre-fetched map track_genre = artist_genre_map.get(track_data['artists'][0]['id'], 'Unknown') track_bpm = audio_features['tempo'] track_energy = audio_features['energy'] track_danceability = audio_features['danceability'] track_loudness = audio_features['loudness'] track_valence = audio_features['valence'] track_length = audio_features['duration_ms'] / 1000 track_acousticness = audio_features['acousticness'] track_speechiness = audio_features['speechiness'] # Print track information print(f"Track name: {track_name}") print(f"Artists: {', '.join(track_artists)}") print(f"Genre: {track_genre}") print(f"Release date: {track_release_date}") print(f"BPM: {track_bpm}") print(f"Energy: {track_energy}") print(f"Danceability: {track_danceability}") print(f"Loudness: {track_loudness}") print(f"Valence: {track_valence}") print(f"Length: {track_length}") print(f"Acousticness: {track_acousticness}") print(f"Speechiness: {track_speechiness}") print(f"Popularity: {track_popularity}") print("----------------------------") counter += 1
内容的提问来源于stack exchange,提问作者Youval
相关产品推荐
相关产品推荐

