从零开始编写农场助手-4
分类: Python, Web 2.0, 笔记 | 标签: Python, 代码 | 日期:2010-04-14 | 332 views
上来先引用两篇文章,随着这两篇都是用C#来写的,一篇在这里,另一篇在此。讲的都是如何得到腾讯加密的算法的。
本章我们需要解决从腾讯服务器那里获取cookie。所以,列了部分代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | VCode='' data={} for item in inputDict: if 'name' not in item: #print item continue if item['name']=='fp': continue if item['name']=='u': print 'user:',item['value'] print 'we set it to user' item['value']='user' if item['name']=='p': print 'password:',item['value'] print 'we set it to correct password' item['value']=myjs.Run('md5',myjs.Run('md5_3','password')+VCode) data[item['name']]=item['value'] data['fp']='loginerroralert' print data import urllib postheader={'Referer':'http://i.qq.com','Accept-Language':'zh-cn','Content-Type':'application/x-www-form-urlencoded',\ 'User-Agent':'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1;.NET CLR 1.1.4322; .NET CLR 2.0.50727)'} opener=urllib2.build_opener() postdata=urllib.urlencode(data) request=urllib2.Request(action,postdata,postheader) results=opener.open(request) a=results.read() print a |
可惜,返回的是错误。
1 | <html><head><meta http-equiv="Content-Language" content="zh-cn"><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>登录失败</title>; </head><script language="Javascript">;alert("您的输入有误, 请重试。");history.go(-1);</script></html> |
这是为啥子尼?再次嵌入到腾讯网页中,仔细寻找,发现有个函数干了一件事,来确定是否需要取得验证码
1 | <input type="text" id="u" name="u" value="" style="ime-mode:disabled" tabindex="1" onfocus="ptui_onUserFocus('u', '#000000')" onblur="ptui_onUserBlue('u', '#CCCCCC');<span style="color: #ff0000;">check()</span>;" /> |
check()部分是重点。意思是,如果用户名输入区域失去焦点,则运行check函数。check函数如下:
1 2 3 4 5 6 7 8 | function check(){ var uin = ptui_trim(document.getElementById("u").value); if (g_uin == uin || (!ptui_checkQQUin(uin))){ return; } g_uin = uin ; ptui_needVC(g_uin,g_appid); } |
如果输入的用户名与以前的不同,则运行ptui_needVC(g_uin,g_appid);其中g_uin是新用户名,g_appid=15000101。再来看这个函数干了啥?
1 | function ptui_needVC(C,D){var B="http://ptlogin2."+g_domain+"/check?uin="+C+"&appid="+D+"&r="+Math.random();var A=document.createElement("script");A.src=B;document.body.appendChild(A);g_loadcheck=true;return } |
原来引用了一个地址,并加入到了当前的文档中。以我的号码为例,测试了一下。返回的内容是:
1 | ptui_checkVC('0','!V4D'); |
原来偷偷运行了一个函数。
1 | function ptui_checkVC(A,B){g_loadcheck=false;if(g_submitting){return }if(A=="0"){document.getElementById("verifycode").value=B;loadVC(false)}else{document.getElementById("verifycode").value="";loadVC(true)}} |
即如果A为0,则将verifycode偷偷改成B的内容,其实这时验证码是不可见的。而如果A不为0,则将验证码输入框内容重置,并调用loadVC函数来加载验证码。loadVC函数如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | function loadVC(flag){ if (isLoadVC == flag){ return; } isLoadVC = flag; if (flag == true){ var img = document.getElementById("imgVerify"); img.src="http://ptlogin2.qq.com/getimage?aid=15000101&"+Math.random(); document.getElementById("verifyinput").style.display=""; document.getElementById("verifytip").style.display=""; document.getElementById("verifyshow").style.display=""; ptui_notifySize("login"); try{ document.getElementById("p").focus(); }catch(e){} }else{ document.getElementById("verifyinput").style.display="none"; document.getElementById("verifytip").style.display="none"; document.getElementById("verifyshow").style.display="none"; ptui_notifySize("login"); } } |
如果传入的flag为真,则直接返回。如果为假,则加载认证码。
于是,我们也通过这样的方法,获取验证码。然而向服务器提交请求之后,还是出错,不过返回的信息变了。
1 | <html> <head><meta http-equiv="Content-Language" content="zh-cn"><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>登录失败</title> </head><script language="Javascript">alert("系统繁忙,请稍后重试(50)。");history.go(-1);</script></html> |
这说明离成功又进了一步。再回来看form代码
1 2 3 | <form id="loginform" autocomplete="off" name="loginform" action="http://ptlogin2.qq.com/login" method="post"
onsubmit="if(!isAbleSubmit){return false;};return <span style="color: #ff0000;">ptui_onLoginEx(loginform, 'qq.com')</span>" onreset="return onFormReset(loginform)" target="_self" style="margin:0px;"> |
注意红色函数,在点击form按钮的同时会验证数据的合法性,如果合法,则运行函数。查看该函数的代码
1 2 3 4 5 6 7 8 | function ptui_onLoginEx(B,C){ if(ptui_onLogin(B)){ var A=new Date(); A.setHours(A.getHours()+24*30); setCookie("ptui_loginuin",B.u.value,A,"/","ui.ptlogin2."+C) } return false } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | function ptui_onLogin(A){ try{ if(parent.ptlogin2_onLogin){ if(!parent.ptlogin2_onLogin()){ return false } } if(parent.ptlogin2_onLoginEx){ var D=A.u.value; var B=A.verifycode.value; if(ptui_str(STR_UINTIP)==D){D=""} if(!parent.ptlogin2_onLoginEx(D,B)){return false} } }catch(C){} return ptui_checkValidate(A) } |
看来要研究setCookie这个函数了。
1 2 3 4 5 6 7 8 9 | function setCookie(C,E){ var A=setCookie.arguments; var H=setCookie.arguments.length; var B=(2<H)?A[2]:null; var G=(3<H)?A[3]:null; var D=(4<H)?A[4]:null; var F=(5<H)?A[5]:null; document.cookie=C+"="+escape(E)+((B==null)?" ":(";expires ="+B.toGMTString()))+((G==null)?" ":(";path = "+G))+((D==null)?" ":(";domain ="+D))+((F==true)?";secure":" ") } |
经过测试发现,C和E是传入的前两个参数,其他参数则通过A[索引]来取得。
所以,在提交表单过程中实际上是将用户名保存到了cookie中,并且设置过期时间为30天。
其实4月6号就写到这个位置了,一直没有发出来。现在开始忙论文,最近是没时间搞了。先见见光吧。


哇塞,太牛掰啦
[回复]
lx 回复:
四月 14th, 2010 at 10:01 下午
@Pynn Yang, 你犯得着用我的主页地址吗。。。。搞得像虚假回复。。。给你改过来了
[回复]
Pynn Yang @ 2010年04月14日
虽然没弄成功,,但是这一份很有帮助的文档,,,
[回复]
lx 回复:
六月 8th, 2010 at 9:25 下午
@fsdf, 最近有再做,但还是没有实质性进展。。。。
[回复]
fsdf @ 2010年06月7日
没事干也在研究这个登录,也是在这里绊倒了,继续~ing
[回复]
lx 回复:
六月 24th, 2010 at 8:12 下午
可以交流交流
[回复]
Neeke 回复:
六月 24th, 2010 at 9:17 下午
@lx, O(∩_∩)O哈哈~已经解决了,登录成功了。
[回复]
lx 回复:
六月 25th, 2010 at 11:15 上午
恭喜啊
Neeke @ 2010年06月24日
Knowledge wants to be free, just like these arltcies!
[回复]
lx 回复:
七月 18th, 2011 at 11:30 上午
@Yancy, your have some typos. arltcies should be articles
[回复]
Yancy @ 2011年07月17日