本文介绍如何安全、高效地从 spotify 流媒体历史 json 文件中删除特定艺术家(如 "doctor who")对应的播放记录,并支持批量处理多个文件,同时规避编码错误与迭代删除引发的索引异常。
本文介绍如何安全、高效地从 spotify 流媒体历史 json 文件中删除特定艺术家(如 "doctor who")对应的播放记录,并支持批量处理多个文件,同时规避编码错误与迭代删除引发的索引异常。
在处理 Spotify 导出的流媒体历史数据时,你常会面对大量结构化 JSON 数组(每个元素为一次播放记录)。若需批量清理某类内容(例如剔除所有 audiobook 条目——其 master_metadata_album_artist_name 为 "Doctor Who"),直接使用 list.pop() 边遍历边删除会导致索引错位、漏删或 IndexError;而未指定编码打开文件则极易触发 UnicodeDecodeError(如 charmap codec can't decode byte 0x9d)。以下是推荐的稳健实践方案:
✅ 正确做法:列表推导式 + 显式 UTF-8 编码 + 批量文件处理
import json
import glob
import os
def filter_json_by_artist(input_path: str, output_path: str, target_artist: str, field: str = "master_metadata_album_artist_name"):
"""从单个 JSON 文件中移除指定字段值匹配的条目,并保存为新文件"""
try:
# 关键:显式指定 encoding="utf-8" 避免解码错误
with open(input_path, "r", encoding="utf-8") as f:
data = json.load(f)
# 使用列表推导式安全过滤(不修改原列表,避免索引问题)
filtered_data = [
item for item in data
if item.get(field) != target_artist
]
# 写入新文件,保留可读格式
with open(output_path, "w", encoding="utf-8") as f:
json.dump(filtered_data, f, sort_keys=True, indent=2, ensure_ascii=False)
print(f"✅ 已处理 {len(data)} 条记录 → 保留 {len(filtered_data)} 条,已保存至 {output_path}")
except FileNotFoundError:
print(f"❌ 文件未找到:{input_path}")
except json.JSONDecodeError as e:
print(f"❌ JSON 解析失败:{input_path},错误:{e}")
except Exception as e:
print(f"❌ 处理失败:{input_path},异常:{e}")
# 批量处理多个 JSON 文件(例如所有 Streaming_History_*.json)
json_files = glob.glob("Streaming_History_Audio_*.json")
for file in json_files:
output_file = f"filtered_{os.path.basename(file)}"
filter_json_by_artist(file, output_file, target_artist="Doctor Who")⚠️ 注意事项与最佳实践
- 永远使用 with open(..., encoding="utf-8"):Spotify 导出文件通常含 Unicode 字符(如专辑名、艺术家名),Windows 默认 cp1252 编码无法解析,必须强制指定 UTF-8。
- 禁止边遍历边 pop() 或 remove():这会改变列表长度,导致跳过相邻元素(经典“漏删” bug)。应使用列表推导式或 filter() 构建新列表。
- 使用 .get(key) 而非直接 item[key]:防止因某些记录缺失该字段(如 null 或完全缺失)引发 KeyError。
- ensure_ascii=False:确保中文、特殊符号等能正常写入,避免 \uXXXX 转义。
- 错误处理不可省略:真实数据可能存在损坏 JSON、权限问题或空文件,健壮脚本需包裹 try/except。
✅ 扩展建议
- 若需多条件过滤(如同时排除 "Doctor Who" 和 "Audible"),可改用:
exclude_artists = {"Doctor Who", "Audible", "BBC Audio"} filtered_data = [item for item in data if item.get(field) not in exclude_artists] - 后续可结合 pandas 进行统计分析(如按艺术家播放时长排序),提升数据洞察力。
通过以上方法,你不仅能精准清理目标数据,还能构建可复用、易维护的批量预处理流程,为后续分析打下坚实基础。


















