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

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 

问题原因

  1. API请求限流:Spotify API有严格的速率限制,原脚本在循环中逐个调用sp.track()、sp.audio_features()、sp.artist(),短时间内大量请求会触发限流,导致部分请求返回不完整数据(比如popularity为0)
  2. 冗余请求: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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 05:37:56