webqq2协议分析和qq聊天机器人简单实现
发表于 梁龙 25 February,2011(0)评论
webqq2协议分析和qq聊天机器人简单实现

通过webqq接口,可以实现发送qq消息接收qq消息等,这样,想实现一个qq聊天机器人,就不是什么难事情了了,下面开始一步步做。


1。首先调用ptlogin2.qq/check?appid=1003903&uin=qq号码,来获取qq号码验证码之类的信息。看返回结果决定是不是要输入验证码登陆
如果返回:ptui_checkVC('1','95ab7db15e5ab17f50f25d33598259e83ccc098c4af2f8a4');需要输入验证码,这里需要记住这个长字符串(获取验证码图片用)以及cookie
如果返回:ptui_checkVC('0','!MPG');不需要输入验证码,验证码值用!MPG代替。可能为其他字符串,但是以感叹号开头
如果需要输入验证码:则调用
captcha.qq/getimage?aid=1003903&&uin=qq号码&vc_type=95ab7db15e5ab17f50f25d33598259e83ccc098c4af2f8a4
获取验证码图片。。。
2。开始登陆,在登陆之前,需要将密码加密,tx的加密方法很复杂,不过还好,弄到了他的js文件,然后通过javaScriptEnginee来执行这个js来获取加密后的字符串。。。
代码:
代码
1. ScriptEngineManager m = new ScriptEngineManager();   
2. ScriptEngine se =&EngineByName("javascript");   
3. se.eval(new FileReader(new File("1.js")));   
4. Object t = se.eval("md5(md5_3(\""+p+"\")+\""+UpperCase()+"\");");   
5. return&String(); 
 
现在调用登陆接口,以获得相关的cookie。注意Referer。这个一定得加上,否则不成功:Referer : web2-b.qq/proxy.html
ptlogin2.qq/login?u=qq号码&p=密码和验证码加密后的字符串&verifycode=验证码&remember_uin=1&aid=1003903&u1=http%3A%2F%2Fweb2.qq%2Floginproxy.html%3Fstrong%

3Dtrue&h=1&ptredirect=0&ptlang=2052&from_ui=1&pttype=1&dumy=&fp=loginerroralert

登陆成功后,要记住返回的cookie值。
如其中ptwebqqskey等。

3。这还没有完成,还需要再次登录,这个好像就是qq聊天接口登陆了(刚才的登陆可以理解为登陆qq网站),只有这次登陆,才算真正登陆qq,这个时候,如果你qq已经登陆,会把你的qq踢下线,而且此次登陆才算上线时间。
地址:web2-b.qq/channel/login,把一个数据结构post给它就够了
r=%7B%22status%22%3A%22%22%2C%22ptwebqq%22%3A%22{1}%22%2C%22passwd_sig%22%3A%22%22%2C%22clientid%22%3A%22{2}%22%7D
其中{1}ptwebqq,在第2步登陆后cookie返回的,{2}clientId,自己随便定义一个数字吧。

如果成功:
会返回一个json数据结构:
{"retcode":0,"result":

{"uin":qq号码,"mode":"master","index":1055,"port":38138,"status":"online","vfwebqq":"f72a8722c988252aef4e0268f1d26a3d647f06f6ff353a5c6cdaaa49abb2fcdf0cee2d8d64373ac2","psessionid":"

8368046764001D636F6E6E7365727665725F77656271714031302E3133332E332E3234300000235100000B79026E040043F60C166D0000000A404746365677767041316D00000028F72A8722C988252AEF4E0268F1D26A3D647F06F6

FF353A5C6CDAAA49ABB2FCDF0CEE2D8D64373AC2"}}
记住其中的psessionid。后面在发送消息和获取qq消息都需要这个参数。


4。发送一个qq消息给好友
地址:web2-b.qq/channel/send_msg
同样是postr={"to":qq号码,"face":0,"content":"[\"23\",[\"font\",{\"name\":\"宋体\",\"size\":\"10\",\"style\":

[0,0,0],\"color\":\"000000

\"}]]","msg_id":7780001,"clientid":"15778909","psessionid":"8368046764001D636F6E6E7365727665725F77656271714031302E3133332E332E3234300000326F00000B71026E040043F60C166D0000000A4042725946

34574676716D00000028E7D8E44718236B0C17365E824FD3817ED2EF6C879FEE88D07EA92D030CEA72EE8E59309863128A3E"}
{"retcode":0,"result":"ok"}
需要把这个json UrlEncode一下再发送,否则会返回错误。

发送成功返回:{"retcode":0,"result":"ok"}


5。循环获取消息接口:
通过这个接口你可以实时的不间断的获取最新的消息。
web2-b.qq/channel/poll?

clientid=15778909&psessionid=8368046764001D636F6E6E7365727665725F77656271714031302E3133332E332E3234300000326F00000B71026E040043F60C166D0000000A404272594634574676716D00000028E7D8E447182

36B0C17365E824FD3817ED2EF6C879FEE88D07EA92D030CEA72EE8E59309863128A3E&t=1288591644319

返回格式:
{"retcode":0,"result":[{"poll_type":"message","value":{"msg_id":9712,"from_uin":qq号码,"to_uin":qq号码,"msg_id2":217523,"msg_type":9,"reply_ip":2887452740,"time":1288591740,"content":[["font",{"size":9,"color":"000000","style":

[0,0,0],"name":"\u5B8B\u4F53"}],"hello world"],"raw_content":"hello world"}}]}
其中的poll_type表示消息格式,message就是普通的qq消息,可以看到发送人,发送时间,以及消息的内容等。
此接口很特殊,在实现时,需要循环不间断调用,如果没有消息返回,该接口会一直等待到,有消息,读取完后要立即再调用该接口。



6.其他接口
获取头像
face7.qun.qq/cgi/svr/face/getface?cache=0&type=1&fid=0&uin=号码

获取个人信息
web2-b.qq/api/get_single_info?tuin=qq号码
获取签名
web2-b.qq/api/get_single_long_nick?tuin=qq号码&t=1288751545148
获取好友列表
web2-b.qq/api/get_user_friends
r    {"vfwebqq":"8f1383ba2239bb7295b100af215274aff1ee4be177b467cbc386fc53ff6606a8e5941aca61d0eb51"}
获取在线的qq好友
web2-b.qq/channel/get_online_buddies?clientid=9547083&psessionid=8368046764001D636F6E6E7365727665725F77656271714031302E3133332E332E323430000062F000000B86026E040043F60C166D0000000A404F526B7558357668476D000000288F1383BA2239BB7295B100AF215274AFF1EE4BE177B467CBC386FC53FF6606A8E5941ACA61D0EB51&t=1288751548600
获取最近联系人
web2-b.qq/api/get_recent_contact
r    {"vfwebqq":"8f1383ba2239bb7295b100af215274aff1ee4be177b467cbc386fc53ff6606a8e5941aca61d0eb51"}

等等。。。

7.附件这是本人通过java写的一个实例客户端,启动后,处于接受qq消息状态,当收到好友发来的消息时,回返回"然后呢?"。。。。
类似qq聊天机器人吧。。。
1.jsqq密码的加密js文件。

。。
 
完整代码:
Java代码 
1. import java.awt.image.BufferedImage;   
2. import java.io.BufferedReader;   
3. import java.io.File;   
4. import java.io.FileReader;   
5. import java.io.InputStream;   
6. import java.io.InputStreamReader;   
7. import java.HttpURLConnection;   
8. import java.URL;   
9. import java.URLEncoder;   
10. import java.util.Date;   
11. import java.util.Random;   
12. import Matcher;   
13. import Pattern;   
14.  
15. import javax.imageio.ImageIO;   
16. import javax.script.ScriptEngine;   
17. import javax.script.ScriptEngineManager;   
18.  
19. import atg.taglib.json.util.JSONArray;   
20. import atg.taglib.json.util.JSONException;   
21. import atg.taglib.json.util.JSONObject;   
22.  
23.  
24. public class QQClient {   
25.  
26.     private int qq = -1;   
27.     private String pwd = null;   
28.        
29.     private int clientid = 66933334;//这个可以随便写  
30.     private String psessionid = "";   
31.        
32.     private String ptwebqq;   
33.     private String vfwebqq;   
34.        
35.     private String skey;   
36.        
37.     private String refer = "web2-b.qq/proxy.html";   
38.        
39.     private String cookie = "";   
40.     //读取消息线程  
41.     private boolean isrun = false;   
42.     private Thread poolThread =new PollThread();   
43.     public Thread getPoolThread() {   
44.         return poolThread;   
45.     }   
46.     /**  
47.      * 记录日志  
48.      */ 
49.     private void log(String msg){   
50.         System.out.println(new Date().toLocaleString()+":"+msg);   
51.     }   
52.        
53.        
54.     public QQClient(int qq, String pwd) {   
55.         this好qq号.qq = qq;   
56.         this.pwd = pwd;   
57.         try {   
58.             boolean rs = checkAndLogin();   
59.             if(rs){   
60.                 isrun = true;   
61.                 poolThread.start();//开始循环接收  
62.                 log("启动成功");   
63.             }   
64.         } catch (Exception e) {   
65.             e.printStackTrace();   
66.         }   
67.     }   
68.     /*****************华丽的分界线*****************/ 
69.     //测试  
70.     public static void main(String[] args) throws Exception{   
71.         QQClient q = new QQClient(qq号码"123");   
72.         q.getPoolThread().join();   
73.     }   
74.        
75.     /*****************华丽的分界线*****************/ 
76.     /**  
77.      * toQQ发送一个msg消息,前提是toQQ是你的好友,要不然他收不到  
78.      */ 
79.     public boolean sendMsg(int toQQ, String message){   
80.         try {   
81.             JSONObject json = new JSONObject();   
82.             json.put("to", toQQ);//要发送的人  
83.             json.put("face"0);   
84.                
85.             JSONArray msg = new JSONArray();