【爬虫】关于加速乐最新反爬虫机制


( ̄▽ ̄)~*又得半夜修仙了,作为一个爬虫小白,花了3天时间写好的程序,才跑了一个月目标网站就更新了,是有点悲催,还是要只有一天的时间重构。
升级提示.png

升级后网站的层次结构并没有太多变化,表面上是国家企业信用信息公示系统 的验证码又升级了。之前是 点按后滑动拼图方式:

图片.png

现在的验证码主要是按顺序点击图片汉字验证码,但也不排除会出现以前的点按拖动验证码:
图片.png

验证码的破解这里就不详细介绍了,需要的可以私信我们一起讨论研究下,详细可参考极验验证码破解-源码+破解手册,极验二代和三代验证码破解的方式基本都是一个套路的东西。


爬虫的过程
  • 破解加速乐最新反爬虫机制获取cookie
  • 传入cookie获取 gt 和 challenge 参数 (破解验证码必须的参数)
  • 破解验证码
  • 带上cookie,提交参数跳转下一层
  • 抓取数据,这就非常简单了
破解加速乐获取cookie

    网站更新前是不需要这个步骤的,这次重构代码的时间主要就花在这了。一开始我用 get 方式直接访问 http://www.gsxt.gov.cn/SearchItemCaptcha ,获取 gt 和 challenge 参数 ,但是却返回错误521,于是我发现不仅仅是这个接口,但是发现根本连首页都进不去,返回错误页面403 forbidden,而且细心发现返回的并不是正常的乱码而是一串js代码。

< script >
var x = "__jsl_clearance@1515751840@w7ZgszEX@addEventListener@18@Fri@reverse@i@else@l@_phantom@if@captcha@3D@false@Jan@dc@catch@935@var@chips@Expires@Array@cookie@charAt@10@function@@D@__phantomas@vHA@while@GMT@4@attachEvent@setTimeout@cd@for@href@Path@challenge@replace@try@1500@6@length@86w@return@onreadystatechange@12@window@TAGGl@location@40@3@@B@document@0@join@DOMContentLoaded@11@e@2".replace(/@*$/, "").split("@"),
y = "k a=r(){w(P.b||P.u){};k B,h='1=2.j|10|';B=n(+[[(+!+[])]+[([-~-~~~![]]+~~{}>>-~-~~~![])]]);k l=['Q',(!{}+[[], -~{}][~~![]]).p(-~[(-~{}<<-~{})]),'3',[{}+[[], -[com.cn.chaomeng.utils.GsxtUtils] - 初始cookie密文:<script>var x="__jsl_clearance@1515751840@w7ZgszEX@addEventListener@18@Fri@reverse@i@
else@l@_phantom@
if@captcha@3D@false@Jan@dc@
catch@935@
var@chips@Expires@Array@cookie@charAt@10@
function@@D@__phantomas@vHA@
while@GMT@4@attachEvent@setTimeout@cd@
for@href@Path@challenge@replace@
try@1500@6@length@86w@
return@onreadystatechange@12@window@TAGGl@location@40@3@@B@document@0@join@DOMContentLoaded@11@e@2 ".replace(/@*$/,"").split("@"),y="k a = r() {
    w(P.b || P.u) {};
    k B,
    h = '1=2.j|10|';
    B = n( + [[( + !+[])] + [([ - ~ - ~~~ ! []] + ~~ {} >> -~ - ~~~ ! [])]]);
    k l = ['Q', (!{} + [[], -~ {}][~~ ! []]).p( - ~ [( - ~ {} << -~ {})]), '3', [{} + [[], -~ {}][~~ ! []]][10].p(T - ~~~ ! [] - ~~~ ! [] + T), '%', [{} + [[], -~ {}][~~ ! []]][10].p(([ - ~ - ~~~ ! []] + ~~ {} >> -~ - ~~~ ! [])), 'V', ( + {} + [[], -~ {}][~~ ! []]).p(15), 'L', (15 + [] + [[]][( + [])]), 't', ([][~~ {}] + [] + []).p(y), 'v', ( - ~ [] / ~~ ! [] + [[], -~ {}][~~ ! []]).p(J), '%e'];
    C(k 8 = 10; 8 < l.K; 8++) {
        B.7()[8] = l[8]
    };
    B = B.11('');
    h += B;
    A('R.D=R.D.G(/[\\?|&]d-F/,\\'\\')', I);
    W.o = (h + ';m=6, O-g-5 13:q:S x;E=/;');
};
c((r() {
    H {
        M !! P.4;
    }
    i(14) {
        M f;
    }
})()) {
    W.4('12', a, f);
}
9 {
    W.z('N', a);
}
",z=0,f=function(x,y){var a=0,b=0,c=0;x=x.split("");y=y||99;while((a=x.shift())&&(b=a.charCodeAt(0)-77.5))c=(Math.abs(b)<13?(b+48.5):parseInt(a,36))+y*c;return c},g=y.match(/\b\w+\b/g).sort(function(x,y){return f(x)-f(y)}).pop();while(f(g,++z)-x.length){};eval(y.replace(/\b\w+\b/g, function(y){return x[f(y,z)-1]}));</script>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
~{}][~~![]]][10].p(T-~~~![]-~~~![]+T),'%',[{}+[[], -~{}][~~![]]][10].p(([-~-~~~![]]+~~{}>>-~-~~~![])),'V',(+{}+[[], -~{}][~~![]]).p(15),'L',(15+[]+[[]][(+[])]),'t',([][~~{}]+[]+[]).p(y),'v',(-~[]/~~![]+[[], -~{}][~~![]]).p(J),'%e'];C(k 8=10;8<l.K;8++){B.7()[8]=l[8]};B=B.11('');h+=B;A('R.D=R.D.G(/[\\?|&]d-F/,\\'\\')',I);W.o=(h+';m=6, O-g-5 13:q:S x;E=/;');};c((r(){H{M !!P.4;}i(14){M f;}})()){W.4('12',a,f);}9{W.z('N',a);}",
z = 0,
f = function(x, y) {
    var a = 0,
    b = 0,
    c = 0;
    x = x.split("");
    y = y || 99;
    while ((a = x.shift()) && (b = a.charCodeAt(0) - 77.5)) c = (Math.abs(b) < 13 ? (b + 48.5) : parseInt(a, 36)) + y * c;
    return c
},
g = y.match(/\b\w+\b/g).sort(function(x, y) {
    return f(x) - f(y)
}).pop();
while (f(g, ++z) - x.length) {};
eval(y.replace(/\b\w+\b/g,
function(y) {
    return x[f(y, z) - 1]
})); < /script>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
/

到这里取cookie只传递了一个__jsluid 的COOKIES值。

__jsluid=8d61794e23c2bff4a5c997b272729fba;

Google 了一下,发现这是 加速乐的一个爬虫防护机制)。浏览器第二次请求的时候会带上 __jsluid cookies和JS解密计算出来的一个叫做__jsl_clearance的cookies值,只有这两个cookies验证匹配才认为是合法的访问身份。

这个确实花费了不少时间,知道了问题所在就简单多了,仔细分析上面的js代码就会发现我们要的东西就是这个方法:

eval(y.replace(/\b\w+\b/g,
function(y) {
    return x[f(y, z) - 1]
})

接下来就简单,用的是JAVA分析的 ,JAVA的js引擎还是挺好用的。稍微改造下js代码

        resHtml = "function getClearance(){" + resHtml+"};";
        resHtml = resHtml.replace("</script>", "");
        resHtml = resHtml.replace("eval", "return");
        resHtml = resHtml.replace("<script>", "");

改造后的代码js:

function getClearance() {
    var x = "__jsl_clearance@1515751840@w7ZgszEX@addEventListener@18@Fri@reverse@i@else@l@_phantom@if@captcha@3D@false@Jan@dc@catch@935@var@chips@Expires@Array@cookie@charAt@10@function@@D@__phantomas@vHA@while@GMT@4@attachEvent@setTimeout@cd@for@href@Path@challenge@replace@try@1500@6@length@86w@return@onreadystatechange@12@window@TAGGl@location@40@3@@B@document@0@join@DOMContentLoaded@11@e@2".replace(/@*$/, "").split("@"),
    y = "k a=r(){w(P.b||P.u){};k B,h='1=2.j|10|';B=n(+[[(+!+[])]+[([-~-~~~![]]+~~{}>>-~-~~~![])]]);k l=['Q',(!{}+[[], -~{}][~~![]]).p(-~[(-~{}<<-~{})]),'3',[{}+[[], -~{}][~~![]]][10].p(T-~~~![]-~~~![]+T),'%',[{}+[[], -~{}][~~![]]][10].p(([-~-~~~![]]+~~{}>>-~-~~~![])),'V',(+{}+[[], -~{}][~~![]]).p(15),'L',(15+[]+[[]][(+[])]),'t',([][~~{}]+[]+[]).p(y),'v',(-~[]/~~![]+[[], -~{}][~~![]]).p(J),'%e'];C(k 8=10;8<l.K;8++){B.7()[8]=l[8]};B=B.11('');h+=B;A('R.D=R.D.G(/[\\?|&]d-F/,\\'\\')',I);W.o=(h+';m=6, O-g-5 13:q:S x;E=/;');};c((r(){H{M !!P.4;}i(14){M f;}})()){W.4('12',a,f);}9{W.z('N',a);}",
    z = 0,
    f = function(x, y) {
        var a = 0,
        b = 0,
        c = 0;
        x = x.split("");
        y = y || 99;
        while ((a = x.shift()) && (b = a.charCodeAt(0) - 77.5)) c = (Math.abs(b) < 13 ? (b + 48.5) : parseInt(a, 36)) + y * c;
        return c
    },
    g = y.match(/\b\w+\b/g).sort(function(x, y) {
        return f(x) - f(y)
    }).pop();
    while (f(g, ++z) - x.length) {};
    return (y.replace(/\b\w+\b/g,
    function(y) {
        return x[f(y, z) - 1]
    }));
};

接下来用js引擎执行这段代码。

       ScriptEngineManager manager = new ScriptEngineManager();
         ScriptEngine engine = manager.getEngineByName("js");

        engine.eval(resHtml);

        Invocable invocable = (Invocable) engine;

        String resJs = (String) invocable.invokeFunction("getClearance");

这样就可以得到这段js原来的样子了,并把没用的东西去掉,得到下面的js,我们会发现dc就是我们需要的东西,具体没用的东西怎么去掉就不贴上来了,只要是有window的代码去掉,会报错;dc就是我们要的东西,模仿上个步骤加上 return dc;就可以了;

var l = function() {
    var cd, dc = '__jsl_clearance=1515751840.935|0|';
    cd = Array( + [[( + !+[])] + [([ - ~ - ~~~ ! []] + ~~ {} >> -~ - ~~~ ! [])]]);
    var chips = ['TAGGl', (!{} + [[], -~ {}][~~ ! []]).charAt( - ~ [( - ~ {} << -~ {})]), 'w7ZgszEX', [{} + [[], -~ {}][~~ ! []]][0].charAt(3 - ~~~ ! [] - ~~~ ! [] + 3), '%', [{} + [[], -~ {}][~~ ! []]][0].charAt(([ - ~ - ~~~ ! []] + ~~ {} >> -~ - ~~~ ! [])), 'B', ( + {} + [[], -~ {}][~~ ! []]).charAt(2), '86w', (2 + [] + [[]][( + [])]), 'D', ([][~~ {}] + [] + []).charAt(4), 'vHA', ( - ~ [] / ~~ ! [] + [[], -~ {}][~~ ! []]).charAt(6), '%3D'];
    for (var i = 0; i < chips.length; i++) {
        cd.reverse()[i] = chips[i]
    };
    cd = cd.join('');
    dc += cd;
    return dc;
};

直接执行就行了:

        engine.eval(resJs);

        String learance= (String) invocable.invokeFunction("l");

执行完就是我们要的东西啦:

__jsl_clearance=1515751840.935|0|TAGGltw7ZgszEXf%2BN86wcDOvHAs%3D

将两段cookie拼接起来就是最终的cookie了:

__jsluid=8d61794e23c2bff4a5c997b272729fba; 
__jsl_clearance=1515751840.935|0|TAGGltw7ZgszEXf%2BN86wcDOvHAs%3D;

接下来带上cookie访问刚刚的接口(http://www.gsxt.gov.cn/SearchItemCaptcha
),就返回200了,成功

{"challenge":"2f5ce96fd594370c49125a3264166df5","status":"ok","validate":"5be4f4ce721a7c7ad2469925800836a6"}

接下来就简单了。


注意
  • 首页返回的JS脚本里面有防止 PhantomJS 的机制:
while (window._phantom || window.__phantomas) {}; 

当发现是_phantom或者__phantomas后就直接进入死循环了。。

  • 最新发现,取上面步骤得到cookie访问的后续的页面会报302
    解决办法:用得到的cookie再次访问,并从response中取set-cookie,可以得到:
JSESSIONID=AFDB40E58D5E6EC434E0584390629C03-n1:-1; 
Path=/; 
HttpOnlytlb_cookie=S172.16.12.67; path=/

再拼接起来才是最终的cookie:

__jsluid=8d61794e23c2bff4a5c997b272729fba; 
__jsl_clearance=1515751840.935|0|TAGGltw7ZgszEXf%2BN86wcDOvHAs%3D;HttpOnly;secure;
JSESSIONID=AFDB40E58D5E6EC434E0584390629C03-n1:-1; Path=/; 
HttpOnlytlb_cookie=S172.16.12.67; path=/

建议将cookie缓存,2小时更新一次就可以了

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容