Python中模拟网页的javascript加密验证处理

      在做网络爬虫中很多人都会遇到,做得比较好的一些企业级网站,对于登陆或者其他操作都会对用户的输入做一些加密处理后再post到服务器上去,而加密这部分几乎都是通过JavaScript来完成的,所以要做爬虫,需要模拟 这些加密的处理。
      我比较喜欢Python来做爬虫,urllib/urllib2库用起来真的是很方便,所以很多时候遇到需要在python中来模拟网站的JavaScript加密过程。暂时总结起来有两种方法:

      第一种是改写JavaScript的代码。这没什么好说的,不过只适用于比较小而且不复杂的JavaScript代码片段。比如人人网上发站内信的页面有这样的一个隐藏post数据:

<input type="hidden" name="biz" value=0 id="xn_biz"/>

     
      在页面上biz的值为0,但是post的时候就会变成类似于941_683291223928232的字串,仔细看一下页面的源代码,就会发现这段验证的加密字串是通过一段JavaScript的代码生成的:

<script>var mREOQQ=’A`ZDu^`’;var VKMHX=’^&+*L/~’;var uCHKAU=0;var rTIU;var wCJS=”;var yAYH=Math.floor(VKMHX.length/2);while(uCHKAU<mREOQQ.length){rTIU=mREOQQ.charCodeAt(uCHKAU++);var aYDG=VKMHX.charCodeAt(rTIU%VKMHX.length);aYDG=String.fromCharCode(aYDG);if(aYDG==’L')aYDG=’<<’;if(aYDG==’~')wCJS+=~rTIU*(-1);else{wCJS+=Math.floor(eval(rTIU+aYDG+yAYH));}}var ab=941;ab+="_";ab+=wCJS; document.getElementById("xn_biz").value=ab;</script>

      这其实类似一段小型的验证加密,它先随机生产一段字串,复制给随机产生的一个变量名,再随机生成一段运算符,复制给另一个随机生成的变量名,然后对这两个变量进行一系列操作和运算,生成一个类似于941_683291223928232的字串。每次刷新页面这段代码中产生的字串和变量名都是不一样的,但是仔细研究这段代码,算法都是相同的,只要得到字串和运算符串,就可以生成这串验证密钥了。所以将这段代码简单的改写成python代码,问题得到解决,下面代码中code就是提取出来的上述JavaScript代码中的mREOQQ,operator代表VKMHX,而xn则代表ab的初始值,最后得到的xn_biz就是我们最终需要的验证密钥了。

def __genBizCode(code, operator, xn):
        rXHU = unicode( code )
        yAMKEN = operator
        VCHEN, yEEJ, eLKKIH = (0, 0, ”);

        KFNQH = int( len(yAMKEN)/2 );
        
        while VCHEN < len(rXHU):
            yEEJ = ord(rXHU[VCHEN])
            VCHEN += 1
            index = yEEJ % len(yAMKEN)
            dDWE = ord( yAMKEN[index] )
            dDWE = chr(dDWE)
            if dDWE==’L':
                dDWE = ‘<<’
            
            if dDWE==’~':
                eLKKIH += str( ~yEEJ*(-1) )
            else:
                reg = ‘%d%s%d’ % ( yEEJ, dDWE, KFNQH)
                eLKKIH += str( int( eval(reg) ) )
        
        xn_biz = xn + ‘_’
        xn_biz += eLKKIH
        return xn_biz

      这种方法没有依赖性,但是使用的范围较窄,一是要求算法简单才能改写,二是要求算法固定,如果每次刷新页面算法都不一样,这种方法就不使用了。下面会谈到一种通用性的方法。

      第二种是在python中运行js代码。由于QZone和QQ校友登陆的时候,post的密码都进行了加密,搜索了一下,发现很多人都研究过这个东东。腾讯将用户的密码和验证码一起,通过一些js代码进行加密,生成一个32为的密钥最终post到服务器上。对于这个加密算法,网上大部分流传的说法是,先将用户密码进行3次md5的加密,转成大写的32位字符串,再将验证转换成大写,与前面的32位md5大写字符串相加,得到一个36位的字符串,最后对这个36位的字串进行md5加密并转换成大写字串,得到最终post的密钥。网上很多人说用标准的md5加密,但是我用python的hashlib里的md5进行上述的加密,得到的结果却与标准结果不同,于是只能寻求其他办法。
      后来在Google的时候搜到了在python中利用windows的插件Windows ScriptControl运行其他脚本语言的方法,不仅适用js,还可以运行vbs等。
      首先需要安装Windows ScriptControl插件,可以去微软的官网上下载。其次还需要安装python的win32库,然后就可以简单的如下执行:

import win32com.client

def readJsFile(filename):
    fp = file( filename, ‘r’ )
    lines = ”
    for line in fp:
        lines += line
    return lines

def driveJsCode(code, func, paras=None):
    js = win32com.client.Dispatch(’MSScriptControl.ScriptControl’)
    js.Language = ‘JavaScript’
    js.AllowUI = False
    js.AddCode( code )

    if paras:
        return js.Run(func, paras[0], paras[1])
    else:
        return js.Run(func)

if __name__ == ‘__main__’:

    code = readJsFile( ‘comm.js’ )
    p = driveJsCode( code, ‘myPreProcess’, [password, verfcode] )
    print ‘The decoded code is %s’ % p

      这种方法通用性强,而且即使服务器改变算法,依然可以得到正确的加密验证码。

Share and Enjoy:
  • Print this article!
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • LinkedIn
  • Live
  • MySpace
  • RSS
  • Slashdot
  • Technorati
  • TwitThis

No related posts.

Leave a Reply

 

 

 

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

*
To prove you're a person (not a spam script), type the security word shown in the picture. Click on the picture to hear an audio file of the word.
Click to hear an audio file of the anti-spam word

Contact us

Admin: Bryan Wu