Featured image of post Apple Music 曲库迁移

Apple Music 曲库迁移

将 Apple Music 日区账户资料库内的歌曲 / 专辑迁移到中国大陆区账户内的方法

背景

刚上大学的时候,我考虑到日区的 Apple Music 版本可选的歌曲更多,而且各种服务也更给力[1]。 于是我就开通了日区的会员,因为有学生优惠,每月也就花 580 日元(约 25 人民币)。 但现在毕业在即,我开始怀疑我到研究生阶段还能不能继续享受这个优惠。而日区会员原价要每月 1080 日元(约 50 人民币),这超出我的可接受范围了。 此外,最近淘宝上苹果日区 App Store 的充值卡不是很好找,而我日区账户的余额也要见底了。 所以,是时候换个平台了。

然而,国内的音乐平台的社交属性太强,我个人不太喜欢这些,觉得太热闹了[2]。 相对而言,Apple Music 则更专注于音乐本身,而且跟苹果生态融合的更好,所以我最后还是选择了转到 Apple Music 的中国大陆区(国区)。

我有两个苹果账户,一个在国区、一个在日区,于我而言这里的“转区”就是将后者资料库的所有歌曲添加到前者的资料库中。 考虑到 Apple Music 国区的版权库不如日区,我并不要求将其全部迁移,只要能将大部分歌曲复制到目标账户的资料库里就行。

我能搜到的成熟的工具不是满足不了我的需求就是需要收费,因此我决定自己探索迁移曲库的方法。本文的方法分为两步:

  1. 从源账户获取歌曲
  2. 将歌曲添加到新账户

这需要操作者有一定的编程和爬虫基础,本文只是讲述我的思路和操作流程,我也没有将其整理成通用的代码的想法,文中的脚本需要根据实际情况修改后才可以正常使用。 本文的方法与账户所在的区域无关,因此理论上也适用于其它区域间的和相同区域不同账户之间的迁移。

第一步:从源账户获取歌曲

我积累了四年的账户里有歌曲 8441 首,它们分布在 1820 张专辑内,所以以专辑为单位迁移更合理一些。

得益于 Apple Music 的网页端,获取相关的 API 并不是什么难事:

  1. 在浏览器内的 Apple Music网页端登录源账户,打开调试工具,切换到 Network 页,过滤出 XHR 请求。
  2. 点击“专辑/Albums”切换到专辑页,这时在调试工具内应该会出现一条 amp-api 开头的请求:
  3. 右键这条请求,Copy -> Copy as cURL,复制到终端内尝试重放请求,在我这里成功了,说明苹果并没有做各种弯弯绕绕的反爬措施,好评。

这个API响应的结构大致如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
{
    "data": [...],
    "resources": {
        "library-albums": {...},
        "albums" : {...},
        "library-artists": {...},
        "artists": {...}
    },
    "meta": {...}
}

有了 API 之后就可以循环请求获取完整列表了:

  1. 请求参数里的 offset 项指定了偏移量,通过不断改变这个值可以获取完整的专辑列表。
  2. 在响应json最后的 meta 项里有订阅的专辑总数,在我这里是 "meta": {"total": 1820, ...},即1820条,请求参数内 limit=100 也就是每页有 100 条。根据这两个数值可以算出一共有 19 页,要请求 19 次。我也尝试了调高 limit,发现 limit>100 时 API 会返回错误。
  3. 将前面复制的 curl 指令放到 .sh 脚本内,写一个循环,例如:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
......
for i in {0..18}; do
chunk="${i}00"
curl "https://amp-api.music.apple.com/.../...&offset=$chunk&..." \
    --compressed \
    ......
    -H 'Sec-Fetch-Site: same-site' \
    -H 'TE: trailers' \
    -o "chunk$chunk.json" # 把响应输出到文件
sleep 10  # 避免请求间隔太短导致被 ban
done
  1. 在终端用 bash 运行这个脚本,不一会资料库内的所有专辑的信息就都被保存到本地的 json 文件内了。

第二步:将歌曲添加到新账户

和上面类似,首先获取添加专辑的 API:

  1. 切换到目标账户,打开调试工具,切换到 Network 页,过滤出 XHR 请求。
  2. 在首页上随便找个专辑添加到资料库内,在调试工具内定位到这条请求:
  3. 同上,复制 curl 指令到终端内尝试重放,成功。

分析请求 URL:

1
https://amp-api.music.apple.com/v1/me/library?art[url]=f&format[resources]=map&ids[albums]=1725057905&representation=ids

其中的 1725057905 对应之前获取到的 json 文件里 resources.albums 内的每个属性的名称,也就是每个专辑的 ID。 由于 URL 内 ID 是复数 ids,我便猜测能否同时添加多个专辑,将URL中的 1725057905 替换为 398320584,322934943,重新发送请求,居然也成功了,说明我的猜测是对的。

有了这些基础,编写脚本就很容易了,首先使用 jq 解析之前保存的响应 json,提取出其中 resources.albums 内每一项的键值,使用逗号分隔输出并拼接到 url 内:

1
2
3
jqs=".resources.albums | keys[${section}] | [ .[] | tonumber ] | @csv"
ids="$(cat chunk${index}00.json | jq -r "$jqs" )"
url="https://amp-api.music.apple.com/.../...&ids%5Balbums%5D=$ids&..."

放到之前的 curl 请求内,加上循环组成脚本,脚本里对每个 chunk 分段请求是因为一次增加 100 张专辑请求的响应会很慢:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
......
for index in {0..18}; do
for section in ':25' '25:50' '50:75' '75:'; do

jqs=".resources.albums | keys[${section}] | [ .[] | tonumber ] | @csv"
ids="$(cat chunk${index}00.json | jq -r "$jqs" )"
url="https://amp-api.music.apple.com/v1/me/library?art%5Burl%5D=f&format%5Bresources%5D=map&ids%5Balbums%5D=$ids&representation=ids"

curl -X POST "$url" \
    -H "$ua" \
    -H 'Accept: */*' \
    ......
    -H 'Content-Length: 0' \
    -H 'TE: trailers'
echo
sleep 10  # 避免请求间隔太短导致被 ban
done
done

之后运行这个脚本,就可以看到自己源账户里的歌曲被慢慢添加到目标账户里了。

哪些歌曲没成功迁移

仿照第一步获取目标账户的所有专辑,然后写一些脚本就能看到有哪些歌曲没被成功迁移了,例如这个 python 程序:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import json
def getalbums(count: int, fn: str) -> dict:
    albums = {}
    for index in range(count):
        filename = fn.format(index)
        data = json.load(open(filename))
        for k,v in data["resources"]["albums"].items():
            albums[int(k)] = v["attributes"]["name"] + ' | ' + v["attributes"]["artistName"]
    return albums

org_album = getalbums(19, "chunk{}00.json")
dest_album = getalbums(15, "after-chunk{}00.json")
ids = set(org_album) - set(dest_album)
for i in ids:
    print(f"{i}:",org_album[i])
print(len(ids))

我一共有 338 张专辑没有被成功迁移,这主要有三种情况:

  1. Apple Music 国区没版权;
  2. 没有一模一样的,但是有不同版本的;
  3. 国区和日区都有,但是 ID 不同,例如 RADWIMPS 和 HOYO-MiX 的专辑。

其中后两者靠手动搜索也可以慢慢添加回去,如果遇到了第一种那就真的没办法了。

参考资料

本文基于CC BY-NC-SA 4.0 协议发布。本文不可商用,转载时请注明出处并使用相同协议
使用 Hugo 构建
主题 StackJimmy 设计