文章目录
- 声明
- 目标
- 加密参数定位
- 翻页逻辑
- 代码实现
声明
本文章中所有内容仅供学习交流,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请私信我立即删除!
目标
复制curl转python
# -*- coding: UTF-8 -*-
import requests
import json
headers = {
"KG-DEVID": "164b01be4b8b37b759a0dbf7f918bc3e6f65ffd20a4f001014fa0e01f5706206732d46fdb3dff190338613e7e4e931b20ec20575366de8475843a37dc2a6617f7ed4b9ed6f921e60fb239462522c472163c2f6729e36147ba355dcde1b2d90edaafd32f1b75cccd9a6062fb77d91288d",
"KG-CLIENTTIMEMS": "1701247879527",
"KG-THash": "5d9e66d",
"User-Agent": "Android11-AndroidPhone-12069-130-0-COMMENT-wifi",
"KG-RC": "1",
"KG-FAKE": "0",
"KG-RF": "0098c118",
"Content-Type": "application/json; charset=utf-8",
"Host": "m.comment.service.kugou.com"
}
url = "http://m.comment.service.kugou.com/v1/cmtlist"
params = {
"code": "fc4be23b4e972707f36b8a828a93ba8a",
"clienttoken": "",
"signature": "9db81d03c35b714f6f73ec636a3d0a4c",
"mid": "334239931975782545528382737887498518928",
"uuid": "f3d96b13323b04867443a3eaa976c6d0",
"ret_cmt_card_media_info": "1",
"show_star_cmts": "1",
"hidden_cmt": "1",
"reply_version": "1",
"pagesize": "20",
"tag": "5",
"clienttime": "1701247879",
"gitversion": "796919f",
"ver": "10",
"area_code": "1",
"extdata": "bf7d67b1bc6d9f10891395fc8f6aa6dd",
"p": "1",
"dfid": "2TnT9N47Jln83dpfih1eheS3",
"fakem": "1acf321ea88ab1da9c093ce610001bc17a0d",
"appid": "1005",
"is_show_hot_word": "1",
"show_classify": "1",
"clientver": "12069",
"mixsongid": "411031988",
"kugouid": "0"
}
data = {}
data = json.dumps(data, separators=(',', ':'))
response = requests.post(url, headers=headers, params=params, data=data)
print(response.json())
本次主要是解决signature。
加密参数定位
直接搜索signature" 有很多结果:
点一个看着有点像的碰碰运气,点进去
hook一下这个getSign方法:
function main(){
Java.perform(function(){
let MusicSearchManager = Java.use("com.kugou.android.app.hicar.newhicar.voicesearch.MusicSearchManager");
MusicSearchManager["getSign"].implementation = function (str, map, map2) {
console.log(`MusicSearchManager.getSign is called: str=${str}, map=${map}, map2=${map2}`);
let result = this["getSign"](str, map, map2);
console.log(`MusicSearchManager.getSign result=${result}`);
return result;
};
})
}
setImmediate(main)
hook评论翻页也没没啥反应,看一下return返回的啥方法
hook 这个a方法看看
function main(){
Java.perform(function(){
let ba = Java.use("com.kugou.common.utils.ba");
ba["a"].overload('java.lang.String', 'java.lang.String').implementation = function (str, str2) {
let result = this["a"](str, str2);
console.log(`\nstr= ${str} \nstr2= ${str2}\nresult= ${result}`);
return result;
};
})
}
setImmediate(main)
有反应了
str= appid=1005&channel=130&platform=1&pluginVersion=0&singerName=Kiiiu_&songHash=AAC5EC2144CB3E479C135F9B3EDCDF28&songId=33983713&usemkv=1&version=12069*s&iN#G70*
str2= utf-8
result= 4a6813f2f51992f2f6ec4226adf92380
可以确定ba.a是个md5,
但是这个str和我们要找的评论接口相关性貌似不大,里面的参数都是写死的
并且后面再翻页就hook不到东西了,至此怀疑评论不走这个a方法。
事实证明:hook错了。。。
signature 是32位看着也像md5
再尝试一下,翻了一下这个ba文件,发现也有个b方法使用的md5
感觉可疑的就hook一下
function main(){
Java.perform(function(){
let ba = Java.use("com.kugou.common.utils.ba");
ba["b"].overload('java.lang.String').implementation = function (str) {
let result = this["b"](str);
console.log(`\nstr= ${str} \nresult= ${result}`);
return result;
};
})
}
setImmediate(main)
入参很像,柳暗花明又一村,撞大运.jpg
OIlwieks28dk2k092lksi2UIkpappid=1005area_code=1clienttime=1701228738clienttoken=clientver=12069code=fc4be23b4e972707f36b8a828a93ba8adfid=2TnT9N47Jln83dpfih1eheS3extdata=c5748b5b2fb966f28b9a71af8290497dfakem=1acf321ea88ab1da9c093ce610001bc17a0dgitversion=796919fhidden_cmt=1is_show_hot_word=1kugouid=0mid=334239931975782545528382737887498518928mixsongid=439217749p=1pagesize=20reply_version=1ret_cmt_card_media_info=1show_classify=1show_star_cmts=1tag=5uuid=f3d96b13323b04867443a3eaa976c6d0ver=10{}OIlwieks28dk2k092lksi2UIkp
验证一下是不是标准md5
比较加密结果一致,确定也是标准md5。
hook到的第3页的一组结果
// md5入参
OIlwieks28dk2k092lksi2UIkpappid=1005area_code=1clienttime=1701234156clienttoken=clientver=12069cmtreturnserver=%7B%22newindex%22%3A%7B%22cmts%22%3A%22%22%2C%22index%22%3A0%7D%2C%22all%5Fstart%5Findex%22%3A40%2C%22scid%22%3A%22188165003%22%2C%22r%5Fsort%5Findex%22%3A%5B%5D%2C%22weightlistcount%22%3A15%7Dcode=fc4be23b4e972707f36b8a828a93ba8adfid=2TnT9N47Jln83dpfih1eheS3extdata=c5748b5b2fb966f28b9a71af8290497dfakem=1acf321ea88ab1da9c093ce610001bc17a0dgitversion=796919fhidden_cmt=1is_show_hot_word=1kugouid=0mid=334239931975782545528382737887498518928mixsongid=439217749p=3pagesize=20reply_version=1ret_cmt_card_media_info=1show_classify=1show_star_cmts=1tag=5uuid=f3d96b13323b04867443a3eaa976c6d0ver=10{}OIlwieks28dk2k092lksi2UIkp
// MD5结果
44db349dca5586f2b947d4b452d1ba4d
入参按着url参数拆一下方便查看:
OIlwieks28dk2k092lksi2UIkp
appid=1005
area_code=1
clienttime=1701234156
clienttoken=
clientver=12069
cmtreturnserver=%7B%22newindex%22%3A%7B%22cmts%22%3A%22%22%2C%22index%22%3A0%7D%2C%22all%5Fstart%5Findex%22%3A40%2C%22scid%22%3A%22188165003%22%2C%22r%5Fsort%5Findex%22%3A%5B%5D%2C%22weightlistcount%22%3A15%7D
code=fc4be23b4e972707f36b8a828a93ba8a
dfid=2TnT9N47Jln83dpfih1eheS3
extdata=c5748b5b2fb966f28b9a71af8290497d
fakem=1acf321ea88ab1da9c093ce610001bc17a0d
gitversion=796919f
hidden_cmt=1
is_show_hot_word=1
kugouid=0
mid=334239931975782545528382737887498518928
mixsongid=439217749
p=3
pagesize=20
reply_version=1
ret_cmt_card_media_info=1
show_classify=1
show_star_cmts=1
tag=5
uuid=f3d96b13323b04867443a3eaa976c6d0
ver=10
{}OIlwieks28dk2k092lksi2UIkp
大部分都是定值。extdata就是作品的hash标识,p就是页数,clienttime是当前时间戳,
翻页逻辑
cmtreturnserver解码之后
第二页
{"newindex":{"cmts":"","index":0},"all_start_index":29,"scid":"188165003","r_sort_index":[],"weightlistcount":15}
第三页
{"newindex":{"cmts":"","index":0},"all_start_index":40,"scid":"188165003","r_sort_index":[],"weightlistcount":15}
第四页
{"newindex":{"cmts":"","index":0},"all_start_index":40,"scid":"188165003","r_sort_index":[],"last_page":{"last_index":30,"p":2},"weightlistcount":15}
第五页
{"newindex":{"cmts":"","index":0},"all_start_index":40,"scid":"188165003","r_sort_index":[],"last_page":{"last_index":56,"p":3},"weightlistcount":15}
第六页
{"newindex":{"cmts":"","index":0},"all_start_index":40,"scid":"188165003","r_sort_index":[],"last_page":{"last_index":82,"p":4},"weightlistcount":15}
第七页
{"newindex":{"cmts":"","index":0},"all_start_index":40,"scid":"188165003","r_sort_index":[],"last_page":{"last_index":104,"p":5},"weightlistcount":15}
没找到啥规律,经查看发现在上页的响应内容都有一个cmtreturnserver
请求下一页的时候携带上这个cmtreturnserver应该就可以实现翻页了。
至此以上所有流程基本都清晰了,接下来就是代码实现。
代码实现
# -*- coding: UTF-8 -*-
import time
import requests
import json
import hashlib
from urllib.parse import unquote
headers = {
"KG-DEVID": "164b01be4b8b37b759a0dbf7f918bc3e6f65ffd20a4f001014fa0e01f5706206732d46fdb3dff190338613e7e4e931b20ec20575366de8475843a37dc2a6617f7ed4b9ed6f921e60fb239462522c472163c2f6729e36147ba355dcde1b2d90edbc881819d853b3c8ce9922044acf9fb3",
"KG-CLIENTTIMEMS": "1701234156542",
"KG-THash": "5d9e66d",
"User-Agent": "Android11-AndroidPhone-12069-130-0-COMMENT-wifi",
"KG-RC": "1",
"KG-FAKE": "0",
"KG-RF": "00988d3d",
"Content-Type": "application/json; charset=utf-8",
"Host": "m.comment.service.kugou.com"
}
def get_md5(sign_s):
m = hashlib.md5()
m.update(sign_s.encode(encoding='UTF-8'))
sign = m.hexdigest()
return sign
def get_kugou_commnet(pages):
page = 1
print(f"指定采集评论{pages}页,当前第{page}页:")
ts = str(round(time.time()))
params = {
"code": "fc4be23b4e972707f36b8a828a93ba8a",
"clienttoken": "",
"mid": "334239931975782545528382737887498518928",
"uuid": "f3d96b13323b04867443a3eaa976c6d0",
"ret_cmt_card_media_info": "1",
"show_star_cmts": "1",
"hidden_cmt": "1",
"reply_version": "1",
"pagesize": "20",
"tag": "5",
"clienttime": ts,
"gitversion": "796919f",
"ver": "10",
"area_code": "1",
# "extdata": "5febf34a4835ef685b27c520d69ec608",
"extdata": "bf7d67b1bc6d9f10891395fc8f6aa6dd",# 掌心之中
# "extdata": "c5748b5b2fb966f28b9a71af8290497d",
"p": str(page),
"dfid": "2TnT9N47Jln83dpfih1eheS3",
"fakem": "1acf321ea88ab1da9c093ce610001bc17a0d",
"appid": "1005",
"is_show_hot_word": "1",
"show_classify": "1",
"clientver": "12069",
"mixsongid": "569900661",
"kugouid": "0"
}
# print(params)
sign_s = f"OIlwieks28dk2k092lksi2UIkpappid={params.get('appid')}area_code={params.get('area_code')}clienttime={params.get('clienttime')}clienttoken=clientver={params.get('clientver')}code={params.get('code')}dfid={params.get('dfid')}extdata={params.get('extdata')}fakem={params.get('fakem')}gitversion=796919fhidden_cmt=1is_show_hot_word=1kugouid=0mid={params.get('mid')}mixsongid={params.get('mixsongid')}p={params.get('p')}pagesize=20reply_version=1ret_cmt_card_media_info=1show_classify=1show_star_cmts=1tag=5uuid={params.get('uuid')}ver=10" + "{}OIlwieks28dk2k092lksi2UIkp"
sign = get_md5(sign_s)
# print(sign)
params.update({"signature":sign})
data = {}
data = json.dumps(data, separators=(',', ':'))
url = "http://m.comment.service.kugou.com/v1/cmtlist"
response = requests.post(url, headers=headers, params=params, data=data)
js_data = response.json()
print(js_data)
cmtreturnserver = js_data["cmtreturnserver"]
# count = js_data["count"] # 总评论数
# pages = count//20
while True:
if page < pages:
page += 1
print(f"指定采集评论{pages}页,当前第{page}页:")
ts = str(round(time.time()))
params.update({"clienttime":ts})
# 翻页更新逻辑
params.update({"cmtreturnserver":cmtreturnserver})
params.update({"p":page})
sign_s = f"OIlwieks28dk2k092lksi2UIkpappid={params.get('appid')}area_code={params.get('area_code')}clienttime={params.get('clienttime')}clienttoken=clientver={params.get('clientver')}cmtreturnserver={params.get('cmtreturnserver')}code={params.get('code')}dfid={params.get('dfid')}extdata={params.get('extdata')}fakem={params.get('fakem')}gitversion=796919fhidden_cmt=1is_show_hot_word=1kugouid=0mid={params.get('mid')}mixsongid={params.get('mixsongid')}p={params.get('p')}pagesize=20reply_version=1ret_cmt_card_media_info=1show_classify=1show_star_cmts=1tag=5uuid={params.get('uuid')}ver=10" + "{}OIlwieks28dk2k092lksi2UIkp"
sign = get_md5(sign_s)
# print(sign)
params.update({"signature": sign})
data = {}
data = json.dumps(data, separators=(',', ':'))
url = "http://m.comment.service.kugou.com/v1/cmtlist"
response = requests.post(url, headers=headers, params=params, data=data)
js_data = response.json()
cmtreturnserver = js_data["cmtreturnserver"]
# print(unquote(cmtreturnserver))
print(js_data)
else:
break
if __name__ == '__main__':
pages = 5
get_kugou_commnet(pages)