XVIT

Jun 12, 2026

酷狗接口分析

1. 前情提要

作为开发者/数据采集者,我们通常会使用 python 去爬取一些数据,比如音乐、视频、文本、图片等。那么,我们如何获取这些数据呢?这就需要我们分析接口了。这次的文章,我们就来分析一下酷狗音乐的数据接口。

2. 分析接口

我们要分析的是酷狗的搜索接口,首先搜索一下音乐,之后打开开发工具选择Network,这里会显示我们访问网站所调用的所有接口和代码文件。

酷狗搜索接口分析1

一顿操作猛如虎,发现我们需要的数据接口存放在下面的接口里

1
https://complexsearch.kugou.com/v2/search/song?callback=callback123&srcappid=2919&clientver=1000&clienttime=1781260420114&mid=a6650f8f76d9557ffa4f82121c0d2a34&uuid=a6650f8f76d9557ffa4f82121c0d2a34&dfid=0RB1xg34c8cU0B44j10kLflE&keyword=run%C2%A0wild%EF%BC%88%E5%90%91%E9%A3%8E%E8%80%8C%E9%87%8E%EF%BC%89&page=1&pagesize=30&bitrate=0&isfuzzy=0&inputtype=0&platform=WebFilter&userid=0&iscorrection=1&privilege_filter=0&filter=10&token=&appid=1014&signature=f7fa2d1192ce820c115c1973ca816ced

因为我们的主要目标是通过代码实现批量爬取或者自动化爬取数据,所以对于接口中的每一个参数都要弄明白具体是啥原理。接下来我先把需要变动的param参数整理成表格,方便大家理解:

参数名 参数值 参数含义
clienttime 1781260420114 客户端时间
mid a6650f8f76d9557ffa4f82121c0d2a34 媒体id
uuid a6650f8f76d9557ffa4f82121c0d2a34 uuid
dfid 0RB1xg34c8cU0B44j10kLflE 用户登录Token
keyword 内容 搜素关键词
signature f7fa2d1192ce820c115c1973ca816ced 加密后的参数

3. 分析参数

3.1 clienttime

这个参数说白了就是请求的时间,用python实现的话代码如下:

1
2
3
import time        # 必须要引入time模块
clienttime = int(time.time() * 1000) # 经过代码分析参数的时间戳长度是13位,所以乘以1000

3.2 mid & uuid

这两个参数是随机生成的参数,具体的代码我们可以使用搜索法,在图片所示的地方,搜索关键字mid或者uuid之后搜索。

酷狗搜索接口分析2

我们发现生成的代码在getBaseInfo.min.js的js代码中,之后我们分析这个js代码可以找到生成代码s.mid = d.getKgMid() 这个代码是生成mid之后赋值给mid,所以需要推出这个代码生成逻辑,把这个函数复制到搜索那里去搜索这个函数位置。搜索发现这个函数还是在getBaseInfo.min.js中,我们点击这个函数跳转到函数位置发现代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
getKgMid: function() {
var e = d.Cookie.read("kg_mid");
if (navigator.cookieEnabled) {
if (d.IsEmpty(e)) {
var n = d.Guid()
, e = d.Md5(n);
try {
d.Cookie.write("kg_mid", d.Md5(n), 864e6, "/", "kugou.com")
} catch (e) {}
}
} else {
var t = navigator.userAgent
, i = function() {
var e = navigator.plugins
, n = "";
if (0 < e.length) {
for (var t = [], i = 0, r = e.length; i < r; i++) {
var o = e[i].name;
t.push(o)
}
n = t.toString()
}
return n
}()
, r = screen.width + "x" + screen.height
, o = screen.colorDepth || ""
, a = screen.pixelDepth || ""
, n = function() {
var e = ["canvas"];
try {
var n, t = document.createElement("canvas");
t.getContext && t.getContext("2d") && (t.width = 200,
t.height = 200,
t.style.display = "inline",
(n = t.getContext("2d")).rect(0, 0, 10, 10),
n.rect(2, 2, 6, 6),
e.push("canvas winding:" + (!1 === n.isPointInPath(5, 5, "evenodd") ? "yes" : "no")),
n.textBaseline = "alphabetic",
n.fillStyle = "#f60",
n.fillRect(125, 1, 62, 20),
n.fillStyle = "#069",
n.font = "14px 'Arial'",
n.fillText("hello kugou", 2, 15),
n.fillStyle = "rgba(102, 204, 0, 0.2)",
n.font = "18pt Arial",
n.fillText("hello kugou", 4, 45),
n.globalCompositeOperation = "multiply",
n.fillStyle = "rgb(255,0,255)",
n.beginPath(),
n.arc(50, 50, 50, 0, 2 * Math.PI, !0),
n.closePath(),
n.fill(),
n.fillStyle = "rgb(0,255,255)",
n.beginPath(),
n.arc(100, 50, 50, 0, 2 * Math.PI, !0),
n.closePath(),
n.fill(),
n.fillStyle = "rgb(255,255,0)",
n.beginPath(),
n.arc(75, 100, 50, 0, 2 * Math.PI, !0),
n.closePath(),
n.fill(),
n.fillStyle = "rgb(255,0,255)",
n.arc(75, 75, 75, 0, 2 * Math.PI, !0),
n.arc(75, 75, 25, 0, 2 * Math.PI, !0),
n.fill("evenodd"),
t.toDataURL && e.push("canvas fp:" + t.toDataURL()))
} catch (e) {}
return d.Md5(e.toString())
}();
e = d.Md5(t + i + r + o + a + n)
}
return e
},

分析代码我们发现大部分都是废话,最核心的代码是:

1
var n = d.Guid(), e = d.Md5(n);

他的意思是调用Guid函数生成一个唯一的随机字符串,之后调用md5函数对这个字符串加密,再结合前面他会被赋值给miduuid。改成python实现方法为:

1
2
3
4
5
6
7
import uuid                                             # 导入uuid
import hashlib # 导入hashlib

def get_mid(): # 定义生成mid函数
uid = uuid.uuid4().hex # 生成一个随机的uuid
mid = hashlib.md5(uid.encode("utf-8")).hexdigest() # 对uuid进行md5加密
return mid # 返回mid 这里的mid也是uuid的值

3.3 dfid

这个参数是通过cookie获取,这个的话可以手动通过开发工具去拉取,在一段时间内这个是不会像其他参数一样短期过期的。

3.4 keyword

这个就不用说了,就是搜索的关键词。

3.5 signature

这个参数发有说法,他是对前面的所有参数的一个加密,具体需要的参数是除了signature以外的所有的param参数,这个参数从长度来看大概是md5加密,但是他加密的参数获取需要我们断点来调试。我们使用搜索功能搜索signature参数,我们发现搜出来很多,先从infSign.min.js去找,右键选择open in sources panel,这时候会跳转到sources面板中。之后我们在l.signature = d(s.join(""))这里打断点,如图所示:

酷狗搜索接口分析3

接下来刷新网页会在我们断点处停止,我们在右侧发现如图圈起来的部分就是加密需要的所有参数:

酷狗搜索接口分析4

1
2
3
4
5
6
7
8
9
10
11
12
[
"NVPh5oo715z5DIWAeQlhMDsWXXQV4hwt",
"appid=1014",
"clienttime=1781266187",
"clientver=1000",
"dfid=0RB1xg34c8cU0B44j10kLflE",
"mid=a6650f8f76d9557ffa4f82121c0d2a34",
"srcappid=2919",
"uuid=1781266186835",
"{\"userid\":0,\"plat\":103,\"m_type\":0,\"vip_type\":0,\"own_ads\":{}}",
"NVPh5oo715z5DIWAeQlhMDsWXXQV4hwt"
]

这里的参数除了我们上面提到的,其他的都保持不变即可,接下来我们就可以编写signaturepython实现方法了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import hashlib

signList = [
"NVPh5oo715z5DIWAeQlhMDsWXXQV4hwt",
"appid=1014",
"clienttime=1781266187",
"clientver=1000",
"dfid=0RB1xg34c8cU0B44j10kLflE",
"mid=a6650f8f76d9557ffa4f82121c0d2a34",
"srcappid=2919",
"uuid=1781266186835",
"{\"userid\":0,\"plat\":103,\"m_type\":0,\"vip_type\":0,\"own_ads\":{}}",
"NVPh5oo715z5DIWAeQlhMDsWXXQV4hwt"
]

signature = hashlib.md5("".join(signList).encode("utf-8")).hexdigest() # 对signList进行md5加密

4. 总结

通过上面的分析,我们知道了酷狗搜索接口的参数获取方法,接下来就可以编写爬虫了,这里就不做展示了。酷狗现在的接口相比之前确实有所改变,以前的miduuidclienttime是一样的都是时间戳,后续改成uuidmd5了,不过这些参数的获取方法都是一样的。

< NEWER