声明
- 仅供技术讨论,不用于任何盈利或者商业目的
- 如有侵权,请发送邮件到博主邮箱,将在收到邮件的第一时间删除相关内容
分析过程
首先下一个 analysis 的 XHR断点,在断下的位置向上查找:
找到函数名,再次以函数名搜索:
直到找到一个请求拦截器,然后进入这个拦截器,查查看拦截器的具体操作:
提一下拦截器,拦截器的话主要是在请求之前由前端对请求的再次操作:
继续看拦截器的代码,似乎是加密的代码:
下断点,继续运行,看一下调试的信息,可以发现生成 analysis 代码就是这里:
所以只需要把这里的代码单独拿出来,就行了,然后把这段代码的几个关键参数找出来,内置到 JS 代码里面,通过外部调用就可以生成 analysis 参数。
主要的关键参数是下图中指定的参数:
以及用到的几个函数,只需要通过这个方法查看一下稍微修改代码就行了,以前几次网站代码的修改都是在这几个地方动手脚
以下是 JS 用的代码:
l = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "+", "/"]
function n_(t) {
var n;
n = f(t.toString(), "binary");
return u(n)
}
function a(t) {
return l[t >> 18 & 63] + l[t >> 12 & 63] + l[t >> 6 & 63] + l[63 & t]
}
function s(t, e, n) {
for (var r, i = [], o = e; o < n; o += 3)
r = (t[o] << 16 & 16711680) + (t[o + 1] << 8 & 65280) + (255 & t[o + 2]),
i.push(a(r));
return i.join("")
}
function u(t) {
for (var e, n = t.length, r = n % 3, i = "", o = [], a = 16383, u = 0, c = n - r; u < c; u += a)
o.push(s(t, u, u + a > c ? c : u + a));
return 1 === r ? (e = t[n - 1],
i += l[e >> 2],
i += l[e << 4 & 63],
i += "==") : 2 === r && (e = (t[n - 2] << 8) + t[n - 1],
i += l[e >> 10],
i += l[e >> 4 & 63],
i += l[e << 2 & 63],
i += "="),
o.push(i),
o.join("")
}
function K(t, e, n, r) {
for (var i = 0; i < r && !(i + n >= e.length || i >= t.length); ++i)
e[i + n] = t[i];
return i
}
function W(t) {
for (var e = [], n = 0; n < t.length; ++n)
e.push(255 & t.charCodeAt(n));
return e
}
function t_(t, e, n, r) {
return K(W(e), t, 0, r)
}
function f(e, n) {
var r = e.length;
t = new Uint8Array(r);
var i = t_(t, e, n, r);
return t
}
function v_(n) {
return n_(encodeURIComponent(n)["replace"](/%([0-9A-F]{2})/g, function (a, n) {
return String["fromCharCode"]("0x" + n)
}))
}
function k_(a, n) {
//n || (n = s()),
a = a["split"]("");
for (var t = a["length"], e = n["length"], r = "charCodeAt", i = 0; i < t; i++)
//a[i] = m_(a[i][r](0) ^ n[(i + 10) % e][r](0));
a[i] = String["fromCharCode"](a[i][r](0) ^ n[(i + 10) % e][r](0));
return a["join"]("")
}
function getAnalysis (synct, url, p_str) {
var g = new Date() - 1000 * synct;
var e = new Date() - g - 1515125653845;
var S = 1;
var palist = [];
for (var key in p_str) {
palist.push(p_str[key])
}
var mm = palist["sort"]()["join"]("");
m_0 = v_(mm);
m_1 = m_0 + "@#" + url.replace("https://api.xxxxx.cn", "");
m_2 = m_1 + "@#" + e;
m_3 = m_2 + "@#" + S;
var b = "00000008d78d46a";
return v_(k_(m_3, b))
}
以下是python代码实现:
# -*- coding: utf-8 -*-
__version_ = 'python 3.7'
__author__ = 'Json·G'
__date__ = '2020/7/6 15:50'
import requests
import datetime
import execjs
js_xxxxx = """
l = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "+", "/"]
function n_(t) {
var n;
n = f(t.toString(), "binary");
return u(n)
}
function a(t) {
return l[t >> 18 & 63] + l[t >> 12 & 63] + l[t >> 6 & 63] + l[63 & t]
}
function s(t, e, n) {
for (var r, i = [], o = e; o < n; o += 3)
r = (t[o] << 16 & 16711680) + (t[o + 1] << 8 & 65280) + (255 & t[o + 2]),
i.push(a(r));
return i.join("")
}
function u(t) {
for (var e, n = t.length, r = n % 3, i = "", o = [], a = 16383, u = 0, c = n - r; u < c; u += a)
o.push(s(t, u, u + a > c ? c : u + a));
return 1 === r ? (e = t[n - 1],
i += l[e >> 2],
i += l[e << 4 & 63],
i += "==") : 2 === r && (e = (t[n - 2] << 8) + t[n - 1],
i += l[e >> 10],
i += l[e >> 4 & 63],
i += l[e << 2 & 63],
i += "="),
o.push(i),
o.join("")
}
function K(t, e, n, r) {
for (var i = 0; i < r && !(i + n >= e.length || i >= t.length); ++i)
e[i + n] = t[i];
return i
}
function W(t) {
for (var e = [], n = 0; n < t.length; ++n)
e.push(255 & t.charCodeAt(n));
return e
}
function t_(t, e, n, r) {
return K(W(e), t, 0, r)
}
function f(e, n) {
var r = e.length;
t = new Uint8Array(r);
var i = t_(t, e, n, r);
return t
}
function v_(n) {
return n_(encodeURIComponent(n)["replace"](/%([0-9A-F]{2})/g, function (a, n) {
return String["fromCharCode"]("0x" + n)
}))
}
function k_(a, n) {
//n || (n = s()),
a = a["split"]("");
for (var t = a["length"], e = n["length"], r = "charCodeAt", i = 0; i < t; i++)
//a[i] = m_(a[i][r](0) ^ n[(i + 10) % e][r](0));
a[i] = String["fromCharCode"](a[i][r](0) ^ n[(i + 10) % e][r](0));
return a["join"]("")
}
function getAnalysis (synct, url, p_str) {
var g = new Date() - 1000 * synct;
var e = new Date() - g - 1515125653845;
var S = 1;
var palist = [];
for (var key in p_str) {
palist.push(p_str[key])
}
var mm = palist["sort"]()["join"]("");
m_0 = v_(mm);
m_1 = m_0 + "@#" + url.replace("https://api.xxxxx.cn", "");
m_2 = m_1 + "@#" + e;
m_3 = m_2 + "@#" + S;
var b = "00000008d78d46a";
return v_(k_(m_3, b))
}
"""
def handle(params, url_start):
headers = {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
"Accept-Encoding": "gzip, deflate, br",
"Accept-Language": "zh-CN,zh;q=0.9",
"Cache-Control": "max-age=0",
"Connection": "keep-alive",
"Host": "www.xxxxx.cn",
"If-Modified-Since": "Mon, 09 Dec 2019 11:03:14 GMT",
"If-None-Match": 'W/"5dee29f2 - be2"',
"Referer": "https://www.xxxxx.cn/",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"
}
resp = requests.get('https://www.xxxxx.cn/rank', headers=headers)
t = resp.cookies.get_dict()
synct = t.get('synct')
def getanaly(synct, url, params):
ctx = execjs.compile(js_xxxxx)
new_pwd = ctx.call("getAnalysis", synct, url, params)
return new_pwd
analysis = getanaly(synct, url_start, params)
headers_sub = {
"Accept": "application/json, text/plain, */*",
"Accept-Encoding": "gzip, deflate, br",
"Accept-Language": "zh-CN,zh;q=0.9",
"Connection": "keep-alive",
"Host": "api.xxxxx.cn",
"Origin": "https://www.xxxxx.cn",
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Site": "same-site",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"
}
params['analysis'] = analysis
url = url_start + '?'
res = requests.get(url=url, headers=headers_sub, params=params)
return res.json()
url_start = "https://api.xxxxx.cn/rank/index"
time_now = datetime.datetime.now().strftime('%Y-%m-%d')
params = {
"brand": "free",
"country": "cn",
"genre": "5000",
"device": "iphone",
"date": str(time_now),
"is_rank_index": 1
}
params["page"] = 1
json_return = handle(params, url_start)
page = json_return["maxPage"]
for i in range(int(page) - 1):
params = {
"brand": "free",
"country": "cn",
"genre": "5000",
"device": "iphone",
"date": str(time_now),
"is_rank_index": 1
}
params["page"] = i + 2
json_return = handle(params, url_start)
print(json_return)
quit()