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

Spotipy应用无法识别重复曲目,执行后未删除歌曲求助

问题:Spotipy脚本无法识别并删除歌单重复曲目

我开发了一个基于Spotipy的Python脚本,用于移除Spotify歌单中的重复曲目。脚本启动后无报错,正常跳转至授权页面,完成授权后脚本执行结束,但未删除任何歌曲。脚本运行时会打印重复曲目,但输出的字典为空,推测应用无法识别重复曲目,期望实现删除重复歌曲的功能。

原脚本代码:

import spotipy
from spotipy.oauth2 import SpotifyOAuth
import re

def get_playlist_id(url):
    playlist_id = re.search(r'/playlist/([a-zA-Z0-9]+)', url)
    if playlist_id:
        return playlist_id.group(1)
    else:
        return None

def get_duplicates(tracks):
    duplicates = {}
    for track in tracks:
        key = f"{track['track']['name']} - {track['track']['artists'][0]['name']}"
        if key in duplicates:
            duplicates[key].append(track['track']['id'])
        else:
            duplicates[key] = [track['track']['id']]
    duplicate_tracks = {key: ids for key, ids in duplicates.items() if len(ids) > 1}
    print("Duplicate tracks:", duplicate_tracks)
    return duplicate_tracks

def remove_duplicates(sp, playlist_id):
    playlist_tracks = sp.playlist_tracks(playlist_id)['items']

    duplicates = get_duplicates(playlist_tracks)
    for ids in duplicates.values():
        for track_id in ids[1:]:
            sp.playlist_remove_all_occurrences_of_items(playlist_id, [track_id])

def main():
    scope = "playlist-read-collaborative playlist-modify-public"
    client_id = 'my client ID'
    client_secret = 'my client secret'
    redirect_uri = 'http://localhost:3036'
    sp = spotipy.Spotify(
        auth_manager=SpotifyOAuth(client_id=client_id, client_secret=client_secret, redirect_uri=redirect_uri,
                                  scope=scope))
    playlist_url = 'https://open.spotify.com/playlist/1x76RxwKGwGq5oP3xofc3o?si=710c91480cb64fb6'
    playlist_id = get_playlist_id(playlist_url)

    if playlist_id:
        remove_duplicates(sp, playlist_id)
    else:
        print("Fehler: Playlist-ID konnte nicht aus der URL extrahiert werden.")

if __name__ == "__main__":
    main()

问题排查与修复方案

1. 修复曲目分页获取问题

Spotify API的playlist_tracks接口默认只返回100条曲目,需循环获取所有分页数据:

def get_all_playlist_tracks(sp, playlist_id):
    tracks = []
    results = sp.playlist_tracks(playlist_id)
    tracks.extend(results['items'])
    while results['next']:
        results = sp.next(results)
        tracks.extend(results['items'])
    return tracks

2. 优化重复项判断逻辑

  • 跳过track为None的无效条目
  • 改用唯一的track_id作为核心判断依据(更准确,避免同名不同曲的误判),同时保留曲目名+艺术家的标识用于输出:
def get_duplicates(tracks):
    track_map = {}
    duplicates = {}
    for item in tracks:
        track = item['track']
        if not track:
            continue  # 跳过无效曲目
        track_id = track['id']
        track_key = f"{track['name']} - {track['artists'][0]['name']}"
        if track_id in track_map:
            # 记录重复项
            if track_key not in duplicates:
                duplicates[track_key] = [track_map[track_id]]
            duplicates[track_key].append(item['id'])  # 用歌单条目的id,而非track_id,删除更准确
        else:
            track_map[track_id] = item['id']
    print("Duplicate tracks:", duplicates)
    return duplicates

3. 补充权限范围

如果操作私有歌单,需添加playlist-modify-private权限:

scope = "playlist-read-collaborative playlist-modify-public playlist-modify-private"

4. 优化删除逻辑

使用歌单条目的item['id']而非track['id']调用playlist_remove_items,删除更精准:

def remove_duplicates(sp, playlist_id):
    playlist_tracks = get_all_playlist_tracks(sp, playlist_id)
    duplicates = get_duplicates(playlist_tracks)
    for item_ids in duplicates.values():
        # 保留第一个条目,删除后续重复条目
        sp.playlist_remove_items(playlist_id, item_ids[1:])

修复后的完整代码

import spotipy
from spotipy.oauth2 import SpotifyOAuth
import re

def get_playlist_id(url):
    playlist_id = re.search(r'/playlist/([a-zA-Z0-9]+)', url)
    if playlist_id:
        return playlist_id.group(1)
    else:
        return None

def get_all_playlist_tracks(sp, playlist_id):
    tracks = []
    results = sp.playlist_tracks(playlist_id)
    tracks.extend(results['items'])
    while results['next']:
        results = sp.next(results)
        tracks.extend(results['items'])
    return tracks

def get_duplicates(tracks):
    track_map = {}
    duplicates = {}
    for item in tracks:
        track = item['track']
        if not track:
            continue
        track_id = track['id']
        track_key = f"{track['name']} - {track['artists'][0]['name']}"
        if track_id in track_map:
            if track_key not in duplicates:
                duplicates[track_key] = [track_map[track_id]]
            duplicates[track_key].append(item['id'])
        else:
            track_map[track_id] = item['id']
    print("Duplicate tracks:", duplicates)
    return duplicates

def remove_duplicates(sp, playlist_id):
    playlist_tracks = get_all_playlist_tracks(sp, playlist_id)
    duplicates = get_duplicates(playlist_tracks)
    for item_ids in duplicates.values():
        sp.playlist_remove_items(playlist_id, item_ids[1:])

def main():
    scope = "playlist-read-collaborative playlist-modify-public playlist-modify-private"
    client_id = 'my client ID'
    client_secret = 'my client secret'
    redirect_uri = 'http://localhost:3036'
    sp = spotipy.Spotify(
        auth_manager=SpotifyOAuth(client_id=client_id, client_secret=client_secret, redirect_uri=redirect_uri,
                                  scope=scope))
    playlist_url = 'https://open.spotify.com/playlist/1x76RxwKGwGq5oP3xofc3o?si=710c91480cb64fb6'
    playlist_id = get_playlist_id(playlist_url)

    if playlist_id:
        remove_duplicates(sp, playlist_id)
    else:
        print("Fehler: Playlist-ID konnte nicht aus der URL extrahiert werden.")

if __name__ == "__main__":
    main()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 12:44:52