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

使用Spotipy获取Spotify数据:突破50条限制与解析方案问询

解决Spotipy批量数据获取与JSON解析效率问题

一、优化批量获取数据的逻辑

你当前的循环获取代码存在两个明显问题:固定循环次数可能遗漏数据,且直接保存完整response会导致后续解析需要多层嵌套操作。可以改成根据总条数动态循环,同时直接提取items存入列表,简化后续结构:

def get_all_liked_tracks(spot_obj):
    tracks = []
    # 先获取第一页数据与总条数
    first_page = spot_obj.current_user_saved_tracks(limit=50)
    total = first_page['total']
    tracks.extend(first_page['items'])
    
    # 根据总条数计算循环次数,逐页获取数据
    for offset in range(50, total, 50):
        page = spot_obj.current_user_saved_tracks(limit=50, offset=offset)
        tracks.extend(page['items'])
    return tracks

返回的tracks直接是所有歌曲的item列表,后续解析无需再处理多层嵌套的response结构。

二、简化JSON嵌套解析的方法

1. 封装辅助提取函数减少重复代码

针对嵌套字段的提取,可封装一个安全获取嵌套值的函数,避免KeyError同时简化代码:

def get_nested_value(data, keys, default=None):
    """安全获取嵌套字典的值"""
    current = data
    for key in keys:
        if isinstance(current, dict) and key in current:
            current = current[key]
        else:
            return default
    return current

# 用辅助函数解析歌曲数据
song_list = []
for track_item in get_all_liked_tracks(spot_obj):
    song = get_nested_value(track_item, ['track', 'name'], '未知歌曲')
    artist = get_nested_value(track_item, ['track', 'album', 'artists', 0, 'name'], '未知歌手')
    album = get_nested_value(track_item, ['track', 'album', 'name'], '未知专辑')
    release = get_nested_value(track_item, ['track', 'album', 'release_date'], '未知日期')
    song_list.append((song, artist, album, release))

2. 用dataclass结构化数据(Python 3.7+)

如果需要更清晰的数据结构,可用dataclasses模块把解析后的歌曲数据封装成类对象,提升代码可读性与维护性:

from dataclasses import dataclass

@dataclass
class Song:
    name: str
    artist: str
    album: str
    release_date: str

def parse_song(track_item):
    return Song(
        name=get_nested_value(track_item, ['track', 'name'], '未知歌曲'),
        artist=get_nested_value(track_item, ['track', 'album', 'artists', 0, 'name'], '未知歌手'),
        album=get_nested_value(track_item, ['track', 'album', 'name'], '未知专辑'),
        release_date=get_nested_value(track_item, ['track', 'album', 'release_date'], '未知日期')
    )

# 生成结构化的歌曲列表
song_objects = [parse_song(item) for item in get_all_liked_tracks(spot_obj)]
# 访问示例:song_objects[0].name

3. 用Pydantic做严谨数据校验(进阶)

如果需要数据校验与自动类型转换,可使用Pydantic库,它能自动处理JSON到类对象的映射,同时处理缺失字段:

from pydantic import BaseModel, Field
from typing import Optional

class Artist(BaseModel):
    name: str

class Album(BaseModel):
    name: str
    release_date: str
    artists: list[Artist] = Field(default_factory=list)

class Track(BaseModel):
    name: str
    album: Album

class SavedTrackItem(BaseModel):
    track: Track

# 解析单条数据
def parse_song_pydantic(track_item):
    try:
        saved_track = SavedTrackItem(**track_item)
        # 处理歌手列表为空的边界情况
        artist_name = saved_track.track.album.artists[0].name if saved_track.track.album.artists else '未知歌手'
        return Song(
            name=saved_track.track.name,
            artist=artist_name,
            album=saved_track.track.album.name,
            release_date=saved_track.track.album.release_date
        )
    except Exception as e:
        print(f"解析失败: {e}")
        return None

# 生成歌曲对象列表
song_objects = [song for song in map(parse_song_pydantic, get_all_liked_tracks(spot_obj)) if song]

三、整合到现有代码

把优化后的批量获取与解析逻辑整合到你的spot_dict中:

spot_obj = spotipy.Spotify(auth=token_info['access_token'])

spot_dict = {}
spot_dict['user'] = spot_obj.current_user()
spot_dict['liked_songs'] = get_all_liked_tracks(spot_obj)
spot_dict['playlists'] = spot_obj.current_user_playlists()  # 播放列表也可套用类似批量获取逻辑
spot_dict['saved_albums'] = spot_obj.current_user_saved_albums()
spot_dict['num_of_liked_songs'] = len(spot_dict['liked_songs'])

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 06:42:26