声明:本文只作学习研究,禁止用于非法用途,否则后果自负,如有侵权,请告知删除,谢谢!
练习网站平台:
1 | JXU1MjREJXU5NzYyJXU2NkI0JXU5NzMyJXU3Njg0JXU4RkQ4JXU0RTBEJXU2NjBFJXU2NjNFJXU0RTQ4 |
抓取目标:
这次要分析的如何抓取指定用户发布的视频
开启分析之旅:
首先在手机上分享出,我们要抓取的用户
看到这个页面之后,我抓一下包分析一下
滑动刷新多抓两个包,进行比较,分析一下参数
max_cursor :每次会根据,上一次的抓包结果里面有
_signature:每次是变化的,和今日头条那个差不多(预计)
dytk:这个值呢,插看原网页就有,如图所示
让我们瞧一瞧_signature这个参数,全局搜索参数
进入到第一个js文件,我们发现
继续向下搜索signature,我们看到生成的函数:
打上断点分析一下
我们发现仅仅需要传进去uid,我们就能生成_signature值,我们把js复制下下来进行分析,
这里有两种还原方式:
下面我阐述其中一种:
首先么搜索_bytedAcrawler。结果如图所示:
我们进入这个函数:
接下来把这个函数复制出来:
!function(t) {
if (t.M = t.M || {},
!t.M.require) {
var e, n, r = document.getElementsByTagName(“head”)[0], i = {}, o = {}, a = {}, u = {}, c = {}, s = {}, l = function(t, n) {
if (!(t in u)) {
u[t] = !0;
var i = document.createElement(“script”);
if (n) {
var o = setTimeout(n, e.timeout);
i.onerror = function() {
clearTimeout(o),
n()
}
;
var a = function() {
clearTimeout(o)
};
“onload”in i ? i.onload = a : i.onreadystatechange = function() {
(“loaded” === this.readyState || “complete” === this.readyState) && a()
}
}
return i.type = “text/javascript”,
i.src = t,
r.appendChild(i),
i
}
}, f = function(t, e, n) {
var r = i[t] || (i[t] = []);
r.push(e);
var o, a = c[t] || c[t + “.js”] || {}, u = a.pkg;
o = u ? s[u].url || s[u].uri : a.url || a.uri || t,
l(o, n && function() {
n(t)
}
)
};
n = function(t, e) {
“function” != typeof e && (e = arguments[2]),
t = t.replace(/.js$/i, “”),
o[t] = e;
var n = i[t];
if (n) {
for (var r = 0, a = n.length; a > r; r++)
nr;
delete i[t]
}
}
,
e = function(t) {
if (t && t.splice)
return e.async.apply(this, arguments);
t = e.alias(t);
var n = a[t];
if (n)
return n.exports;
var r = o[t];
if (!r)
throw “[ModJS] Cannot find module " + t + "
“;
n = a[t] = {
exports: {}
};
var i = “function” == typeof r ? r.apply(n, [e, n.exports, n]) : r;
return i && (n.exports = i),
n.exports && !n.exports[“default”] && Object.defineProperty && Object.isExtensible(n.exports) && Object.defineProperty(n.exports, “default”, {
value: n.exports
}),
n.exports
}
,
e.async = function(n, r, i) {
function a(t) {
for (var n, r = 0, h = t.length; h > r; r++) {
var p = e.alias(t[r]);
p in o ? (n = c[p] || c[p + “.js”],
n && “deps”in n && a(n.deps)) : p in s || (s[p] = !0,
l++,
f(p, u, i),
n = c[p] || c[p + “.js”],
n && “deps”in n && a(n.deps))
}
}
function u() {
if (0 === l—) {
for (var i = [], o = 0, a = n.length; a > o; o++)
i[o] = e(n[o]);
r && r.apply(t, i)
}
}
“string” == typeof n && (n = [n]);
var s = {}
, l = 0;
a(n),
u()
}
,
e.resourceMap = function(t) {
var e, n;
n = t.res;
for (e in n)
n.hasOwnProperty(e) && (c[e] = n[e]);
n = t.pkg;
for (e in n)
n.hasOwnProperty(e) && (s[e] = n[e])
}
,
e.loadJs = function(t) {
l(t)
}
,
e.loadCss = function(t) {
if (t.content) {
var e = document.createElement(“style”);
e.type = “text/css”,
e.styleSheet ? e.styleSheet.cssText = t.content : e.innerHTML = t.content,
r.appendChild(e)
} else if (t.url) {
var n = document.createElement(“link”);
n.href = t.url,
n.rel = “stylesheet”,
n.type = “text/css”,
r.appendChild(n)
}
}
,
e.alias = function(t) {
return t.replace(/.js$/i, “”)
}
,
e.timeout = 5e3,
t.M.define = n,
t.__M.require = e
}
}(this);
M.define(“douyin_falcon:node_modules/byted-acrawler/dist/runtime”, function(l, e) {
Function(function(l) {
return ‘e(e,a,r){(b[e]||(b[e]=t(“x,y”,”x “+e+” y”)(r,a)}a(e,a,r){(k[r]||(k[r]=t(“x,y”,”new xy.join(“,x[y]”)(1)+”)”)(e,a)}r(e,a,r){n,t,s={},b=s.d=r?r.d+1:0;for(s[“$”+b]=s,t=0;t>>065:h=,y=,[y]=h66:u(e(t[b],,67:y=,d=,u((g=).x===c?r(g.y,y,k):g.apply(d,y68:u(e((g=t[b])<”<”?(b—,f):g+g,,70:u(!1)71:n72:+f73:u(parseInt(f,3675:if(){bcase 74:g=<<16>>16g76:u(k[])77:y=,u([y])78:g=,u(a(v,x-=g+1,g79:g=,u(k[“$”+g])81:h=,[f]=h82:u([f])83:h=,k[]=h84:!085:void 086:u(v[x-1])88:h=,y=,h,y89:u({e{r(e.y,arguments,k)}e.y=f,e.x=c,e})90:null91:h93:h=0:;default:u((g<<16>>16)-16)}}n=this,t=n.Function,s=Object.keys||(e){a={},r=0;for(c in e)a[r]=c;a=r,a},b={},k={};r’.replace(/[-]/g, function(e) {
return l[15 & e.charCodeAt(0)]
})
}(“v[x++]=v[—x]t.charCodeAt(b++)-32function return ))++.substrvar .length(),b+=;break;case ;break}”.split(“”)))()(‘gr$Daten Иb/s!l y͒yĹg,(lfi~ah`{mv,-n|jqewVxp{rvmmx,&effkx[!cs”l”.Pq%widthl”@q&heightl”vrgetContextx$”2d[!cs#l#,;?|u.|uc{uq$fontl#vr(fillTextxlimeq+shadowColorl#vr#arcx88802[%c}l#vr&strokex[ c}l”v,)}eOmyoZB]mx[ cs!0s$l$Pb
value: !0
})])
});
var dycs = __M.require(“douyin_falcon:node_modules/byted-acrawler/dist/runtime”);
function sign(uid){
return dycs.sign(uid);
}
console.log(sign(382237371544059));
初步还原点代码,下面我们继续分析
接下来就是我们本片文章的重点内容:
我进入函数sign里,看看最检测有哪些:
打上断点,调试,一顿操作猛如虎:
首先看到的是webdriver的检测,这里是检测selenium等等webdriver的特征,这就是为啥无法用selenium获取数据的原因
我们继续调试;
然后是对location对象进行检测
环境参数_zid
接下来是重要的环节,继续调试可以发现这个js还对canvas做了检测
最后是tac的字符串,这段东西是动态生成的,需要从静态页面源码获取
接下来开始逐步还原js加密算法:
1 | window = global; |
游览器对象补充完毕:
我们和并完成代码:
1 |
|
到这里我们就还原成功了:
到此我们分析结束,
请求数据时注意:
保持游览器头和js写的一致,如有疑问,搜索公众号,后台点击联系我。
微信公众号菜鸟童靴,不定期更新,欢迎关注,我们一起进步