misiektoja/lastfm_monitor
GitHub: misiektoja/lastfm_monitor
一个基于 Python 的 Last.fm 实时监听追踪工具,支持 Spotify 自动播放、邮件通知、CSV 数据导出和年度收听统计分析。
Stars: 26 | Forks: 5
# lastfm_monitor
-u "your_lastfm_api_key" -w "your_lastfm_api_secret"
```
或者,如果您是[手动安装](#manual-installation)的:
```
python3 lastfm_monitor.py -u "your_lastfm_api_key" -w "your_lastfm_api_secret"
```
要获取所有支持的命令行参数/标志列表:
```
lastfm_monitor --help
```
## 配置
### 配置文件
大多数设置都可以通过命令行参数进行配置。
如果您想持久化存储配置,可以生成一个默认的配置模板并将其保存到名为 `lastfm_monitor.conf` 的文件中:
```
lastfm_monitor --generate-config > lastfm_monitor.conf
```
编辑 `lastfm_monitor.conf` 文件并更改所需的配置选项(每个选项都有详细的注释)。
**v2.3 新增:** 配置文件包含在控制台和邮件输出中启用/禁用音乐服务 URL(Last.fm、Spotify、Apple Music、YouTube Music、Amazon Music、Deezer、Tidal)和歌词服务 URL(Genius、AZLyrics、Tekstowo.pl、Musixmatch、Lyrics.com)的选项。
**v2.5 新增:** [曲目时长](#getting-track-duration-from-spotify)和[自动播放](#automatic-playback-of-listened-tracks-in-the-spotify-client)功能在配置了可选的 app 凭据时,使用官方的 OAuth app Web API。匿名的 web-player backend 是新的自动备用方案,不需要 Spotify 凭据。
### Last.fm API Key 和 Shared Secret
- 在此创建您的 Last.fm `API key` 和 `Shared secret`:[https://www.last.fm/api/account/create](https://www.last.fm/api/account/create)
- 或者从以下位置获取现有凭据:[https://www.last.fm/api/accounts](https://www.last.fm/api/accounts)
- 使用以下方法之一提供 `LASTFM_API_KEY` 和 `LASTFM_API_SECRET` 密钥:
- 在运行时使用 `-u` / `--lastfm-api-key` 和 `-w` / `--lastfm-secret` 传入
- 将其设置为[环境变量](#storing-secrets)(例如 `export LASTFM_API_KEY=...; export LASTFM_API_SECRET=...`)
- 将其添加到 [.env 文件](#storing-secrets)(`LASTFM_API_KEY=...` 和 `LASTFM_API_SECRET=...`)以供持久使用
- 备用方案:在代码或配置文件中硬编码
如果您将 `LASTFM_API_KEY` 和 `LASTFM_API_SECRET` 存储在 dotenv 文件中,您可以更新它们的值,并向进程发送 `SIGHUP` 信号以重新加载包含新密钥值的文件,而无需重启工具。更多信息请参见[存储密钥](#storing-secrets)和[信号控制 (macOS/Linux/Unix)](#signal-controls-macoslinuxunix)。
### 用户隐私设置
为了监控 Last.fm 用户的活动,需要在被监控的用户帐户上启用适当的隐私设置。
用户应前往 [Last.fm 隐私设置](https://www.last.fm/settings/privacy)。
应禁用 **Hide recent listening information** 设置。
否则,您将收到 `pyLast` 库返回的错误消息:*'Login: User required to be logged in'*。
### Spotify Metadata Backends
[曲目时长功能](#getting-track-duration-from-spotify)和[自动播放功能](#automatic-playback-of-listened-tracks-in-the-spotify-client)都需要 Spotify 曲目元数据:
- 时长查找需要 Spotify 曲目时长
- 自动播放需要 Spotify 曲目 ID,以便本地 Spotify 客户端知道要播放哪首曲目
Spotify app 凭据对这两个功能都不是强制性的。该工具可以从匿名的 web-player backend 获取所需的元数据。如果您配置了 OAuth app 凭据,则会优先尝试官方的 Spotify Web API。
2.5 版本使用以下元数据顺序:
1. 通过可选的 OAuth app Client Credentials 进行官方 Spotify Web API 搜索
2. 匿名 web-player 搜索和 Pathfinder `getTrack` 元数据
3. Last.fm 时长作为最后的备用方案
#### 可选的 Spotify OAuth App 设置
如果您希望官方的 Spotify Web API 成为主要的元数据 backend,请按照以下步骤操作:
1. 登录 [Spotify Developer Dashboard](https://developer.spotify.com/dashboard)
2. 选择 **Create app**
3. 输入应用名称和描述
4. 对于 **Redirect URI**,输入 `http://127.0.0.1:1234`
- Client Credentials 流程不会重定向用户,但 Spotify 的应用表单需要一个重定向 URI
- 请完全按照显示的数字回环地址使用,因为 Spotify 不允许 `localhost`
5. 在 API 选择下,选择 **Web API**
6. 接受 Spotify 的开发者服务条款并创建应用
7. 打开应用设置
8. 复制 **Client ID**
9. 选择 **View client secret** 并复制 **Client Secret**
Spotify 目前要求 Development Mode 应用的所有者拥有有效的 Spotify Premium 订阅。有关当前的限制,请参阅 Spotify 的 [2026 年 2 月 Development Mode 迁移指南](https://developer.spotify.com/documentation/web-api/tutorials/february-2026-migration-guide)。
使用以下方法之一提供 `SP_CLIENT_ID` 和 `SP_CLIENT_SECRET`:
- 在运行时使用 `-z` / `--spotify-creds` 传入
- 使用 `SP_CLIENT_ID:SP_CLIENT_SECRET` 格式,值之间用冒号分隔
- 将它们设置为[环境变量](#storing-secrets),例如 `export SP_CLIENT_ID=...` 和 `export SP_CLIENT_SECRET=...`
- 将它们添加到 [dotenv 文件](#storing-secrets)中,格式为 `SP_CLIENT_ID=...` 和 `SP_CLIENT_SECRET=...`
- 将它们添加到 `lastfm_monitor.conf`
- 作为最后的备用方案,将它们硬编码在 `lastfm_monitor.py` 中
命令行示例:
```
lastfm_monitor -z "your_spotify_app_client_id:your_spotify_app_client_secret"
```
该工具会自动刷新 OAuth app 的 access token。token 缓存路径通过 `SP_TOKENS_FILE` 配置,默认为 `.lastfm-monitor-oauth-app.json`。将 `SP_TOKENS_FILE` 设置为空字符串以使用纯内存缓存。
如果您将 `SP_CLIENT_ID` 和 `SP_CLIENT_SECRET` 存储在 dotenv 文件中,您可以更新它们并发送 `SIGHUP` 来重新加载值,而无需重启工具。请参阅[存储密钥](#storing-secrets)和[信号控制](#signal-controls-macoslinuxunix)。
OAuth backend 依赖于 Spotipy 的过期感知 Client Credentials 缓存。它不会调用单独的 Web API endpoint 来验证 token。如果凭据缺失、token 检索失败或 OAuth 搜索返回不完整的元数据,匿名 backend 将自动运行。
该工具在生成所需的 v61 TOTP 参数之前会获取 Spotify 服务器时间。它将匿名 token 缓存直到其过期窗口,并从活动的 web-player bundle 中发现当前的 persisted-query hashes。遇到 HTTP 401 会刷新一次 token。被拒绝的 persisted query 会刷新一次其 hash。
v61 版本和 cipher bytes 作为 `SPOTIFY_TOTP_VERSION` 和 `SPOTIFY_TOTP_SECRET_CIPHER_BYTES` 配置选项提供。如果 Spotify 轮换了密钥,您可以使用 [spotify_monitor_secret_grabber](https://github.com/misiektoja/spotify_monitor/blob/dev/debug/spotify_monitor_secret_grabber.py) 工具从配置文件中更新它们,而无需更改代码。
Spotify 元提供曲目时长、标题、艺术家、专辑、URI 和外部 URL。当 Spotify Web 元数据不可用或不完整时,Last.fm 时长仍然是最后的备用方案。
使用 `-r` 时,来自任一 Spotify backend 的成功时长会标记为 `S*`。Last.fm 备用时长标记为 `L*`。如果不使用 `-r`,Last.fm 将仍然是时长来源,但 Spotify 元数据仍可以解析用于 `-g` 播放的 track ID。
### SMTP 设置
如果您想使用邮件通知功能,请在 `lastfm_monitor.conf` 文件中配置 SMTP 设置。
使用 `--send-test-email` 标志验证您的 SMTP 设置(工具将尝试发送一封测试邮件通知):
```
lastfm_monitor --send-test-email
```
### 存储密钥
建议将诸如 `LASTFM_API_KEY`、`LASTFM_API_SECRET`、`SP_CLIENT_ID`、`SP_CLIENT_SECRET` 或 `SMTP_PASSWORD` 等密钥存储为环境变量或 dotenv 文件。
在 **Linux/Unix/macOS/WSL** 系统上使用 `export` 设置所需的环境变量:
```
export LASTFM_API_KEY="your_lastfm_api_key"
export LASTFM_API_SECRET="your_lastfm_api_secret"
export SP_CLIENT_ID="your_spotify_app_client_id"
export SP_CLIENT_SECRET="your_spotify_app_client_secret"
export SMTP_PASSWORD="your_smtp_password"
```
在 **Windows 命令提示符** 上使用 `set` 代替 `export`,在 **Windows PowerShell** 上使用 `$env`。
或者,将它们持久化存储在 dotenv 文件中(推荐):
```
LASTFM_API_KEY="your_lastfm_api_key"
LASTFM_API_SECRET="your_lastfm_api_secret"
SP_CLIENT_ID="your_spotify_app_client_id"
SP_CLIENT_SECRET="your_spotify_app_client_secret"
SMTP_PASSWORD="your_smtp_password"
```
默认情况下,该工具会自动在当前目录及其上层目录中搜索名为 `.env` 的 dotenv 文件。
您可以使用 `DOTENV_FILE` 或 `--env-file` 标志指定自定义文件:
```
lastfm_monitor --env-file /path/.env-lastfm_monitor
```
您也可以使用 `DOTENV_FILE = "none"` 或 `--env-file none` 禁用 `.env` 自动搜索:
```
lastfm_monitor --env-file none
```
作为备用方案,您也可以将密钥存储在配置文件或源代码中。
## 用法
### 监控模式
要监控特定用户的活动,只需在命令行参数中输入 Last.fm 用户名(在下面的示例中为 `lastfm_username`):
```
lastfm_monitor
```
如果您尚未设置 `LASTFM_API_KEY` 和 `LASTFM_API_SECRET` 密钥,可以使用 `-u` 和 `-w` 标志:
```
lastfm_monitor -u "your_lastfm_api_key" -w "your_lastfm_api_secret"
```
要为单次运行提供可选的 Spotify OAuth app 凭据,请使用 `-z` / `--spotify-creds`:
```
lastfm_monitor -z "your_spotify_app_client_id:your_spotify_app_client_secret"
```
默认情况下,该工具会在以下位置查找名为 `lastfm_monitor.conf` 的配置文件:
- 当前目录
- 主目录 (`~`)
- 脚本目录
如果您按照[配置](#configuration)中的说明生成了配置文件,但将其保存在不同的名称或不同的目录下,您可以使用 `--config-file` 标志指定其位置:
```
lastfm_monitor --config-file /path/lastfm_monitor_new.conf
```
要启用对关注者和/或关注中变化的追踪:
- 将 `TRACK_FOLLOWERS` 和/或 `TRACK_FOLLOWINGS` 设置为 `True`
- 或使用 `--track-followers` 和/或 `--track-followings` 标志
```
lastfm_monitor --track-followers --track-followings
```
该工具将一直运行直到被中断(`Ctrl+C`)。使用 `tmux` 或 `screen` 以保持持久化。
您可以通过运行多个脚本副本来监控多个 Last.fm 用户。
该工具会自动将其输出保存到 `lastfm_monitor_.log` 文件中。可以通过设置中的 `LF_LOGFILE` 配置选项进行更改,或者通过 `DISABLE_LOGGING` / `-d` 标志完全禁用。
该工具还会将最后的活动信息(艺术家、曲目、时间戳)保存到 `lastfm__last_activity.json` 文件中,并将关注中和关注者的数量及列表保存到 `lastfm__followings.json` 和 `lastfm__followers.json` 文件中(如果启用了追踪),以便在工具重启时重用这些数据。
### 列出模式
该工具还有另一种模式,可以打印用户最近收听的曲目(`-l` 标志)。
您还可以添加 `-n` 标志来指定要显示多少首曲目,默认显示最后 30 首曲目:
```
lastfm_monitor -l -n 10
```
-l -n 10 -b lastfm_tracks_username.csv
```
### 邮件通知
要在用户变得活跃时启用邮件通知:
- 将 `ACTIVE_NOTIFICATION` 设置为 `True`
- 或使用 `-a` 标志
```
lastfm_monitor -a
```
要在用户变得不活跃时收到通知:
- 将 `INACTIVE_NOTIFICATION` 设置为 `True`
- 或使用 `-i` 标志
```
lastfm_monitor -i
```
不活跃邮件包含会话中的最近歌曲及其跳过和继续播放状态。通过 `INACTIVE_EMAIL_RECENT_SONGS_COUNT` 配置选项配置要包含的最近歌曲数量。
要在用户离线时出现新记录时收到通知:
- 将 `OFFLINE_ENTRIES_NOTIFICATION` 设置为 `True`
- 或使用 `-f` 标志
```
lastfm_monitor -f
```
要在播放受监控的曲目或专辑时收到邮件通知:
- 将 `TRACK_NOTIFICATION` 设置为 `True`
- 或使用 `-t` 标志
要使用此功能,您还需要创建一个包含您想要追踪的歌曲列表的文件(每行一首曲目或一张专辑)。使用 `MONITOR_LIST_FILE` 或 `-s` 标志指定该文件:
示例文件 `lastfm_tracks_username`:
```
we fell in love in october
Like a Stone
Half Believing
Something Changed
I Will Be There
```
如果需要,您可以使用 # 注释掉特定的行。
然后使用 `-t` 和 `-s` 标志运行该工具:
```
lastfm_monitor -t -s lastfm_tracks_username
```
要为用户收听的每一首歌曲启用邮件通知:
- 将 `SONG_NOTIFICATION` 设置为 `True`
- 或使用 `-j` 标志
```
lastfm_monitor -j
```
要在用户循环收听同一首歌曲时收到通知:
- 将 `SONG_ON_LOOP_NOTIFICATION` 设置为 `True`
- 或使用 `-x` 标志
```
lastfm_monitor -x
```
要禁用出错时发送邮件(默认启用):
- 将 `ERROR_NOTIFICATION` 设置为 `False`
- 或使用 `-e` 标志
```
lastfm_monitor -e
```
要在用户的关注者发生变化时收到通知:
- 将 `FOLLOWERS_NOTIFICATION` 设置为 `True`
- 或使用 `--notify-followers` 标志
```
lastfm_monitor --track-followers --notify-followers
```
要在用户的关注中(好友)发生变化时收到通知:
- 将 `FOLLOWINGS_NOTIFICATION` 设置为 `True`
- 或使用 `--notify-followings` 标志
```
lastfm_monitor --track-followings --notify-followings
```
只有在启用了追踪功能(`--track-followers` 和/或 `--track-followings` 标志)时,才会发送有关关注者和/或关注中变化的通知。
您还可以决定在 HTML 邮件通知的“Last played:” / “Track:”字段中使用 Last.fm 或 Spotify URL(请参阅 `USE_LASTFM_URL_IN_LAST_PLAYED` 配置选项)。
请确保您之前已经定义了 SMTP 设置(请参阅 [SMTP 设置](#smtp-settings))。
示例邮件:
-b lastfm_tracks_username.csv
```
如果文件不存在,将会自动创建。
### Last.fm Wrapped 工具
*[lastfm_wrapped.py](https://raw.githubusercontent.com/misiektoja/lastfm_monitor/refs/heads/main/tools/lastfm_wrapped.py)* 脚本根据 `lastfm_monitor.py` 创建的 CSV 文件生成 Spotify Wrapped 风格的统计数据。
它会分析您的收听数据,并提供包括指定时间段内的热门艺术家、曲目和专辑的见解。
**基本用法:**
默认情况下,它会生成当前年度的统计数据(1 月 1 日至 11 月 15 日,类似于 Spotify Wrapped):
```
python3 tools/lastfm_wrapped.py lastfm_tracks_username.csv
```
**自定义日期范围:**
您可以使用 `--from` 和 `--to` 标志指定自定义的日期范围:
```
python3 tools/lastfm_wrapped.py lastfm_tracks_username.csv --from 2024-01-01 --to 2024-12-31
```
**前 N 项:**
默认情况下,它会像 Spotify Wrapped 一样显示每个类别中的前 5 项。您可以使用 `--top-n` 标志进行更改:
```
python3 tools/lastfm_wrapped.py lastfm_tracks_username.csv --top-n 10
```
**示例输出:**
该工具会显示:
- 该时间段内的总 scrobble 数
- 热门艺术家(按播放次数)
- 热门曲目(按播放次数)
- 热门专辑(按播放次数)
### 在 Spotify 客户端中自动播放收听的曲目
如果您希望该工具在您的本地 Spotify 客户端中自动播放用户收听的曲目:
- 将 `TRACK_SONGS` 设置为 `True`
- 或使用 `-g` 标志
```
lastfm_monitor -g
```
您的 Spotify 客户端需要已安装并正在运行,此功能才能起作用。
自动播放需要为每个 scrobble 提供一个 Spotify track ID。该工具通过 [Spotify metadata backends](#spotify-metadata-backends) 解析该 ID。它会在配置了凭据时优先尝试官方的 OAuth app Web API,然后使用匿名的 web-player backend。OAuth app 凭据是可选的。
本地播放操作本身使用配置好的平台方法,例如 macOS 上的 AppleScript 或 Linux 上的 D-Bus。它不使用 Spotify Web API 播放控制。
该工具在 **Linux** 和 **macOS** 上完全支持自动播放。这意味着它会自动播放更改后的曲目。它还会根据被追踪用户的操作自动暂停和恢复播放。此外,一旦用户变得不活跃,它可以暂停或播放指定的曲目(请参阅 `SP_USER_GOT_OFFLINE_TRACK_ID` 配置选项)。
对于 **Windows**,它以半自动的方式工作:如果您正在运行 Spotify 客户端且没有收听任何歌曲,那么第一首曲目会自动播放。但是,随后的曲目会在客户端中定位,但您需要手动按下播放按钮。
您可以使用相应的配置选项更改每个平台的播放方法。
对于 **macOS**,将 `SPOTIFY_MACOS_PLAYING_METHOD` 设置为以下值之一:
- "**apple-script**"(推荐,**默认**)
- "trigger-url"
对于 **Linux**,将 `SPOTIFY_LINUX_PLAYING_METHOD` 设置为以下值之一:
- "**dbus-send**"(最常见,**默认**)
- "qdbus"(如果 dbus-send 不起作用请尝试)
- "trigger-url"
对于 **Windows**,将 `SPOTIFY_WINDOWS_PLAYING_METHOD` 设置为以下值之一:
- "**start-uri**"(推荐,**默认**)
- "spotify-cmd"
- "trigger-url"
推荐的默认设置应该适用于大多数人。
### 进度指示器
如果您希望看到一个实时进度指示器,显示用户当前正在收听曲目的精确分钟和秒数:
- 将 `PROGRESS_INDICATOR` 设置为 `True`
- 或使用 `-p` 标志
```
lastfm_monitor -p
```
-r
```
曲目时长通过 [Spotify metadata backends](#spotify-metadata-backends) 解析。在配置了凭据时,会优先尝试官方的 OAuth app Web API。接下来运行匿名的 web-player backend。只有当两个 Spotify backend 都失败或返回不完整的元数据时,才会使用 Last.fm 时长。
您可以判断曲目时长是否来自 Spotify,因为它在末尾带有 S* 后缀(例如 **3 minutes 42 seconds S\***),而那些来自 Last.fm 的带有 L*(例如 **2 minutes 13 seconds L\***)。
您可以通过 `-q` 标志禁用显示曲目时长标记(L* S*)。
```
lastfm_monitor -r -q
```
如果禁用了从 Spotify 检索曲目时长的功能,则不会显示时长标记。
### Spotify 中的私密模式检测
该工具包含检测 Spotify 中何时可能使用私密模式的功能,甚至会估算其使用时长。它默认启用且不可配置。
它并非 100% 准确。我观察到,当使用私密模式时(尤其是长时间使用),通常会在禁用私密模式后导致 Last.fm 帐户中创建许多重复记录。这会导致不同的曲目具有相同的开始时间戳。
我怀疑这与 Spotify 中的一个错误有关,并且主要发生在用户于多个设备上使用 Spotify 时。
但是,请记住,这并非 100% 准确。我曾观察到即使私密模式也会出现重复记录,但在这种情况下,重复记录的数量是有限的。因此,不要将其视为绝对确定的事情,但它是私密模式是否被使用过的一个非常好的指标。
-k 2 -c 10
```
* `LASTFM_ACTIVE_CHECK_INTERVAL`, `-k`: 用户在线时的检查间隔,即当前正在播放时(秒)
* `LASTFM_CHECK_INTERVAL`, `-c`: 被视为用户离线时的检查间隔,即没有播放音乐时(秒)
如果您想更改将用户标记为不活跃所需的时间(计时器在用户停止播放音乐后启动),请使用 `-o` 标志(或 `LASTFM_INACTIVITY_CHECK` 配置选项):
```
lastfm_monitor -o 120
```
关注者/关注中追踪功能使用单独的检查间隔,您可以通过 `FRIENDS_CHECK_INTERVAL` 配置选项或 `--friends-check-interval` 标志进行设置。这独立于音乐轮询间隔。
为了避免短暂的 API 故障导致的错误通知,只有在连续几次检查(默认:3 次)确认变化后,才会发送通知。您可以通过 `FRIENDS_CHANGE_COUNTER` 选项或 `--friends-change-counter` 标志进行配置。此设置还控制抑制重复错误消息的阈值。
您还可以通过 `FRIENDS_RETRY_INTERVAL` 配置选项或 `--friends-retry-interval` 标志配置在确认短暂变化或错误时使用的重试超时时间。
### 信号控制 (macOS/Linux/Unix)
该工具实现了多个信号处理程序,允许在不使用新的配置选项/标志重启工具的情况下更改工具的行为。
支持的信号列表:
| 信号 | 描述 |
| ----------- | ----------- |
| USR1 | 切换用户变得活跃/不活跃或出现新的离线记录时的邮件通知 (-a, -i, -f) |
| USR2 | 切换每首歌曲的邮件通知 (-j) |
| URG | 切换进度指示器的显示 (-p) |
| CONT | 切换追踪歌曲的邮件通知 (-t) |
| PIPE | 切换用户循环播放歌曲时的邮件通知 (-x) |
| TRAP | 增加不活跃检查计时器(增加 30 秒)(-o) |
| ABRT | 减少不活跃检查计时器(减少 30 秒)(-o) |
| HUP | 从 .env 文件重新加载密钥 |
使用 `kill` 或 `pkill` 发送信号,例如:
```
pkill -USR1 -f "lastfm_monitor "
```
由于 Windows 支持的信号数量有限,此功能仅在 Linux/Unix/macOS 上可用。
### 使用 GRC 为日志输出着色
您可以使用 [GRC](https://github.com/garabik/grc) 为日志着色。
添加到您的 GRC 配置 (`~/.grc/grc.conf`) 中:
```
# 监控日志文件
.*_monitor_.*\.log
conf.monitor_logs
```
现在将 [conf.monitor_logs](https://raw.githubusercontent.com/misiektoja/lastfm_monitor/refs/heads/main/grc/conf.monitor_logs) 复制到您的 `~/.grc/` 目录中,这样在使用 `grc` 工具时,日志文件应该会被漂亮地着色。
示例:
```
grc tail -F -n 100 lastfm_monitor_.log
```
## 更新日志
详情请参阅 [RELEASE_NOTES.md](https://github.com/misiektoja/lastfm_monitor/blob/main/RELEASE_NOTES.md)。
## 许可证
采用 GPLv3 授权。请参阅 [LICENSE](https://github.com/misiektoja/lastfm_monitor/blob/main/LICENSE)。
标签:Last.fm, Python, Spotify集成, 无后门, 自动化播放, 逆向工具, 音乐追踪