• Weibo Crawler in Action


    1、要写一个微博爬虫,得分开几个模块来做:

      (1)模拟登录

      (2)模拟浏览

      (3)针对短时间内大量访问而引起怀疑的禁止登陆解决方案

      (4)其他

    (1)模拟登陆模块

        前提:要模拟登录,得首先知道在登录微博的时候,每一次的HTTP请求中都包含了什么信息,于是,可以利用fiddler结合浏览器(chrome除外)来观察每个请求包信息

        过程:

          (一)在浏览器输入:weibo.com,截获如下操作:

            

            

            可以看到这个过程中,有一次尤为重要的HTTP请求:GET /sso/prelogin.php

            也就是登陆前的预处理,名字也显而易见--pre,这一步操作主要是拿到了几个重要的参数,用作下一步POST表单的参数。

            可以在浏览器中访问这一请求的地址:http://login.sina.com.cn/sso/prelogin.php?entry=weibo&callback=sinaSSOController.preloginCallBack&su=&rsakt=mod&client=ssologin.js(v1.4.11)&_=1390381358228

            查看返回的如下(一共有7个参数):

    sinaSSOController.preloginCallBack ({

    1  "retcode":0,

    2  "servertime":1390393012,

    3  "pcid":"xd-7b601057c7fdb6c0cd2308ab66f824cf655d",

    4  "nonce":"YNJDUH",

    5  "pubkey":"EB2A38568661887FA180BDDB5CABD5F21C7BFD59C090CB2D245A87AC253062882729293E5506350508E7F9AA3BB77F4333231490F915F6D63C55FE2F08A49B353F444AD3993CACC02DB784ABBB8E42A9B1BBFFFB38BE18D78E87A0E41B9B8F73A928EE0CCEE1F6739884B9777E4FE9E88A1BBE495927AC4A799B3181D6442443",

    6  "rsakv":"1330428213",

    7  "exectime":1

    })

             其中,

            1. 

            2. servertime:服务时间戳,

            3. 

            4. nonce:是一个6位随机码,

            5. pubkey:是用于rsa2密码加密的公钥,

            6. rsakv:显然也是加密用的。

            7. 

            2,4,5,6 四个值都是需要在下一步用到的。

            在旧版本的新浪微博登陆机制当中,使用的是sha的加密方式,没有pubkey和rsakv参数,

            因此,在网上看到的2012年的爬虫代码模拟登陆的代码都已经不适合用,但总体逻辑是没多大变化的,只需要稍作修改还是能用的,我就是这么走过来的,碰壁无数=.= 

            给出参考文章:

            原文参考:http://www.th7.cn/web/js/201308/12198.shtml

            For Python: http://www.douban.com/note/201767245/

            For PHP: http://www.2cto.com/kf/201210/159591.html

          (二)在登录页面输入登录信息(用户名和密码后)截获如下操作:

            

             

            通过查看其中第一个HTTP请求:POST /sso/login.php?client=ssologin.js(v1.4.11)

            看到了,有几个重要的参数包括:

              1. su:加密后的用户名

              2. servertime

              3. nonce

              4. pwencode:pwd加密方式

              5. nonce

              6. rsakv

              7. sp:加密后的密码

            现在问题就是用户名(su)和密码(sp)是怎么加密的了,

            很容易地我们找到了pwencode,知道密码使用rsa2加密的

            而通过查看微博登录页面 http://login.sina.com.cn/signup/signin.php:

            的目光聚焦到js代码上面

            我们发现了里面有用于密码加密的js代码位于 http://login.sina.com.cn/js/sso/ssologin.js,

            里面的代码是加密过的,找个工具解密一下(http://www.cnlabs.net/tools/Js_Decoder/),

            由上文知道,加密的时候使用了 servertime和nonce,那么我们可以找到:

            

            其中发现与su,sp和servertime,nonce有关的 js代码:

    var makeRequest = function (username, password, savestate)
        {
            var request = 
            {
                entry : me.getEntry(), gateway : 1, from : me.from, savestate : savestate, useticket : me.useTicket ? 1 : 0
            };
            if (me.failRedirect) {
                me.loginExtraQuery.frd = 1
            }
            request = objMerge(request, {
                pagerefer : document.referrer || ""
            });
            request = objMerge(request, me.loginExtraFlag);
            request = objMerge(request, me.loginExtraQuery);
            request.su = sinaSSOEncoder.base64.encode(urlencode(username));
            if (me.service) {
                request.service = me.service
            }
            if ((me.loginType & rsa) && me.servertime && sinaSSOEncoder && sinaSSOEncoder.RSAKey)
            {
                request.servertime = me.servertime;
                request.nonce = me.nonce;
                request.pwencode = "rsa2";
                request.rsakv = me.rsakv;
                var RSAKey = new sinaSSOEncoder.RSAKey();
                RSAKey.setPublic(me.rsaPubkey, "10001");
                password = RSAKey.encrypt([me.servertime, me.nonce].join(" ") + " " + password)
            }
            else
            {
                if ((me.loginType & wsse) && me.servertime && sinaSSOEncoder && sinaSSOEncoder.hex_sha1)
                {
                    request.servertime = me.servertime;
                    request.nonce = me.nonce;
                    request.pwencode = "wsse";
                    password = sinaSSOEncoder.hex_sha1("" + sinaSSOEncoder.hex_sha1(sinaSSOEncoder.hex_sha1(password)) + me.servertime + me.nonce);
                }
            }
            request.sp = password;
            try {
                request.sr = window.screen.width + "*" + window.screen.height
            }
            catch (e) {}
            return request;
        };

      

            

            可以看到su使用的是base64加密方式;

            通过寻找sinaSSOEncoder.base64.encode函数,可以看到:

        this.base64 = 
        {
            encode : function (l)
            {
                l = "" + l;
                if (l == "") {
                    return ""
                }
                var j = "";
                var s, q, o = "";
                var r, p, n, m = "";
                var k = 0;
                do
                {
                    s = l.charCodeAt(k++);
                    q = l.charCodeAt(k++);
                    o = l.charCodeAt(k++);
                    r = s >> 2;
                    p = ((s & 3) << 4) | (q >> 4);
                    n = ((q & 15) << 2) | (o >> 6);
                    m = o & 63;
                    if (isNaN(q)) {
                        n = m = 64
                    }
                    else {
                        if (isNaN(o)) {
                            m = 64;
                        }
                    }
                    j = j + this._keys.charAt(r) + this._keys.charAt(p) + this._keys.charAt(n) + this._keys.charAt(m);
                    s = q = o = "";
                    r = p = n = m = ""
                }
                while (k < l.length);
                return j;
            },
    decode : function (s, p, l)
            {
    ...
    }
    _keys : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
    _keys_urlsafe : 
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_="
        };

            而sp就稍微复杂一点了,

            if中的是新浪当前版本的密码加密方式rsa2的代码,而else中的是就版本sha加密的代码,

            我们只需要关心if中的内容, 加密过程很简单:

             var RSAKey = new sinaSSOEncoder.RSAKey();
                  RSAKey.setPublic(me.rsaPubkey, "10001");
                  password = RSAKey.encrypt([me.servertime, me.nonce].join(" ") + " " + password)

            首先利用sinaSSOEncoder生成一个RSAKey,好,那么sinaSSOEncoder.RSAKey是什么呢?通过查看,发现在sinaSSOEncoder中有代码:

      1 var sinaSSOEncoder = sinaSSOEncoder || {};
      2 (function ()
      3 {
      4     var av;
      5     var ah = 244837814094590;
      6     var Y = ((ah & 16777215) == 15715070);
      7     function aq(z, t, az)
      8     {
      9         if (z != null)
     10         {
     11             if ("number" == typeof z) {
     12                 this.fromNumber(z, t, az)
     13             }
     14             else {
     15                 if (t == null && "string" != typeof z) {
     16                     this.fromString(z, 256)
     17                 }
     18                 else {
     19                     this.fromString(z, t)
     20                 }
     21             }
     22         }
     23     }
     24     function h()
     25     {
     26         return new aq(null)
     27     }
     28     function b(aB, t, z, aA, aD, aC)
     29     {
     30         while (--aC >= 0) {
     31             var az = t * this [aB++] + z[aA] + aD;
     32             aD = Math.floor(az / 67108864);
     33             z[aA++] = az & 67108863
     34         }
     35         return aD
     36     }
     37     function ax(aB, aG, aH, aA, aE, t)
     38     {
     39         var aD = aG & 32767, aF = aG >> 15;
     40         while (--t >= 0)
     41         {
     42             var az = this [aB] & 32767;
     43             var aC = this [aB++] >> 15;
     44             var z = aF * az + aC * aD;
     45             az = aD * az + ((z & 32767) << 15) + aH[aA] + (aE & 1073741823);
     46             aE = (az >>> 30) + (z >>> 15) + aF * aC + (aE >>> 30);
     47             aH[aA++] = az & 1073741823
     48         }
     49         return aE
     50     }
     51     function aw(aB, aG, aH, aA, aE, t)
     52     {
     53         var aD = aG & 16383, aF = aG >> 14;
     54         while (--t >= 0)
     55         {
     56             var az = this [aB] & 16383;
     57             var aC = this [aB++] >> 14;
     58             var z = aF * az + aC * aD;
     59             az = aD * az + ((z & 16383) << 14) + aH[aA] + aE;
     60             aE = (az >> 28) + (z >> 14) + aF * aC;
     61             aH[aA++] = az & 268435455
     62         }
     63         return aE
     64     }
     65     if (Y && (navigator.appName == "Microsoft Internet Explorer")) {
     66         aq.prototype.am = ax;
     67         av = 30
     68     }
     69     else
     70     {
     71         if (Y && (navigator.appName != "Netscape")) {
     72             aq.prototype.am = b;
     73             av = 26
     74         }
     75         else {
     76             aq.prototype.am = aw;
     77             av = 28;
     78         }
     79     }
     80     aq.prototype.DB = av;
     81     aq.prototype.DM = ((1 << av) - 1);
     82     aq.prototype.DV = (1 << av);
     83     var Z = 52;
     84     aq.prototype.FV = Math.pow(2, Z);
     85     aq.prototype.F1 = Z - av;
     86     aq.prototype.F2 = 2 * av - Z;
     87     var ad = "0123456789abcdefghijklmnopqrstuvwxyz";
     88     var af = new Array();
     89     var ao, v;
     90     ao = "0".charCodeAt(0);
     91     for (v = 0; v <= 9; ++v) {
     92         af[ao++] = v
     93     }
     94     ao = "a".charCodeAt(0);
     95     for (v = 10; v < 36; ++v) {
     96         af[ao++] = v
     97     }
     98     ao = "A".charCodeAt(0);
     99     for (v = 10; v < 36; ++v) {
    100         af[ao++] = v
    101     }
    102     function ay(t)
    103     {
    104         return ad.charAt(t)
    105     }
    106     function A(z, t)
    107     {
    108         var az = af[z.charCodeAt(t)];
    109         return (az == null) ?- 1 : az
    110     }
    111     function X(z)
    112     {
    113         for (var t = this.t - 1; t >= 0; --t) {
    114             z[t] = this [t]
    115         }
    116         z.t = this.t;
    117         z.s = this.s
    118     }
    119     function n(t)
    120     {
    121         this.t = 1;
    122         this.s = (t < 0) ?- 1 : 0;
    123         if (t > 0) {
    124             this [0] = t
    125         }
    126         else {
    127             if (t <- 1) {
    128                 this [0] = t + DV
    129             }
    130             else {
    131                 this.t = 0;
    132             }
    133         }
    134     }
    135     function c(t)
    136     {
    137         var z = h();
    138         z.fromInt(t);
    139         return z
    140     }
    141     function w(aD, z)
    142     {
    143         var aA;
    144         if (z == 16) {
    145             aA = 4
    146         }
    147         else
    148         {
    149             if (z == 8) {
    150                 aA = 3
    151             }
    152             else
    153             {
    154                 if (z == 256) {
    155                     aA = 8
    156                 }
    157                 else
    158                 {
    159                     if (z == 2) {
    160                         aA = 1
    161                     }
    162                     else {
    163                         if (z == 32) {
    164                             aA = 5
    165                         }
    166                         else {
    167                             if (z == 4) {
    168                                 aA = 2
    169                             }
    170                             else {
    171                                 this.fromRadix(aD, z);
    172                                 return
    173                             }
    174                         }
    175                     }
    176                 }
    177             }
    178         }
    179         this.t = 0;
    180         this.s = 0;
    181         var aC = aD.length, az = false, aB = 0;
    182         while (--aC >= 0)
    183         {
    184             var t = (aA == 8) ? aD[aC] & 255 : A(aD, aC);
    185             if (t < 0) {
    186                 if (aD.charAt(aC) == "-") {
    187                     az = true
    188                 }
    189                 continue
    190             }
    191             az = false;
    192             if (aB == 0) {
    193                 this [this.t++] = t
    194             }
    195             else
    196             {
    197                 if (aB + aA > this.DB) {
    198                     this [this.t - 1] |= (t & ((1 << (this.DB - aB)) - 1)) << aB;
    199                     this [this.t++] = (t >> (this.DB - aB))
    200                 }
    201                 else {
    202                     this [this.t - 1] |= t << aB
    203                 }
    204             }
    205             aB += aA;
    206             if (aB >= this.DB) {
    207                 aB -= this.DB
    208             }
    209         }
    210         if (aA == 8 && (aD[0] & 128) != 0) {
    211             this.s =- 1;
    212             if (aB > 0) {
    213                 this [this.t - 1] |= ((1 << (this.DB - aB)) - 1) << aB
    214             }
    215         }
    216         this.clamp();
    217         if (az) {
    218             aq.ZERO.subTo(this, this)
    219         }
    220     }
    221     function O()
    222     {
    223         var t = this.s & this.DM;
    224         while (this.t > 0 && this [this.t - 1] == t) {
    225             --this.t
    226         }
    227     }
    228     function q(z)
    229     {
    230         if (this.s < 0) {
    231             return "-" + this.negate().toString(z)
    232         }
    233         var az;
    234         if (z == 16) {
    235             az = 4
    236         }
    237         else
    238         {
    239             if (z == 8) {
    240                 az = 3
    241             }
    242             else
    243             {
    244                 if (z == 2) {
    245                     az = 1
    246                 }
    247                 else {
    248                     if (z == 32) {
    249                         az = 5
    250                     }
    251                     else {
    252                         if (z == 4) {
    253                             az = 2
    254                         }
    255                         else {
    256                             return this.toRadix(z);
    257                         }
    258                     }
    259                 }
    260             }
    261         }
    262         var aB = (1 << az) - 1, aE, t = false, aC = "", aA = this.t;
    263         var aD = this.DB - (aA * this.DB) % az;
    264         if (aA--> 0)
    265         {
    266             if (aD < this.DB && (aE = this [aA] >> aD) > 0) {
    267                 t = true;
    268                 aC = ay(aE)
    269             }
    270             while (aA >= 0)
    271             {
    272                 if (aD < az) {
    273                     aE = (this [aA] & ((1 << aD) - 1)) << (az - aD);
    274                     aE |= this [--aA] >> (aD += this.DB - az)
    275                 }
    276                 else {
    277                     aE = (this [aA] >> (aD -= az)) & aB;
    278                     if (aD <= 0) {
    279                         aD += this.DB;
    280                         --aA
    281                     }
    282                 }
    283                 if (aE > 0) {
    284                     t = true
    285                 }
    286                 if (t) {
    287                     aC += ay(aE)
    288                 }
    289             }
    290         }
    291         return t ? aC : "0"
    292     }
    293     function R()
    294     {
    295         var t = h();
    296         aq.ZERO.subTo(this, t);
    297         return t
    298     }
    299     function ak()
    300     {
    301         return (this.s < 0) ? this.negate() : this
    302     }
    303     function G(t)
    304     {
    305         var az = this.s - t.s;
    306         if (az != 0) {
    307             return az
    308         }
    309         var z = this.t;
    310         az = z - t.t;
    311         if (az != 0) {
    312             return az
    313         }
    314         while (--z >= 0) {
    315             if ((az = this [z] - t[z]) != 0) {
    316                 return az;
    317             }
    318         }
    319         return 0
    320     }
    321     function j(z)
    322     {
    323         var aA = 1, az;
    324         if ((az = z >>> 16) != 0) {
    325             z = az;
    326             aA += 16
    327         }
    328         if ((az = z >> 8) != 0) {
    329             z = az;
    330             aA += 8
    331         }
    332         if ((az = z >> 4) != 0) {
    333             z = az;
    334             aA += 4
    335         }
    336         if ((az = z >> 2) != 0) {
    337             z = az;
    338             aA += 2
    339         }
    340         if ((az = z >> 1) != 0) {
    341             z = az;
    342             aA += 1
    343         }
    344         return aA
    345     }
    346     function u()
    347     {
    348         if (this.t <= 0) {
    349             return 0
    350         }
    351         return this.DB * (this.t - 1) + j(this [this.t - 1]^(this.s & this.DM))
    352     }
    353     function ap(az, z)
    354     {
    355         var t;
    356         for (t = this.t - 1; t >= 0; --t) {
    357             z[t + az] = this [t]
    358         }
    359         for (t = az - 1; t >= 0; --t) {
    360             z[t] = 0
    361         }
    362         z.t = this.t + az;
    363         z.s = this.s
    364     }
    365     function W(az, z)
    366     {
    367         for (var t = az; t < this.t; ++t) {
    368             z[t - az] = this [t]
    369         }
    370         z.t = Math.max(this.t - az, 0);
    371         z.s = this.s
    372     }
    373     function s(aE, aA)
    374     {
    375         var z = aE % this.DB;
    376         var t = this.DB - z;
    377         var aC = (1 << t) - 1;
    378         var aB = Math.floor(aE / this.DB), aD = (this.s << z) & this.DM, az;
    379         for (az = this.t - 1; az >= 0; --az) {
    380             aA[az + aB + 1] = (this [az] >> t) | aD;
    381             aD = (this [az] & aC) << z
    382         }
    383         for (az = aB - 1; az >= 0; --az) {
    384             aA[az] = 0
    385         }
    386         aA[aB] = aD;
    387         aA.t = this.t + aB + 1;
    388         aA.s = this.s;
    389         aA.clamp()
    390     }
    391     function l(aD, aA)
    392     {
    393         aA.s = this.s;
    394         var aB = Math.floor(aD / this.DB);
    395         if (aB >= this.t) {
    396             aA.t = 0;
    397             return
    398         }
    399         var z = aD % this.DB;
    400         var t = this.DB - z;
    401         var aC = (1 << z) - 1;
    402         aA[0] = this [aB] >> z;
    403         for (var az = aB + 1; az < this.t; ++az) {
    404             aA[az - aB - 1] |= (this [az] & aC) << t;
    405             aA[az - aB] = this [az] >> z
    406         }
    407         if (z > 0) {
    408             aA[this.t - aB - 1] |= (this.s & aC) << t
    409         }
    410         aA.t = this.t - aB;
    411         aA.clamp()
    412     }
    413     function aa(z, aA)
    414     {
    415         var az = 0, aB = 0, t = Math.min(z.t, this.t);
    416         while (az < t) {
    417             aB += this [az] - z[az];
    418             aA[az++] = aB & this.DM;
    419             aB >>= this.DB
    420         }
    421         if (z.t < this.t) {
    422             aB -= z.s;
    423             while (az < this.t) {
    424                 aB += this [az];
    425                 aA[az++] = aB & this.DM;
    426                 aB >>= this.DB
    427             }
    428             aB += this.s
    429         }
    430         else {
    431             aB += this.s;
    432             while (az < z.t) {
    433                 aB -= z[az];
    434                 aA[az++] = aB & this.DM;
    435                 aB >>= this.DB
    436             }
    437             aB -= z.s
    438         }
    439         aA.s = (aB < 0) ?- 1 : 0;
    440         if (aB <- 1) {
    441             aA[az++] = this.DV + aB
    442         }
    443         else {
    444             if (aB > 0) {
    445                 aA[az++] = aB;
    446             }
    447         }
    448         aA.t = az;
    449         aA.clamp()
    450     }
    451     function D(z, aA)
    452     {
    453         var t = this.abs(), aB = z.abs();
    454         var az = t.t;
    455         aA.t = az + aB.t;
    456         while (--az >= 0) {
    457             aA[az] = 0
    458         }
    459         for (az = 0; az < aB.t; ++az) {
    460             aA[az + t.t] = t.am(0, aB[az], aA, az, 0, t.t)
    461         }
    462         aA.s = 0;
    463         aA.clamp();
    464         if (this.s != z.s) {
    465             aq.ZERO.subTo(aA, aA)
    466         }
    467     }
    468     function Q(az)
    469     {
    470         var t = this.abs();
    471         var z = az.t = 2 * t.t;
    472         while (--z >= 0) {
    473             az[z] = 0
    474         }
    475         for (z = 0; z < t.t - 1; ++z)
    476         {
    477             var aA = t.am(z, t[z], az, 2 * z, 0, 1);
    478             if ((az[z + t.t] += t.am(z + 1, 2 * t[z], az, 2 * z + 1, aA, t.t - z - 1)) >= t.DV) {
    479                 az[z + t.t] -= t.DV;
    480                 az[z + t.t + 1] = 1;
    481             }
    482         }
    483         if (az.t > 0) {
    484             az[az.t - 1] += t.am(z, t[z], az, 2 * z, 0, 1)
    485         }
    486         az.s = 0;
    487         az.clamp()
    488     }
    489     function E(aH, aE, aD)
    490     {
    491         var aN = aH.abs();
    492         if (aN.t <= 0) {
    493             return
    494         }
    495         var aF = this.abs();
    496         if (aF.t < aN.t) {
    497             if (aE != null) {
    498                 aE.fromInt(0)
    499             }
    500             if (aD != null) {
    501                 this.copyTo(aD)
    502             }
    503             return
    504         }
    505         if (aD == null) {
    506             aD = h()
    507         }
    508         var aB = h(), z = this.s, aG = aH.s;
    509         var aM = this.DB - j(aN[aN.t - 1]);
    510         if (aM > 0) {
    511             aN.lShiftTo(aM, aB);
    512             aF.lShiftTo(aM, aD)
    513         }
    514         else {
    515             aN.copyTo(aB);
    516             aF.copyTo(aD)
    517         }
    518         var aJ = aB.t;
    519         var az = aB[aJ - 1];
    520         if (az == 0) {
    521             return
    522         }
    523         var aI = az * (1 << this.F1) + ((aJ > 1) ? aB[aJ - 2] >> this.F2 : 0);
    524         var aQ = this.FV / aI, aP = (1 << this.F1) / aI, aO = 1 << this.F2;
    525         var aL = aD.t, aK = aL - aJ, aC = (aE == null) ? h() : aE;
    526         aB.dlShiftTo(aK, aC);
    527         if (aD.compareTo(aC) >= 0) {
    528             aD[aD.t++] = 1;
    529             aD.subTo(aC, aD)
    530         }
    531         aq.ONE.dlShiftTo(aJ, aC);
    532         aC.subTo(aB, aB);
    533         while (aB.t < aJ) {
    534             aB[aB.t++] = 0
    535         }
    536         while (--aK >= 0)
    537         {
    538             var aA = (aD[--aL] == az) ? this.DM : Math.floor(aD[aL] * aQ + (aD[aL - 1] + aO) * aP);
    539             if ((aD[aL] += aB.am(0, aA, aD, aK, 0, aJ)) < aA) {
    540                 aB.dlShiftTo(aK, aC);
    541                 aD.subTo(aC, aD);
    542                 while (aD[aL] <--aA) {
    543                     aD.subTo(aC, aD)
    544                 }
    545             }
    546         }
    547         if (aE != null) {
    548             aD.drShiftTo(aJ, aE);
    549             if (z != aG) {
    550                 aq.ZERO.subTo(aE, aE)
    551             }
    552         }
    553         aD.t = aJ;
    554         aD.clamp();
    555         if (aM > 0) {
    556             aD.rShiftTo(aM, aD)
    557         }
    558         if (z < 0) {
    559             aq.ZERO.subTo(aD, aD)
    560         }
    561     }
    562     function N(t)
    563     {
    564         var z = h();
    565         this.abs().divRemTo(t, null, z);
    566         if (this.s < 0 && z.compareTo(aq.ZERO) > 0) {
    567             t.subTo(z, z)
    568         }
    569         return z
    570     }
    571     function K(t)
    572     {
    573         this.m = t
    574     }
    575     function U(t)
    576     {
    577         if (t.s < 0 || t.compareTo(this.m) >= 0) {
    578             return t.mod(this.m)
    579         }
    580         else {
    581             return t;
    582         }
    583     }
    584     function aj(t)
    585     {
    586         return t
    587     }
    588     function J(t)
    589     {
    590         t.divRemTo(this.m, null, t)
    591     }
    592     function H(t, az, z)
    593     {
    594         t.multiplyTo(az, z);
    595         this.reduce(z)
    596     }
    597     function at(t, z)
    598     {
    599         t.squareTo(z);
    600         this.reduce(z)
    601     }
    602     K.prototype.convert = U;
    603     K.prototype.revert = aj;
    604     K.prototype.reduce = J;
    605     K.prototype.mulTo = H;
    606     K.prototype.sqrTo = at;
    607     function B()
    608     {
    609         if (this.t < 1) {
    610             return 0
    611         }
    612         var t = this [0];
    613         if ((t & 1) == 0) {
    614             return 0
    615         }
    616         var z = t & 3;
    617         z = (z * (2 - (t & 15) * z)) & 15;
    618         z = (z * (2 - (t & 255) * z)) & 255;
    619         z = (z * (2 - (((t & 65535) * z) & 65535))) & 65535;
    620         z = (z * (2 - t * z % this.DV)) % this.DV;
    621         return (z > 0) ? this.DV - z :- z
    622     }
    623     function f(t)
    624     {
    625         this.m = t;
    626         this.mp = t.invDigit();
    627         this.mpl = this.mp & 32767;
    628         this.mph = this.mp >> 15;
    629         this.um = (1 << (t.DB - 15)) - 1;
    630         this.mt2 = 2 * t.t
    631     }
    632     function ai(t)
    633     {
    634         var z = h();
    635         t.abs().dlShiftTo(this.m.t, z);
    636         z.divRemTo(this.m, null, z);
    637         if (t.s < 0 && z.compareTo(aq.ZERO) > 0) {
    638             this.m.subTo(z, z)
    639         }
    640         return z
    641     }
    642     function ar(t)
    643     {
    644         var z = h();
    645         t.copyTo(z);
    646         this.reduce(z);
    647         return z
    648     }
    649     function P(t)
    650     {
    651         while (t.t <= this.mt2) {
    652             t[t.t++] = 0
    653         }
    654         for (var az = 0; az < this.m.t; ++az)
    655         {
    656             var z = t[az] & 32767;
    657             var aA = (z * this.mpl + (((z * this.mph + (t[az] >> 15) * this.mpl) & this.um) << 15)) & t.DM;
    658             z = az + this.m.t;
    659             t[z] += this.m.am(0, aA, t, az, 0, this.m.t);
    660             while (t[z] >= t.DV) {
    661                 t[z] -= t.DV;
    662                 t[++z]++
    663             }
    664         }
    665         t.clamp();
    666         t.drShiftTo(this.m.t, t);
    667         if (t.compareTo(this.m) >= 0) {
    668             t.subTo(this.m, t)
    669         }
    670     }
    671     function al(t, z)
    672     {
    673         t.squareTo(z);
    674         this.reduce(z)
    675     }
    676     function y(t, az, z)
    677     {
    678         t.multiplyTo(az, z);
    679         this.reduce(z)
    680     }
    681     f.prototype.convert = ai;
    682     f.prototype.revert = ar;
    683     f.prototype.reduce = P;
    684     f.prototype.mulTo = y;
    685     f.prototype.sqrTo = al;
    686     function i()
    687     {
    688         return ((this.t > 0) ? (this [0] & 1) : this.s) == 0
    689     }
    690     function x(aE, aF)
    691     {
    692         if (aE > 4294967295 || aE < 1) {
    693             return aq.ONE
    694         }
    695         var aD = h(), az = h(), aC = aF.convert(this), aB = j(aE) - 1;
    696         aC.copyTo(aD);
    697         while (--aB >= 0) {
    698             aF.sqrTo(aD, az);
    699             if ((aE & (1 << aB)) > 0) {
    700                 aF.mulTo(az, aC, aD)
    701             }
    702             else {
    703                 var aA = aD;
    704                 aD = az;
    705                 az = aA;
    706             }
    707         }
    708         return aF.revert(aD)
    709     }
    710     function am(az, t)
    711     {
    712         var aA;
    713         if (az < 256 || t.isEven()) {
    714             aA = new K(t)
    715         }
    716         else {
    717             aA = new f(t)
    718         }
    719         return this.exp(az, aA)
    720     }
    721     aq.prototype.copyTo = X;
    722     aq.prototype.fromInt = n;
    723     aq.prototype.fromString = w;
    724     aq.prototype.clamp = O;
    725     aq.prototype.dlShiftTo = ap;
    726     aq.prototype.drShiftTo = W;
    727     aq.prototype.lShiftTo = s;
    728     aq.prototype.rShiftTo = l;
    729     aq.prototype.subTo = aa;
    730     aq.prototype.multiplyTo = D;
    731     aq.prototype.squareTo = Q;
    732     aq.prototype.divRemTo = E;
    733     aq.prototype.invDigit = B;
    734     aq.prototype.isEven = i;
    735     aq.prototype.exp = x;
    736     aq.prototype.toString = q;
    737     aq.prototype.negate = R;
    738     aq.prototype.abs = ak;
    739     aq.prototype.compareTo = G;
    740     aq.prototype.bitLength = u;
    741     aq.prototype.mod = N;
    742     aq.prototype.modPowInt = am;
    743     aq.ZERO = c(0);
    744     aq.ONE = c(1);
    745     function k()
    746     {
    747         this.i = 0;
    748         this.j = 0;
    749         this.S = new Array()
    750     }
    751     function e(aB)
    752     {
    753         var aA, z, az;
    754         for (aA = 0; aA < 256; ++aA) {
    755             this.S[aA] = aA
    756         }
    757         z = 0;
    758         for (aA = 0; aA < 256; ++aA)
    759         {
    760             z = (z + this.S[aA] + aB[aA % aB.length]) & 255;
    761             az = this.S[aA];
    762             this.S[aA] = this.S[z];
    763             this.S[z] = az
    764         }
    765         this.i = 0;
    766         this.j = 0
    767     }
    768     function a()
    769     {
    770         var z;
    771         this.i = (this.i + 1) & 255;
    772         this.j = (this.j + this.S[this.i]) & 255;
    773         z = this.S[this.i];
    774         this.S[this.i] = this.S[this.j];
    775         this.S[this.j] = z;
    776         return this.S[(z + this.S[this.i]) & 255]
    777     }
    778     k.prototype.init = e;
    779     k.prototype.next = a;
    780     function an()
    781     {
    782         return new k()
    783     }
    784     var M = 256;
    785     var m;
    786     var T;
    787     var ab;
    788     function d(t)
    789     {
    790         T[ab++]^ = t & 255;
    791         T[ab++]^ = (t >> 8) & 255;
    792         T[ab++]^ = (t >> 16) & 255;
    793         T[ab++]^ = (t >> 24) & 255;
    794         if (ab >= M) {
    795             ab -= M
    796         }
    797     }
    798     function S()
    799     {
    800         d(new Date().getTime())
    801     }
    802     if (T == null)
    803     {
    804         T = new Array();
    805         ab = 0;
    806         var I;
    807         if (navigator.appName == "Netscape" && navigator.appVersion < "5" && window.crypto && typeof (window.crypto.random) === "function")
    808         {
    809             var F = window.crypto.random(32);
    810             for (I = 0; I < F.length; ++I) {
    811                 T[ab++] = F.charCodeAt(I) & 255;
    812             }
    813         }
    814         while (ab < M) {
    815             I = Math.floor(65536 * Math.random());
    816             T[ab++] = I >>> 8;
    817             T[ab++] = I & 255
    818         }
    819         ab = 0;
    820         S()
    821     }
    822     function C()
    823     {
    824         if (m == null) {
    825             S();
    826             m = an();
    827             m.init(T);
    828             for (ab = 0; ab < T.length; ++ab) {
    829                 T[ab] = 0
    830             }
    831             ab = 0
    832         }
    833         return m.next()
    834     }
    835     function au(z)
    836     {
    837         var t;
    838         for (t = 0; t < z.length; ++t) {
    839             z[t] = C();
    840         }
    841     }
    842     function ac() {}
    843     ac.prototype.nextBytes = au;
    844     function g(z, t)
    845     {
    846         return new aq(z, t)
    847     }
    848     function ag(az, aA)
    849     {
    850         var t = "";
    851         var z = 0;
    852         while (z + aA < az.length) {
    853             t += az.substring(z, z + aA) + "
    ";
    854             z += aA
    855         }
    856         return t + az.substring(z, az.length)
    857     }
    858     function r(t)
    859     {
    860         if (t < 16) {
    861             return "0" + t.toString(16)
    862         }
    863         else {
    864             return t.toString(16);
    865         }
    866     }
    867     function ae(aA, aD)
    868     {
    869         if (aD < aA.length + 11) {
    870             alert("Message too long for RSA");
    871             return null
    872         }
    873         var aC = new Array();
    874         var az = aA.length - 1;
    875         while (az >= 0 && aD > 0)
    876         {
    877             var aB = aA.charCodeAt(az--);
    878             if (aB < 128) {
    879                 aC[--aD] = aB
    880             }
    881             else
    882             {
    883                 if ((aB > 127) && (aB < 2048)) {
    884                     aC[--aD] = (aB & 63) | 128;
    885                     aC[--aD] = (aB >> 6) | 192
    886                 }
    887                 else {
    888                     aC[--aD] = (aB & 63) | 128;
    889                     aC[--aD] = ((aB >> 6) & 63) | 128;
    890                     aC[--aD] = (aB >> 12) | 224
    891                 }
    892             }
    893         }
    894         aC[--aD] = 0;
    895         var z = new ac();
    896         var t = new Array();
    897         while (aD > 2) {
    898             t[0] = 0;
    899             while (t[0] == 0) {
    900                 z.nextBytes(t)
    901             }
    902             aC[--aD] = t[0]
    903         }
    904         aC[--aD] = 2;
    905         aC[--aD] = 0;
    906         return new aq(aC)
    907     }
    908     function L()
    909     {
    910         this.n = null;
    911         this.e = 0;
    912         this.d = null;
    913         this.p = null;
    914         this.q = null;
    915         this.dmp1 = null;
    916         this.dmq1 = null;
    917         this.coeff = null
    918     }
    919     function o(z, t)
    920     {
    921         if (z != null && t != null && z.length > 0 && t.length > 0) {
    922             this.n = g(z, 16);
    923             this.e = parseInt(t, 16)
    924         }
    925         else {
    926             alert("Invalid RSA public key")
    927         }
    928     }
    929     function V(t)
    930     {
    931         return t.modPowInt(this.e, this.n)
    932     }
    933     function p(az)
    934     {
    935         var t = ae(az, (this.n.bitLength() + 7) >> 3);
    936         if (t == null) {
    937             return null
    938         }
    939         var aA = this.doPublic(t);
    940         if (aA == null) {
    941             return null
    942         }
    943         var z = aA.toString(16);
    944         if ((z.length & 1) == 0) {
    945             return z
    946         }
    947         else {
    948             return "0" + z;
    949         }
    950     }
    951     L.prototype.doPublic = V;
    952     L.prototype.setPublic = o;
    953     L.prototype.encrypt = p;
    954     this.RSAKey = L;
    955 }).call(sinaSSOEncoder);

            那么,通过这样一步一步往回退,就解决了密码加密的问题了。

            只要给出有效的参数,就可以得到su和sp了。

          (三)模拟登录请求:

            1)首先是发送 GET请求:http://login.sina.com.cn/sso/prelogin.php?entry=weibo&callback=sinaSSOController.preloginCallBack&su=&rsakt=mod&client=ssologin.js(v1.4.11)&_=1390463770958 <-- 时间戳

              并得到返回:

              sinaSSOController.preloginCallBack({"retcode":0,"servertime":1390466275,"pcid":"xd-5cdeb6364e29309bdea78e342a27bb3d2389","nonce":"SBUEXR","pubkey":"EB2A38568661887FA180BDDB5CABD5F21C7BFD59C090CB2D245A87AC253062882729293E5506350508E7F9AA3BB77F4333231490F915F6D63C55FE2F08A49B353F444AD3993CACC02DB784ABBB8E42A9B1BBFFFB38BE18D78E87A0E41B9B8F73A928EE0CCEE1F6739884B9777E4FE9E88A1BBE495927AC4A799B3181D6442443","rsakv":"1330428213","exectime":0})

              提取其中的servertime、nonce、pubkey和rsakv作为下一步的必要输入。

            2)然后发送 POST请求:http://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.11) 

              并填写好下面的这些参数,利用setEntity来设置他们的值

              

              其中的servertime,rsakv,nonce是从上一步得到的,su利用得到的js代码或者用base64加密方式生成,sp利用js代码生成(pubkey,servertime,nonce,password作为参数)

              特别注意的是,su和sp有可能会随着微博版本而有所改变,需要注意定期更新或跟踪观察!!

              这一步可以得到下述的内容,其中获取location.replace("...")中的内容作为下一步请求的url的:

                <html>

              <head>

              <title>����ͨ��֤</title>

              <meta http-equiv="refresh" content="0; url=&#39;http://weibo.com/sso/login.php?ssosavestate=1393172391&url=http%3A%2F%2Fweibo.com%2Fajaxlogin.php%3Fframelogin%3D1%26callback%3Dparent.sinaSSOController.feedBackUrlCallBack%26sudaref%3Dweibo.com&ticket=ST-MTc2MDM3OTk2NA==-1390580391-gz-312B05A73C71C256F9C7E79E92F78E72&retcode=0&#39;"/>

              <meta http-equiv="Content-Type" content="text/html; charset=GBK" />

              </head>

              <body bgcolor="#ffffff" text="#000000" link="#0000cc" vlink="#551a8b" alink="#ff0000">

              <script type="text/javascript" language="javascript">

              location.replace("http://weibo.com/sso/login.php?ssosavestate=1393172391&url=http%3A%2F%2Fweibo.com%2Fajaxlogin.php%3Fframelogin%3D1%26callback%3Dparent.sinaSSOController.feedBackUrlCallBack%26sudaref%3Dweibo.com&ticket=ST-MTc2MDM3OTk2NA==-1390580391-gz-312B05A73C71C256F9C7E79E92F78E72&retcode=0");

              </script>

               </body>

              </html>

              这里特别需要注意的是只有当retcode=0的时候,才说明之前的所有步骤操作正确,否则请检查之前的操作哪一步中出错了!(是请求的参数包括"_"等等没有填写好还是url没有填写好)

             3)接着发送 POST请求:(刚刚得到的locationreplace中的url)

              获取POST请求执行结果中的Header内容,将其中所有的“Set-Cache”值取出来作为下一步正式登陆时的header中的cache值添加以登陆

             4)最后以个人主页作为url,发送GET请求(除了cache,还要设置其他的header,具体哪些可以通过使用一次fiddler捕获登陆过程中的header来填写)

              若成功,会返回个人主页的页面信息,否则,会得到邀请注册的页面(就是HI谁谁谁,快加入微博关注我之类的话的内容

    (1)模拟浏览模块

      (一)解析页面获得微博内容并实现翻页

          说明:网页版微博有几个更新或者叫翻页的功能,分别是:

            1)

              利用了:GET http://weibo.com/aj/mblog/fsearch?_wv=5_k=1392707288692116&_t=0&since_id=3679341378537185&__rnd=1392708157261 HTTP/1.1

              其中,如_wv=5(貌似与个人账户有关),_k1392707299692116,_t=0(暂时不明)均不是必须的,

                since_id:(与end_id相反)上一次,最后一条刷新出来的微博信息的mid,向下到哪条微博为止

                __rnd:现在的系统时间

            2)

              利用了:GET http://weibo.com/aj/mblog/fsearch?_wv=5&page=1&count=15&max_id=3679341991665814&pre_page=1&end_id=3679341378537185&pagebar=0&_k=139270728869244&_t=0&__rnd=1392707310629 HTTP/1.1

            3)

              利用了:GET http://weibo.com/aj/mblog/fsearch?_wv=5&page=2&count=15&pre_page=1&_k=139270851073081&_t=0&end_id=3679348915284679&end_msign=-1&__rnd=1392708820178 HTTP/1.1

            2)和3)都十分相似,实际上他们几乎都是一样的,其中

      (二)模拟请求获得微博评论

          说明:每次点击评论按钮就是发送了一个Get请求,如下图所示:

          

          请求如下所示:

          http://weibo.com/aj/comment/small?_wv=5&act=list&mid=3677461138997998&uid=1760379964&isMain=true&ouid=3926428816&special_feed=2&location=home&_t=0&__rnd=1392295975327%20HTTP/1.1

          通过多次比较,发现其中的意义:

            _wv:

            mid:微博id

            uid:登陆用户的id

            ouid:微博所有用户的id

            special_feed:

            __rnd:系统时间

          mid、uid和ouid都可以从登陆页面的个人信息和weibo处得到:

          通过发送上面的Get请求就可以得到评论的内容了!(!!!注意,返回的内容是Json格式的数据,需要将html的内容提取出来,并转义成,评论内容在<dd></dd>之中)

      (三)模拟获得好友列表访问并获得好友主页内容

  • 相关阅读:
    根据汉字获取其的首个字母
    jqure获取单选按钮的值(比如性别)
    dataset 和DataTable的用法
    利用ExcelDataReader封装类 导入表格数据
    批量导入数据.net
    一个按下键盘触发事件的例子
    Build Error 6041: Internal build error
    Word 2010巧妙绘制各种分割线的方法(图文)
    vbscript multiple line syntax
    Update msi using vbscript
  • 原文地址:https://www.cnblogs.com/DeeFOX/p/3530291.html
Copyright © 2020-2023  润新知