mcpField
S
spotifyscraper

spotifyscraper

本地服务
github.com/AliAkhtari78游戏娱乐32218 周前更新

关于 spotifyscraper

spotifyscraper 是用于获取 Spotify 公开元数据的 Python 库和 MCP 服务,也可读取歌词与播客文字稿。公开数据无需 API 密钥;歌词和文字稿需要可选的 Spotify 账户 Cookie。

主要功能

  1. 01读取曲目、专辑、艺人、播放列表和播客
  2. 02跨实体类型搜索
  3. 03通过 Cookie 获取歌词和播客文字稿
  4. 04提供同步与异步客户端
  5. 05提供可选命令行工具

适用场景

  1. 01为应用获取 Spotify 元数据
  2. 02搜索 Spotify 公开实体
  3. 03获取带时间信息的歌词或播客文字稿
  4. 04通过 MCP 向 AI Agent 提供 Spotify 数据

MCP 相关

可选的 spotifyscraper-mcp 服务向 MCP 客户端开放 SpotifyScraper 能力,包括批量工具和曲目视觉信息工具。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"aliakhtari78-spotifyscraper": {
"command": "uvx",
"args": [
"spotifyscraper"
],
"env": {
"SPOTIFY_SP_DC": "<SPOTIFY_SP_DC>"
}
}
}
}
启动命令uvx spotifyscraper
需要配置的环境变量
SPOTIFY_SP_DC密钥Optional sp_dc cookie that unlocks authenticated tools (lyrics, transcripts, account).

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
pypispotifyscraper3.9.2

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

SpotifyScraper

Live demo PyPI version Python versions Downloads CI Docs Container Maintained with Claude Code License: MIT GitHub stars

无需官方 API 或 API 密钥,即可提取公开的 Spotify 数据——曲目、专辑、艺人、播放列表和播客。

🎧 在浏览器中在线体验 → ——粘贴任意 Spotify 链接,查看 SpotifyScraper 如何提取类型化数据、封面图和试听片段,以及实现这一功能的完整 Python 代码。(了解构建过程。)

SpotifyScraper 会从 Spotify 自己的公开嵌入页面获取匿名令牌,并读取网页播放器使用的相同 JSON 端点,返回类型化的不可变模型。v3 是从头重写的版本,专注于可靠性和简洁、现代的 API。公开数据无需登录;可选的登录后功能(歌词、播客文字稿和账户信息)只需添加你自己的 Spotify sp_dc Cookie——无需密码或 API 密钥。

**从 v2 升级?**请参阅迁移指南。之前的版本仍保留在 v2.x 分支。

SpotifyScraper 与官方 API(spotipy)

spotipy 封装了 Spotify 的官方 Web API——如果你需要向用户的帐户写入数据,或读取私有数据/资料库数据,这是合适的选择。SpotifyScraper 读取 Web 播放器已公开的数据,因此无需任何设置。

SpotifyScraperspotipy(官方 API)
API 密钥/应用注册❌ 不需要✅ 必需
OAuth 流程❌ 不需要✅ 大多数数据都需要
速率限制配额/计费无Spotify 配额
同步和异步✅仅同步
完全类型化的不可变模型✅部分支持
歌词与播客转录文本✅(cookie)❌
面向 Claude/大模型 Agent 的 MCP 服务✅❌
写入/播放/私有数据❌(仅限公开数据,只读)✅

需要经过身份验证的写入操作和符合市场区域的数据时,请使用 spotipy;需要快速、免密钥地访问公开元数据、歌词和试听片段,以及可直接使用的 MCP 服务来连接 AI Agent 时,请使用 SpotifyScraper。

受到官方 API 弃用的影响? 自 2024 年 11 月起,Spotify 的 audio-features、recommendations 和 related-artists 端点已对新应用返回 403。SpotifyScraper 仍可在无需 API 密钥的情况下返回相关艺人和推荐内容。(它无法恢复 audio-features——Spotify 已从所有工具中彻底移除了这些数据。)

安装

pip install spotifyscraper                 # core (only depends on httpx)
pip install "spotifyscraper[media]"        # + cover/preview embedding (mutagen)
pip install "spotifyscraper[browser]"      # + Playwright browser fallback & login
pip install "spotifyscraper[cli]"          # + the spotifyscraper command-line tool
pip install "spotifyscraper[keyring]"      # + store the login cookie in the OS keyring
pip install "spotifyscraper[mcp]"          # + the spotifyscraper-mcp MCP server for LLM hosts
pip install "spotifyscraper[all]"          # everything

Python 3.10+。

快速入门

from spotify_scraper import SpotifyClient

with SpotifyClient() as client:
    track = client.get_track("https://open.spotify.com/track/4uLU6hMCjMI75M1A2tKUQC")
    print(track.name, "—", track.artists[0].name)
    print(track.duration_ms, "ms |", track.preview_url)

    print(track.to_dict())          # JSON-safe dict, if you prefer dicts

每种实体都有专属方法:get_track、get_album、get_artist、get_playlist、get_episode、get_show——每个方法都接受 URL、URI 或纯 ID。

异步
import asyncio
from spotify_scraper import AsyncSpotifyClient

async def main():
    async with AsyncSpotifyClient() as client:
        track, album = await asyncio.gather(
            client.get_track("4uLU6hMCjMI75M1A2tKUQC"),
            client.get_album("6N9PS4QXF1D0OWPk0Sxtb4"),
        )
        print(track.name, "|", album.name)

asyncio.run(main())
下载封面和试听片段
from spotify_scraper import SpotifyClient

with SpotifyClient() as client:
    track = client.get_track("4uLU6hMCjMI75M1A2tKUQC")
    client.download_cover(track, dest="covers/")
    client.download_preview(track, dest="previews/", embed_cover=True)  # needs [media]
本地化显示名称

传入 locale——一个 BCP-47 语言标签:可以是单独的语言子标签("de"、"ja"),也可以是语言-地区标签("ja-JP")——以本地化显示名称所用的语言。可以为客户端设置此项,也可以在每次调用时覆盖:

with SpotifyClient(locale="ja-JP") as client:        # default for every call
    track = client.get_track("4uLU6hMCjMI75M1A2tKUQC")
    other = client.get_track("4uLU6hMCjMI75M1A2tKUQC", locale="de-DE")  # per-call wins

此值会作为 Accept-Language 标头发送,只会改变名称的拼写。它不是国家/市场代码——单独的 "US" 作为语言没有意义,会被忽略——也不会筛选地区可用性或改变试听 URL:匿名访问 Spotify 时会根据请求 IP 确定国家/地区,其 pathfinder 会静默忽略 market 变量。真正的市场/可用性筛选需要经过身份验证的 Web API,本库并未实现此功能;如需获取特定地区的结果,请将客户端的 proxy 指向目标地区。请参阅本地化指南。

功能

  • 所有核心实体 + 播客 — 曲目、专辑、艺人、播放列表、节目、单集。
  • 搜索所有实体类型,并返回类型化的 SearchResults。
  • 榜单与发现 — 编辑精选榜单、相关艺人、完整的分页唱片目录和专辑推荐。
  • 封面颜色与 Canvas — 提取艺术作品的主题配色,并下载曲目的循环 Canvas 视频。
  • 署名与演唱会 — 演奏者/词曲作者/制作人,以及艺人即将举行的现场演出。
  • 公开用户资料 — get_user()(姓名、关注者数量、公开播放列表)。
  • MCP 服务 — 通过 spotifyscraper-mcp 向 Claude/大模型开放所有功能(批量工具 + 一次调用即可完成的 get_track_visuals);也提供 ghcr.io 上的容器版本。
  • 本地化显示名称 — 传入 BCP-47 语言标签(locale)以设置名称的语言。
  • 歌词与播客文字稿 — 通过 Cookie 认证、与时间同步,一个令牌即可用于两者。
  • 浏览器辅助登录 + 会话持久化 — 登录一次,之后即可无头运行(不存储密码)。
  • 感知账户状态 — get_account() / is_premium(),以及无需 Cookie 的 session_info()。
  • 批量辅助函数 — 复数形式的 get_*s([...]),提供可安全处理部分失败的结果,并管理并发。
  • 同步与异步客户端,共用一个无 I/O 核心。
  • 类型化的冻结模型,支持 JSON 安全的 to_dict() / from_dict()。
  • 双层弹性机制 — 使用 Spotify 的 GraphQL API,并在必要时自动回退到嵌入页面。
  • 仅依赖一个核心依赖项(httpx);媒体和浏览器支持为可选扩展。
  • 可选响应缓存 — 按需启用、持久化且令牌安全(仅缓存不含令牌的 pathfinder GET 请求)。
  • 内置防封禁机制 — 按主机限流、退避重试、轮换 UA、代理。
  • 通过 Playwright 提供浏览器回退,以便在需要真实浏览器时使用。

命令行

安装 cli 扩展后,即可使用 spotifyscraper 命令:

spotifyscraper track 4uLU6hMCjMI75M1A2tKUQC          # entity metadata as JSON
spotifyscraper playlist <id> --max-tracks 50 --pretty
spotifyscraper download preview <id> -o ./previews --embed-cover

每条命令都会输出 JSON,因此可以与 jq 等工具组合使用。请参阅 CLI 指南。

批量辅助函数

每个 getter 都有对应的复数形式(get_tracks、get_albums……),可获取多个输入,并为每个输入返回一个 BatchItem——索引一一对应;某个输入无效也不会中止其余请求:

items = client.get_tracks(["4uLU6hMCjMI75M1A2tKUQC", "bad-id"])
ok = [i.result for i in items if i.ok]
failed = {i.value: i.error for i in items if not i.ok}

异步客户端会并发运行这些请求,并受 max_concurrency 限制(默认为 5)。请参阅批量处理指南。

响应缓存

对于重复查询,可按需启用持久缓存。缓存只存储不含令牌的 pathfinder 响应——绝不缓存包含匿名令牌的嵌入页面——因此不会有任何凭据写入磁盘:

from spotify_scraper import SpotifyClient, CacheConfig, FileCache

with SpotifyClient(cache=CacheConfig(store=FileCache())) as client:
    client.get_track("4uLU6hMCjMI75M1A2tKUQC")   # first call hits the network
    client.get_track("4uLU6hMCjMI75M1A2tKUQC")   # served from the cache

默认 TTL 为 24h;FileCache 仅依赖标准库,后端可插拔。 请参阅缓存指南。

搜索

search() 会针对所有实体类型运行一次匿名聚合查询,并返回类型化的 SearchResults:

from spotify_scraper import SpotifyClient

with SpotifyClient() as client:
    results = client.search("daft punk", types=("track", "artist"), limit=5)
    print(results.total, "track matches")
    for track in results.tracks:
        print(track.name, "—", track.artists[0].name)

搜索结果内容较少(传入 id 调用 get_album()/get_show() 可获取完整实体); total 是匹配曲目的数量。请参阅 搜索指南。

歌词与文字稿

歌词和播客文字稿需要 Spotify 账户 Cookie(sp_dc);该库会为你处理令牌握手,一个 Cookie 即可用于两者:

from spotify_scraper import SpotifyClient

with SpotifyClient(cookies="cookies.txt") as client:   # or cookies={"sp_dc": "..."}
    lyrics = client.get_lyrics("4uLU6hMCjMI75M1A2tKUQC")
    for line in lyrics.lines:
        print(line.start_ms, line.text)

    transcript = client.get_transcript("07gKzPFkbvGF0cHoeG7ARS")   # a podcast episode
    for line in transcript.lines:
        print(line.start_ms, line.text)

你的 Cookie 只会发送给 Spotify,且绝不会被记录。没有文字稿的单集会引发 NotFoundError。请参阅 歌词与 Cookie 指南。

浏览器辅助登录

不想手动复制 Cookie?login() 会打开真实浏览器,你只需登录一次,捕获的 sp_dc 就会被保存(不会收集或存储密码)。之后的运行会以无头模式重新连接,非常适合服务器:

from spotify_scraper import SpotifyClient

with SpotifyClient() as client:
    client.login()                              # reuse a valid session, else open a browser
    print(client.get_lyrics("4uLU6hMCjMI75M1A2tKUQC").sync_type)

# A later, headless run — no browser needed:
with SpotifyClient.from_saved_session() as client:
    account = client.get_account()              # who am I?
    print(account.product, account.country, client.is_premium())
    transcript = client.get_transcript("07gKzPFkbvGF0cHoeG7ARS")

默认情况下,login() 会复用有效的已保存会话(只有第一次需要使用浏览器);from_saved_session() 则完全不需要 browser extra。Cookie 会存储在仅所有者可访问的文件中,或者存入操作系统密钥环(使用 store="keyring" 和 keyring extra)。get_account()/is_premium() 会报告已登录的账户,SpotifyClient.session_info() 则可在不暴露 Cookie 的情况下检查已保存的会话。请参阅已认证会话指南。

路线图

已发布

版本范围
3.0库:所有实体、分页、媒体下载、浏览器回退、文档
3.1命令行界面
3.2Cookie 身份验证歌词
3.3Cookie 身份验证播客文字稿(get_transcript);浏览器辅助登录、会话持久化与账户感知(get_account/is_premium)
3.4所有实体类型的搜索(search())· 显示语言本地化(locale)
3.5可选响应缓存(cache=CacheConfig(...))· 支持受管理并发的批处理辅助工具
3.6视觉与发现:封面颜色、Canvas 视频、排行榜、相关艺人、分页唱片目录、推荐、公开个人资料、曲目鸣谢、演唱会 · 一流的 MCP 服务 + 容器镜像
3.7MCP 批处理工具(get_tracks/get_albums/…)· 为视觉前端提供便捷工具 get_track_visuals
3.8维护:依赖项、工具链与 CI 现代化(所有 Actions 均使用当前主版本并固定 SHA)· 文档与 PyPI 反向链接
3.9发布至官方 MCP 注册表(并支持 Glama/mcp.so/PulseMCP/Smithery 发现)· “vs spotipy” 对比 · 一次性、可选择退出的 CLI 点星提示

接下来 — 未来计划会记录在 GitHub 里程碑和 问题中 — 👍 或就你最关注的事项发表意见。计划范围可能会有变更。

可靠性与维护

此库依赖 Spotify 自身的公共端点,因此 Spotify 更改端点时可能会导致其失效。为确保可靠性:

  • 我们每天都会运行一次金丝雀测试,针对 Spotify 运行实时测试套件。端点发生变化时,它会自动创建 spotify-breakage 问题(并在恢复后关闭),让回归问题在影响到你之前就能显现。
  • 在维护者审核下,我们会借助 Claude Code(Anthropic 的编码 Agent)迅速分类并修复故障——这套由 Agent 辅助的工作流也推动着本项目持续发展。持久化查询哈希集中在一个文件(api/pathfinder.py)中,因此 Spotify 轮换哈希时只需修改一行。
  • 每项更改都要通过 ruff + mypy --strict + 隔离测试套件(覆盖率至少 85%),并在 Linux、macOS 和 Windows 上使用 Python 3.10–3.13 进行测试。

如果你遇到了问题,请提交问题——监控通常已经发现了这些问题。

文档

完整文档、指南和 API 参考:https://spotifyscraper.readthedocs.io

MCP 服务也提供容器版本: docker run -p 8000:8000 ghcr.io/aliakhtari78/spotifyscraper(设置 SPOTIFY_SP_DC 以启用需要身份验证的工具)。

法律声明

SpotifyScraper 是一个非官方的独立项目,与 Spotify 无关联。它读取公开可用的数据以及 Spotify 发布的约 30 秒试听片段;不会下载完整曲目,也不会规避 DRM。请将其用于教育和个人用途,并遵守 Spotify 的服务条款。请参阅法律声明。

贡献

欢迎贡献——请参阅 CONTRIBUTING.md。本项目采用基于规范优先的方式开发,并使用 OpenSpec;规范位于 openspec/。

Star 历史

如果 SpotifyScraper 帮你省去了官方 API 的 OAuth 流程,点个 ⭐ 能帮助其他开发者发现它,也能告诉我应该继续开发哪些功能。

AliAkhtari78/SpotifyScraper 的 Star 历史

许可证

MIT © Ali Akhtari — 全栈 AI 工程师(aliakhtari.com)。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。