1. 程式人生 > >【爬蟲】關於企業信用信息公示系統-加速樂最新反爬蟲機制

【爬蟲】關於企業信用信息公示系統-加速樂最新反爬蟲機制

pos 錯誤頁面 code 小時 timeout googl ear 系統 phantom


( ̄▽ ̄)~*又得半夜修仙了,作為一個爬蟲小白,花了3天時間寫好的程序,才跑了一個月目標網站就更新了,是有點悲催,還是要只有一天的時間重構。
技術分享圖片

升級後網站的層次結構並沒有太多變化,表面上是國家企業信用信息公示系統 的驗證碼又升級了。之前是 點按後滑動拼圖方式:
技術分享圖片
現在的驗證碼主要是按順序點擊圖片漢字驗證碼,但也不排除會出現以前的點按拖動驗證碼:
技術分享圖片

驗證碼的破解這裏就不詳細介紹了,需要的可以私信我們一起討論研究下,詳細可參考極驗驗證碼破解-源碼+破解手冊,極驗二代和三代驗證碼破解的方式基本都是一個套路的東西。
* * *

爬蟲的過程
  • 破解加速樂最新反爬蟲機制獲取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小時更新一次就可以了

【爬蟲】關於企業信用信息公示系統-加速樂最新反爬蟲機制