A chance I saw a QQ number in a group is always based on the message you send your own initiative to reply, at that time very feeling wonderful. I know to be able to simulate the login site, unexpectedly can also be simulated login QQ, the first thing I think of is how to achieve the simulation of the PC-side QQ, began to study the next, found that QQ sent packets are very difficult to understand.
So it turned to the web version of QQ, because in the Web page can capture all the requests to better realize the simulation function!
First, the first step is to open the Web version of QQ. Open the browser developer mode to monitor all requests here!
When I open the login screen,
A GET request is captured
https://ssl.ptlogin2.qq.com/check?uin=10588690&appid=1003903&js_ver=10080&js_type=0&login_sig= yw1zuusiu*7fepsr1blgegcsvwehcrnvvqutt1lz0paoxz-6xhtypeqngoo-velq&u1=http%3a%2f%2fweb2.qq.com% 2floginproxy.html&r=0.5928007187321782
UIn is your QQ number.
The return value is PTUI_CHECKVC (' 1 ', ' aar4bdjmeh2hea77ptuohhqmtxbrqop3 ', ' \x00\x00\x00\x00\x00\xa1\x92\x12 ');
1 means a verification code is required another return value PTUI_CHECKVC (' 0 ', '! Ljv ', ' \x00\x00\x00\x00\x00\xa1\x92\x12 ') such representations are not required by the CAPTCHA
def checkverify (Self,uin): check= "https://ssl.ptlogin2.qq.com/check?uin={uin}&appid=1003903&js_ver= 10080&js_type=0&login_sig=ypd0p*wu2n8vw1os2f7vfzvpf3ku5vnkp4nzimf0gybr02fskzdjgyb7f9r7nqrn&u1=http %3a%2f%2fweb2.qq.com%2floginproxy.html&r=0.8179273759014904 " check=check.replace (' {UIn} ', UIn) Pattern=re.compile ("ptui_checkvc\ (. *) ', ' (. *) ', ' (. *) ' \);") Result=self. Get (check) checked= pattern.search (Result). Groups () print ' step1:checkverify ' return checked
How to obtain a verification code
def getverify (self): #url = ' https://ssl.captcha.qq.com/getimage?&uin= ' +str (self. QQ) + ' &aid=1002101&0.45644426648505 ' + str (random.randint (10,99)) verify= "https://ssl.captcha.qq.com/ GETIMAGE?AID=1003903&R=0.6472875226754695&UIN={QQ}&CAP_CD=ASD-ZVCNECOZLZUURHNYHP-MBHF4HJBJ " Verify=verify.replace (' {QQ} ', self. QQ) path= R "c:/verify/1.jpg" #data = Urllib.urlretrieve (url,path) data = Urllib2.urlopen (verify) Localpic =open (r "c:/verify/1.jpg", ' WB ') Localpic.write (Data.read ()) Localpic.close ()
Enter username and password and send a GET request after verification code
Https://ssl.ptlogin2.qq.com/login?
U=10588690&p=ab80cd3b6429d9660878e93058dd78bd&verifycode=teyx&webqq_type=10&remember_uin=1 &login2qq=1&aid=1003903&u1=http%3a%2f%2fweb2.qq.com%2floginproxy.html%3flogin2qq%3d1%26webqq_type% 3d10&h=1&ptredirect=0&ptlang=2052&daid=164&from_ui=1&pttype=1&dumy=&fp= loginerroralert&action=6-14-296574&mibao_css=m_webqq&t=1&g=1&js_type=0&js_ver=10080 &login_sig=yw1zuusiu*7fepsr1blgegcsvwehcrnvvqutt1lz0paoxz-6xhtypeqngoo-velq&pt_uistyle=5
This inside u represents the account p represents password password is a certain algorithm encrypted verify is the verification code
Cryptographic algorithms such as the following
def passwordsecret (self,password,v1,v2,md5=true): if md5==true: password=self. PCMD5 (password). Upper () length=len (password) temp= "For me in Range (0,length,2): temp+=r ' \x ' + PASSWORD[I:I+2] return self. PCMd5 (self. PCMD5 (SELF.HEX2ASC (temp) +SELF.HEX2ASC (v2)). Upper () +v1). Upper () #md5加密函数 def PCMd5 (self,s): h=hashlib.md5 () h.update (s) return h.hexdigest () #16进制转字符 def hex2asc (self,s): _str= "". Join (S.split ( R ' \x ')) Length=len (_str) data= "For me in Range (0,length,2): data+=chr (int (_str[i:i+2],16)) return Data
And then the login section code.
def Login (self,uin,pwd): #获取參数 cheked=self. Checkverify (UIn) #加密password #pwd =self. Passwordsecret (pwd,cheked[1],cheked[2]) #pwd =self. Passwordsecret (pwd,r ' aast ', R ' \x00\x00\x00\x00\x00\xa1\x92\x12 ') loginurl= "Https://ssl.ptlogin2.qq.com/login?U={uin}&p={pwd}&verifycode={verify}&webqq_type=10&remember_uin=1&login2qq=1&aid= 1003903&u1=http%3a%2f%2fweb2.qq.com%2floginproxy.html%3flogin2qq%3d1%26webqq_type%3d10&h=1& ptredirect=0&ptlang=2052&daid=164&from_ui=1&pttype=1&dumy=&fp=loginerroralert& action=4-30-135914&mibao_css=m_webqq&t=1&g=1&js_type=0&js_ver=10080&login_sig=ypd0p* Wu2n8vw1os2f7vfzvpf3ku5vnkp4nzimf0gybr02fskzdjgyb7f9r7nqrn&pt_uistyle=5 "Loginurl=loginurl.replace (' {UIn} ', UIn) #loginurl =loginurl.replace (' {pwd} ', pwd) #loginurl =loginurl.replace (' {verify} ', Cheked[1]) #result =get (loginurl) if (cheked[0]== "1"): #下载验证码 self. Getverify () image = Image.open (r "C:/verify/1.jpg") Image.show () code=raw_input ("Verifycod E: "). Strip () Loginurl=loginurl.replace (' {verify} ', Code.upper ()) pwd=self. Passwordsecret (pwd,r "+code.upper (), CHEKED[2]) #pwd =self. Passwordsecret (pwd,cheked[1],cheked[2]) else:loginurl=loginurl.replace (' {verify} ', Cheked[1]) Pwd=self. Passwordsecret (pwd,cheked[1],cheked[2]) loginurl=loginurl.replace (' {pwd} ', pwd) result=self. Get (loginurl, ' ssl.ptlogin2.qq.com ', ' https://ui.ptlogin2.qq.com/cgi-bin/login?daid=164&target=self& style=5&mibao_css=m_webqq&appid=1003903&enable_qlogin=0&no_verifyimg=1&s_url=http%3a%2f% 2fweb2.qq.com%2floginproxy.html&f_url=loginerroralert&strong_login=1&login_state=10&t= 20140514001 ', None) print ' Step2:login ' Pattern=re.compile ("ptuicb\ (. *) ', ' (. *) ', ' (. *) ', ' (. *) ', ' (. *) ', ' (. *) ', \s ' (.) *)‘\);") ret= Pattern.search (Result). Groups () #获取必要的cookie Otherwise the second login will go wrong self. Get (ret[2]) print ' Step3:getcookie ' for C in Self.cj:if c.name== ' ptwebqq ': self. Ptwebqq=c.value return result
Server returns a string of JSON data after the login is successful
PTUICB (' 0 ', ' 0 ', ' http://ptlogin4.web2.qq.com/check_sig?pttype=1&uin=10588690&service=login&nodirect =0&ptsig=*zwu0pftmyp93fbdt6uszbbodzlz0ey9g25pdge5zzu_&s_url=http%3a%2f%2fweb2.qq.com%2floginproxy.html %3flogin2qq%3d1%26webqq_type%3d10&f_url=&ptlang=2052&ptredirect=100&aid=1003903&daid=164 &j_later=0&low_login_hour=0®master=0&pt_login_type=1&pt_aid=0&pt_aaid=0&pt_ Light=0 ', ' 0 ', ' Login successful!
', ' little Bamboo ');
The first 0 indicates a successful login, but there is no real sign-in success
The URL in the return value above is used to obtain a key cookie that is PTWEBQQ
Then a second login, this time is the real login
Http://d.web2.qq.com/channel/login2
Requests such as the following
- accept:*/*
- Accept-encoding:gzip,deflate,sdch
- accept-language:zh-cn,zh;q=0.8
- Connection:keep-alive
- content-length:244
- content-type:application/x-www-form-urlencoded
- cookie:o_cookie=455910092; RK=FMEAWEZ0QC; ts_last=web2.qq.com/; ts_refer=www.baidu.com/; ts_uid=4588821804; pgv_pvid=914251705; pgv_info=ssid=s3525422600&pgvreferrer=; verifysession=h02leyrtarkwbzesu_czkiczensnldm7v1mcm-a5qatkwnhanfgb2z46zh4x7ofyhft7wh6lfschpvslhdgxfa4ea**; ptui_loginuin=10588690; PTISP=CNC; PTCZ=DACE9CF90E7064A16EE56C8153273EFF9F2DE1D2827BA31F6571412AC18C50C3; PTWEBQQ=B21232ED3519839063D1C2EAD8A8588C385D168097EFDF88BC56E1A78BE7DFB4; pt2gguin=o0010588690; uin=o0010588690; [Email protected]; p_uin=o0010588690; p_skey=cz5*ks-nocxld2q0aepjnmexwc2ya0g7jbtygpvfia8_; pt4_token=1syuj39eq6okewehgiizeg__
- Host:d.web2.qq.com
- Origin:http://d.web2.qq.com
- referer:http://d.web2.qq.com/proxy.html?v=20110331002&callback=1&id=2
- user-agent:mozilla/5.0 (Windows NT 6.2; WOW64) applewebkit/537.36 (khtml, like Gecko) chrome/34.0.1847.116 safari/537.36
- Form DataView SourceView URL encoded
- r:{"status": "Online", "PTWEBQQ": "B21232ed3519839063d1c2ead8a8588c385d168097efdf88bc56e1a78be7dfb4", "Passwd_sig" : "", "ClientID": "7963288", "Psessionid": null}
- clientid:7963288
- Psessionid:null
The PTWEBQQ is what we just obtained from the cookie.
This part of the code is
def Login2 (self): try: url= "http://d.web2.qq.com/channel/login2" postdata= "r=%7b%22status%22%3a% 22online%22%2c%22ptwebqq%22%3a%22{$ptwebqq}%22%2c%22passwd_sig%22%3a%22%22%2c%22clientid%22%3a%22{$clientid}% 22%2c%22psessionid%22%3anull%7d&clientid={$clientid}&psessionid=null " postdata=postdata.replace (" { $PTWEBQQ} ", SELF.PTWEBQQ) postdata=postdata.replace (" {$clientid} ", str (self.clientid)) print ' STEP4: Login2 ' result=self. Post (url,postdata,qqrobot.host[0],qqrobot.referer[0],qqrobot.origin[0]) retjson=json.loads (Result) retjson=retjson["Result"] return Retjson except exception,e: print "Login2 error" +str (e)
A second login succeeds and returns a
' {' Retcode ': 0,
"Result": {
"UIn": 10588690,
"CIP": 1707901841,
"Index": 1075,
"Port": 59571,
"Status": "Online",
"VFWEBQQ": "C043f1f6ce5c3b76a4603ab60082668bef2dde0b987808f728e2071eb7c164eeb30fcd85c31018d2",
"Psessionid": " 8368046764001d636f6e6e7365727665725f77656271714031302e3133392e372e31363000006cb000001ae1036200a192126d0000000a40356c59374 2635175316d00000028c043f1f6ce5c3b76a4603ab60082668bef2dde0b987808f728e2071eb7c164eeb30fcd85c31018d2 ",
"User_state": 0,
"F": 0
}
}‘‘‘
0 of this data structure indicates a successful landing
Need to save this write data
After the landing, we'll be able to pull out the list.
#获取群列表信息 def getgroupnamelist (SELF,VFWEBQQ): Try:url= "HTTP://S.WEB2. Qq.com/api/get_group_name_list_mask2 "Postdata=" r=%7b%22vfwebqq%22%3a%22{$vfwebqq}%22%7d "postdata=p Ostdata.replace ("{$vfwebqq}", Vfwebqq) ret=self. Post (url,postdata,qqrobot.host[1],qqrobot.referer[1],qqrobot.origin[1]) print ' step5:getgrouplist ' Retjson=json.loads (ret) retjson=retjson["result"] Self.grouplist=retjson for group in SEL f.grouplist[' gnamelist ': Print group["code"],group["name"] except Exception,e: Print "Getgroupnamelist error" +str (e)
#获取群成员信息 def getgroupinfo (SELF,GCODE,VFWEBQQ): try: url= "Http://s.web2.qq.com/api/get_group_info_ ext2?gcode={$gcode}&cb=undefined&vfwebqq={$vfwebqq}&t=1402069438458 " url=url.replace (" {$ VFWEBQQ} ", VFWEBQQ) url=url.replace (" {$gcode} ", str (gcode)) ret=self. Get (url,qqrobot.host[1],qqrobot.referer[1],none) print "Step6:getgroupinfo" retjson=json.loads (ret) retjson=retjson["Result"] Self.groupuserlist=retjson except exception,e: print "GetGroupInfo Error "+STR (e)
#发送群消息 def sendgroupmsg (Self,groupid,msg,psessionid): try: #msg =u ":" +msg #msg =msg.stri P () #urlmsg =quote (Msg.encode (' UTF8 ')) #把普通字符串包裹起来 stype= "%5c%22{content}%5c%22" temp= "" part= "" for C-msg:if type (c) is types. Listtype:part=quote (str (c). Strip (). Encode (' UTF8 ') + "%2c" #part = Part.replace ("%20", "") Part=part.replace ("%27", "%5c%22") #把 ' change to \ ' Part=part.replac E ("U", "") #把 u change to null Temp+=part else:temp+=stype.replace ("{content}", QUOTE (C.encode (' UTF8 ')) + "%2c" Temp=temp[0:len (temp)-3] #urlmsg = "%5c%228%5c%22" # "%5b%5c% 22face%5c%22%2c13%5d "Urlmsg=temp url=" HTTP://D.WEB2.QQ.COM/CHANNEL/SEND_QUN_MSG2 "msg_id = 77860003 #postdata = "r=%7b%22group_uin%22%3a{$group _uin}%2c%22content%22%3a%22%5b%5c%22{$msg}%5c%22%2c%5c%22%5c%22%2c%5b%5c%22font%5c%22%2c%7b%5c%22name% 5c%22%3a%5c%22%e5%ae%8b%e4%bd%93%5c%22%2c%5c%22size%5c%22%3a%5c%2210%5c%22%2c%5c%22style%5c%22%3a%5b0%2c0%2c0% 5d%2c%5c%22color%5c%22%3a%5c%22000000%5c%22%7d%5d%5d%22%2c%22msg_id%22%3a{$msg _id}%2c%22clientid%22%3a%22{$ clientid}%22%2c%22psessionid%22%3a%22{$psessionid}%22%7d&clientid={$clientid}&psessionid={$psessionid} "#表情 #postdata =" r=%7b%22group_uin%22%3a{$group _uin}%2c%22content%22%3a%22%5b{$msg}%2c%5c%22%5c%5cn% 5c%22%2c%5b%5c%22font%5c%22%2c%7b%5c%22name%5c%22%3a%5c%22%e5%ae%8b%e4%bd%93%5c%22%2c%5c%22size%5c%22%3a%5c% 2210%5c%22%2c%5c%22style%5c%22%3a%5b0%2c0%2c0%5d%2c%5c%22color%5c%22%3a%5c%22000000%5c%22%7d%5d%5d%22%2c%22msg _id%22%3a{$msg _id}%2c%22clientid%22%3a%22{$clientid}%22%2c%22psessionid%22%3a%22{$psessionid}%22%7d& clientid={$clientid}&psessionid={$psessionid} "#字符 postdata=" r=%7b%22group_uin%22%3a{$group _uin}%2c%22content%22%3a%22%5b{$msg}%2c%5c%22%5c%22%2c%5b%5c%22font%5c%22%2c%7b%5c%22name%5c%22%3a%5c%22%e5%ae%8b %e4%bd%93%5c%22%2c%5c%22size%5c%22%3a%5c%2210%5c%22%2c%5c%22style%5c%22%3a%5b0%2c0%2c0%5d%2c%5c%22color%5c%22% 3a%5c%22000000%5c%22%7d%5d%5d%22%2c%22msg_id%22%3a{$msg _id}%2c%22clientid%22%3a%22{$clientid}%22%2c% 22psessionid%22%3a%22{$psessionid}%22%7d&clientid={$clientid}&psessionid={$psessionid} "pos Tdata=postdata.replace ("{$group _uin}", str (GROUPID)) Postdata=postdata.replace ("{$psessionid}", Psessionid) Postdata=postdata.replace ("{$clientid}", str (Self.clientid)) Postdata=postdata.replace ("{$msg _id}", Str (msg _id)) Postdata=postdata.replace ("{$msg}", urlmsg) self. Post (url,postdata,qqrobot.host[0],qqrobot.referer[0],qqrobot.origin[0]) except Exception,e:print "SendG Roupmsg Error "+STR (e) #print" Send msg: "+str (MSG)
The heartbeat is to ask the server once every time to prove that you are still there!
#心跳包 def Heartbreak (Self,psessionid): Url= "Http://d.web2.qq.com/channel/poll2" Postdata= "R=%7b%22clientid %22%3a%22{$clientid}%22%2c%22psessionid%22%3a%22{$psessionid}%22%2c%22key%22%3a0%2c%22ids%22%3a%5b%5d%7d& clientid={$clientid}&psessionid={$psessionid} "Postdata=postdata.replace (" {$clientid} ", str (SELF.CLIENTID)) Postdata=postdata.replace ("{$psessionid}", Psessionid) while True: #每隔2秒发送心跳包 ret=self. Post (Url,postdata,qqrobot.host[0],qqrobot.referer[0],qqrobot.origin[0]) try:retjson=json.loads ( RET) retjson=retjson["result"] retjson=retjson[0] #print "Heartbreak" if (retjson["Poll_type"]== "Group_message"): msg=retjson["value"] self. PROCESSMSG (msg) except exception,e: #print "Heartbreak Error" +str (e) Pass Time.sleep (2)
Item http://download.csdn.net/detail/zhujunxxxxx/7663953
Continue to update tomorrow.
。。。。
。
Welcome everyone to my personal site http://www.zhujuncoding.com
Python implementation QQ robot (self-login, get group messages, send group messages)