从零开始编写农场助手-3
分类: Python, 代码, 笔记 | 标签: Python, 代码 | 日期:2010-04-03 | 254 views
上一篇写到了在获取cookie之后所需要进行的第一步数据操作,以及python中的md5编码。
那么现在,最重要的一步就是迈进腾讯服务器的登录程序,获取cookie了。因此,还是需要先参考官方的登录方法,包括表单提交所用的数据,编码的格式等。为此,查看源代码http://imgcache.qq.com/ptlogin/v3/js/comm.js?v=1.5
发现了里面第一个重要的函数ajax_Submit(),将源代码列出来,后面我加上了每一步的注释
function ajax_Submit()
{
if (!isLoadVC)//isLoadVC意思是is VerifyCode Loaded? 是否加载了验证码,如果没加载则进入if语句
{
g_uin=0//应该是global的uin
}
var D=true;//布尔值D赋值为真
var E=document.forms[0];//将所有表单集合中的第一个赋给E,总共就一个表单,那就是它了
var B=”"; //B 字符串赋初值为空
for (var A=0;A<E.length;A++) //遍历E也就是那个提交的表单中的所有input元素
{
if (E[A].name==”fp”||E[A].type==”submit”) //如果input的name是submit(那其实是提交的按钮)或者fp(我不懂这里fp为什么跳过,然后在遍历结束后又人工加上了相同的fp值)
{
continue//没什么好说的,下一轮循环
}
if (E[A].name==”ptredirect”)//如果input的name是ptredirect(pt重定向?pt是什么的缩写不明白),则进入if语句
{
g_ptredirect=E[A].value //全局的ptredirect赋值
}
if (E[A].name==”low_login_enable”&&(!E[A].checked)) //如果input的name是low_login_enable,并且这个选项勾选了的话(说明这个input是个option),进入if语句
{
D=false; //D赋值为假
continue//直接下一轮循环,跳过下面语句
}
if (E[A].name==”low_login_hour”&&(!D))//如果input的name是左边那话儿,并且D为否,则进入if语句,也就是进入下一轮循环
{
continue
}
if (E[A].name==”webqq_type”&&(!E[A].checked))//如果name是webqq_type并且这个option没有勾选,则下一轮循环
{
continue
}
B+=E[A].name;//如果input的name不属于以上特例,则将name加入B,可见B是用来提交表单的data
B+=”=”;//B后面加个等号,接下来就要给B加相应的数据了
if (E[A].name==”p”)//重要,如果input是密码输入区域,则
{
var F=”";//定义空字符串F
F+=E.verifycode.value;//F赋值为用户输入的验证码
F=F.toUpperCase();//将验证码全部大写
B+=md5(md5_3(E.p.value)+F)//将用户输入的密码值用md5_3()加密一次之后与F连接再md5一次
}//后面的md5与我们上一篇讨论的python中标准md5相符,但md5_3()这个函数需要仔细观看
else
{
if (E[A].name==”u1″||E[A].name==”ep”)//如果input名字是u1或者是ep(i.qq.com里面的login表单出现的name是u1,不知道哪个表单中会出现u1)
{
B+=encodeURIComponent(E[A].value)//将地址编码加入data B
}
else
{
B+=E[A].value //如果是其他数据,则直接加入表单数据B
}
}
B+=”&” //每加一个数据,则用连接符&连接不同数据
}
B+=”fp=loginerroralert”; //这里的fp和表单内自带的完全一致,不懂为什么单独拿出来,难道是为了放在最后?
var C=document.createElement(“script”);//创建一个script元素并追加到网页中
C.src=E.action+”?”+B;
document.body.appendChild(C);
return
}
如你所见,我们还需要弄清楚md5_3()这个函数,如下:
function md5_3(B)
{
var A=new Array;
A=core_md5(str2binl(B),B.length*chrsz);
A=core_md5(A,16*chrsz);
A=core_md5(A,16*chrsz);
return binl2hex(A)
}
然而,腾讯制作的javascript函数实在是比较乱,如果现在知道了如何编码,万一腾讯将其改动那么一点,则整个程序都将不可用了。
可行的一个办法是(想法来自于这里),把腾讯为我们写好的js函数直接拿来调用,但python如何调用和解释javascript呢,windows下我们有PyV8可用,但它似乎比较深奥(对我而言),不能够直接读取js文件。
所以,一个可选的办法就是,在windows下使用DOM来操作javascript,要这么做的话,我们需要pywin32这个增强软件(从这里看来的)。
于是,依然是从腾讯的登录界面中提取js的地址,并获取js全部代码
import urllib2,win32com.client
url=’http://2url.org?grabqq’
site=urllib2.urlopen(url)
con=(site.read()).decode(‘utf-8′)
sub_a=’<script language=”javascript” src=”‘
i_a=con.find(sub_a)+len(sub_a)
j_a=con.find(‘”‘,i_a+len(sub_a))
js_addr=con[i_a:j_a]
js_con=unicode(urllib2.urlopen(js_addr).read(),’utf-8′)
myjs=win32com.client.Dispatch(‘MSScriptControl.ScriptControl’)
myjs.Language=’JavaScript’
myjs.AllowUI=False
myjs.AddCode(js_con)
可气的是,直接这么用会报错。错误信息是:
com_error: (-2147352567, ‘\xb7\xa2\xc9\xfa\xd2\xe2\xcd\xe2\xa1\xa3′, (0, u’Microsoft JScript \u8fd0\u884c\u65f6\u9519\u8bef’, u”‘window’ \u672a\u5b9a\u4e49″, None, 0, -2146823279), None)
这个鸟语相信没人能够看懂,但是通过此处可以查阅到unicode的map,将上面的x星文翻译成汉字就是
com_error: (-2147352567, ‘意外错误。’, (0, ‘Microsoft JScript 运行时错误’, “‘window’ 未定义”, None, 0, -2146823279), None)
这源于腾讯的js函数定义中有个window.ActiveXObject,把window换成document似乎也不行,于是干脆把window.这一串给干掉,竟然成功了。只需要加上这么一句
js_con=js_con.replace(‘window.’,”)
只不过,与hashlib直接得出的结果不同,与Firefox、IE和Chrome相同,使用微软的这个JScript解释器运行出来的md5字符串全都是大写的,说明腾讯在输出之前就已经转大写了。但这些都不用我们关心了,我们只管调用函数就好了。
经过测试,Microsoft的JScript解释器调用腾讯的js函数工作良好,与网页上的运行结果一致。至此,进行http通信post数据之前的所有工作都已准备就绪。
下一章,post服务器,获取cookie。

