Chinaunix首页 | 论坛 | 博客
  • 博客访问: 126465
  • 博文数量: 19
  • 博客积分: 810
  • 博客等级: 准尉
  • 技术积分: 200
  • 用 户 组: 普通用户
  • 注册时间: 2008-11-14 23:34
文章分类

全部博文(19)

文章存档

2010年(2)

2009年(12)

2008年(5)

我的朋友

分类: Python/Ruby

2009-09-27 13:53:52

      在做网络爬虫中很多人都会遇到,做得比较好的一些企业级网站,对于登陆或者其他操作都会对用户的输入做一些加密处理后再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的,然后就可以简单的如下执行:

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


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



阅读(3135) | 评论(4) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2009-11-18 13:15:01

我找到了他人写的开心网的外挂源码,放入'MSScriptControl.ScriptControl'执行的是: var g4234 = "df582702e91e"; var acc3 = "cbaktr0f1"; function acc() { var acc = '--' + dff04.substr(0,2) + g4234.substr(2,5) ; return acc; } var dff04 = "ee6a935a7eb7"; acc中的各个参数都初始化了而我的没有:(也不知道该如何初始化: 而我的情况是 function DelKeyword(id_article,id) { if(!confirm("确认?")){ return false; } else { this.document.delkeywordform.id_article.value = id_articl

chinaunix网友2009-10-27 14:51:42

谢谢你的留言 我看了你在csdn的提问,不过我也还还没有研究过这个,我觉得似乎是不可行的,因为这个js代码需要和网页互动,我觉得可能需要静态的js代码才行 如果你有什么新发现,还望不吝赐教,谢谢~~

chinaunix网友2009-10-20 16:36:55

请问:如果这样呢? http://topic.csdn.net/u/20091018/03/bc9ed719-c37e-47e4-874c-92c1528a45d7.html 在js中是一个submit,还能执行吗?

chinaunix网友2009-10-20 16:36:17

请问:如果这样呢? http://topic.csdn.net/u/20091018/03/bc9ed719-c37e-47e4-874c-92c1528a45d7.html 在js中是一个submit,还能执行吗?