python实现的登录和操作开心网脚本分享
SNS什么的我是一直无爱的,这次蛋疼写了个登录开心网(kaixin001)并向所有好友发送站内消息的脚本。
开心网在登录的时候做了一些处理,并不传原始密码,从js分析到的结果是:登录时会生成一个随机的key,然后用这个key和原始密码进行xxtea加密,把加密后的结果再进行sha1加密。之后post这个key以及加密后的密码进行登录验证。
以下是很简陋的脚本内容:
#coding:utf-8 """ 开心网操作脚本 Author:piglei2007@gmail.com Version:1.0 """ importre importurllib importurllib2 importrandom importhashlib importbinascii importcookielib importsimplejson fromxxteaimportencrypt LOGIN_URL="http://www.kaixin001.com/login/login_api.php" LOGIN_KEY_URL="http://www.kaixin001.com/" FRIEND_LIST_URL="http://www.kaixin001.com/interface/suggestfriend.php" MESSAGE_SEND_URL="http://www.kaixin001.com/msg/post.php" LOGIN_KEY_RE=re.compile(r"new\sEnLogin\('(.*?)'") classLoginError(Exception): """ 登录失败抛出异常 """ classKaixin001User(object): """ 操作kaixin001,现有方法: get_login_key-获得用户访问登录页面时分配的加密key get_rpassword-获得经过xxtea以及sha1加密后的密码 login-登录 get_friends_list-获得所有好友,返回字典格式 send_messages_to_all-给所有好友发消息 """ def__init__(self,username,password): self.username=username self.password=password self.cj=cookielib.CookieJar() opener=urllib2.build_opener(urllib2.HTTPCookieProcessor(self.cj)) opener.addheaders=[ ("User-agent","Mozilla/5.0(X11;U;FreeBSDi386;en-US;rv:1.9.1)Gecko/20090704Firefox/3.5"), ("Accept","*/*"), ("Host","www.kaixin001.com") ] urllib2.install_opener(opener) defget_login_key(self): """ 获得登录时候的加密key """ _temp=urllib2.urlopen(LOGIN_KEY_URL).read() key=LOGIN_KEY_RE.search(_temp).group(1) returnkey deflogin(self): """ 登录 """ login_key=self.get_login_key() rpassword=self.get_rpassword(self.password,login_key) login_params={ 'email':self.username, 'encypt':login_key, 'rpasswd':rpassword, 'url':'/home/', 'ver':'1' } req=urllib2.Request(LOGIN_URL,urllib.urlencode(login_params),{ "Referer":"http://www.kaixin001.com/" }) result=urllib2.urlopen(req).read() #登录失败 if"errno"inresult: raiseLoginError("登录失败,请检查用户名或密码") print"用户%s登录成功!"%self.username return'ok' defget_friends_list(self): """ 获得所有好友列表 """ get_friends_params={ 't':str(random.random()), 'type':'all', } result=urllib2.urlopen(FRIEND_LIST_URL,urllib.urlencode(get_friends_params)).read() friends=simplejson.loads(result) print"你一共有%s位好友"%(len(friends)-1) returnfriends defsend_messages_to_all(self,message=''): """ 给所有好友发消息 """ friends=self.get_friends_list() send_params={ 'attachment_cancel':'', 'attachment_forwarding':'', 'attachment_random':'', 'code':'', 'content':message, 'forward_thread':'', 'rcode':'', 'service':'0', 'texttype':'html', 'uids':",".join([str(f['uid'])forfinfriends]) } result=urllib2.urlopen(MESSAGE_SEND_URL,urllib.urlencode(send_params)) printresult.geturl() print"消息发送成功" return'ok' defget_rpassword(self,password,key): """ 获得加密后的密码 """ xxtea_pw=binascii.b2a_hex(encrypt(password,key)) r_password=hashlib.sha1(xxtea_pw).hexdigest() returnr_password if__name__=='__main__': kxu=Kaixin001User( username='your_username', password='your_password' ) kxu.login() kxu.send_messages_to_all("ThismessageissendbyPython.")
这是脚本中需要用到的xxtea算法的python实现(xxtea.py):
importstruct _DELTA=0x9E3779B9 def_long2str(v,w): n=(len(v)-1)<<2 ifw: m=v[-1] if(m<n-3)or(m>n):return'' n=m s=struct.pack('<%iL'%len(v),*v) returns[0:n]ifwelses def_str2long(s,w): n=len(s) m=(4-(n&3)&3)+n s=s.ljust(m,"\0") v=list(struct.unpack('<%iL'%(m>>2),s)) ifw:v.append(n) returnv defencrypt(str,key): ifstr=='':returnstr v=_str2long(str,True) k=_str2long(key.ljust(16,"\0"),False) n=len(v)-1 z=v[n] y=v[0] sum=0 q=6+52//(n+1) whileq>0: sum=(sum+_DELTA)&0xffffffff e=sum>>2&3 forpinxrange(n): y=v[p+1] v[p]=(v[p]+((z>>5^y<<2)+(y>>3^z<<4)^(sum^y)+(k[p&3^e]^z)))&0xffffffff z=v[p] y=v[0] v[n]=(v[n]+((z>>5^y<<2)+(y>>3^z<<4)^(sum^y)+(k[n&3^e]^z)))&0xffffffff z=v[n] q-=1 return_long2str(v,False) defdecrypt(str,key): ifstr=='':returnstr v=_str2long(str,False) k=_str2long(key.ljust(16,"\0"),False) n=len(v)-1 z=v[n] y=v[0] q=6+52//(n+1) sum=(q*_DELTA)&0xffffffff while(sum!=0): e=sum>>2&3 forpinxrange(n,0,-1): z=v[p-1] v[p]=(v[p]-((z>>5^y<<2)+(y>>3^z<<4)^(sum^y)+(k[p&3^e]^z)))&0xffffffff y=v[p] z=v[n] v[0]=(v[0]-((z>>5^y<<2)+(y>>3^z<<4)^(sum^y)+(k[0&3^e]^z)))&0xffffffff y=v[0] sum=(sum-_DELTA)&0xffffffff return_long2str(v,True) if__name__=="__main__": printdecrypt(encrypt('HelloXXTEA!','16bytelongstring'),'16bytelongstring')