




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
\o"webqq2协议分析和qq聊天机器人简单实现"webqq2协议分析和qq聊天机器人简单实现发表于
梁龙
25February,2011
8368046764001D636F6E6E7365727665725F77656271714031302E3133332E332E3234300000235100000B79026E040043F60C166D0000000A404746365677767041316D00000028F72A8722C988252AEF4E0268F1D26A3D647F06F6
FF353A5C6CDAAA49ABB2FCDF0CEE2D8D64373AC2"}}
记住其中的psessionid。后面在发送消息和获取qq消息都需要这个参数。
4。发送一个qq消息给好友
地址:/channel/send_msg
同样是post:r={"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"}
需要把这个jsonUrlEncode一下再发送,否则会返回错误。
发送成功返回:{"retcode":0,"result":"ok"}
5。循环获取消息接口:
通过这个接口你可以实时的不间断的获取最新的消息。
/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"}],"helloworld"],"raw_content":"helloworld"}}]}
其中的poll_type表示消息格式,message就是普通的qq消息,可以看到发送人,发送时间,以及消息的内容等。
此接口很特殊,在实现时,需要循环不间断调用,如果没有消息返回,该接口会一直等待到,有消息,读取完后要立即再调用该接口。
6.其他接口
获取头像
/cgi/svr/face/getface?cache=0&type=1&fid=0&uin=号码
获取个人信息
/api/get_single_info?tuin=qq号码
获取签名
/api/get_single_long_nick?tuin=qq号码&t=1288751545148
获取好友列表
/api/get_user_friends
r
{"vfwebqq":"8f1383ba2239bb7295b100af215274aff1ee4be177b467cbc386fc53ff6606a8e5941aca61d0eb51"}
获取在线的qq好友
/channel/get_online_buddies?clientid=9547083&psessionid=8368046764001D636F6E6E7365727665725F77656271714031302E3133332E332E323430000062F000000B86026E040043F60C166D0000000A404F526B7558357668476D000000288F1383BA2239BB7295B100AF215274AFF1EE4BE177B467CBC386FC53FF6606A8E5941ACA61D0EB51&t=1288751548600
获取最近联系人
/api/get_recent_contact
r
{"vfwebqq":"8f1383ba2239bb7295b100af215274aff1ee4be177b467cbc386fc53ff6606a8e5941aca61d0eb51"}
等等。。。
7.附件这是本人通过java写的一个实例客户端,启动后,处于接受qq消息状态,当收到好友发来的消息时,回返回"然后呢?"。。。。
类似qq聊天机器人吧。。。
1.js是qq密码的加密js文件。
。。
完整代码:Java代码
import
java.awt.image.BufferedImage;
import
java.io.BufferedReader;
import
java.io.File;
import
java.io.FileReader;
import
java.io.InputStream;
import
java.io.InputStreamReader;
import
.HttpURLConnection;
import
.URL;
import
.URLEncoder;
import
java.util.Date;
import
java.util.Random;
import
java.util.regex.Matcher;
import
java.util.regex.Pattern;
import
javax.imageio.ImageIO;
import
javax.script.ScriptEngine;
import
javax.script.ScriptEngineManager;
import
atg.taglib.json.util.JSONArray;
import
atg.taglib.json.util.JSONException;
import
atg.taglib.json.util.JSONObject;
public
class
QQClient
{
private
int
=
-1;
private
String
pwd
=
null;
private
int
clientid
=
66933334;//这个可以随便写
private
String
psessionid
=
"";
private
String
ptwebqq;
private
String
vfwebqq;
private
String
skey;
private
String
refer
=
"/proxy.html";
private
String
cookie
=
"";
//读取消息线程
private
boolean
isrun
=
false;
private
Thread
poolThread
=new
PollThread();
public
Thread
getPoolThread()
{
return
poolThread;
}
/**
*
记录日志
*/
private
void
log(String
msg){
System.out.println(new
Date().toLocaleString()+":"+msg);
}
public
QQClient(int
qq,
String
pwd)
{
this.qq
=
qq;
this.pwd
=
pwd;
try
{
boolean
rs
=
checkAndLogin();
if(rs){
isrun
=
true;
poolThread.start();//开始循环接收
log("启动成功");
}
}
catch
(Exception
e)
{
e.printStackTrace();
}
}
/*****************华丽的分界线*****************/
//测试
public
static
void
main(String[]
args)
throws
Exception{
QQClient
q
=
new
QQClient(qq号码,
"123");
q.getPoolThread().join();
}
/*****************华丽的分界线*****************/
/**
*
给toQQ发送一个msg消息,前提是toQQ是你的好友,要不然他收不到
*/
public
boolean
sendMsg(int
toQQ,
String
message){
try
{
JSONObject
json
=
new
JSONObject();
json.put("to",
toQQ);//要发送的人
json.put("face",
0);
JSONArray
msg
=
new
JSONArray();
msg.add(message);
JSONArray
font
=
new
JSONArray();
font.add("font");
JSONObject
font1
=
new
JSONObject().put("name",
"宋体").put("size",
"10");
JSONArray
style
=
new
JSONArray();
style.add(0);
style.add(0);
style.add(0);
font1.put("style",
style);
font1.put("color",
"000000");
font.add(font1);
msg.add(font);
json.put("content",
msg.toString());
json.put("msg_id",
new
Random().nextInt(10000000));
json.put("clientid",
clientid);
json.put("psessionid",
psessionid);//需要这个才能发送
String
sendMsgUrl
=
"/channel/send_msg";
String
content
=
json.toString();
content
=
URLEncoder.encode(content);//他要需要编码
content
="r="+content;
//发送
String
res
=
postUrl(sendMsgUrl,
content);
//不出意外,这是返回结果:{"retcode":0,"result":"ok"}
JSONObject
rh
=
new
JSONObject(res);
if("ok".equals(rh.getString("result"))){
return
true;
}
}
catch
(JSONException
e)
{
e.printStackTrace();
}
return
false;
}
/**
*
检查并且登陆
*/
private
boolean
checkAndLogin()
throws
Exception{
if(qq
==
-1
||
pwd
==
null)
throw
new
IllegalArgumentException("qq和密码不能为空");
String
checkIdUrl
=
"/check?appid=1003903&uin="+qq;
String
res
=
getUrl(checkIdUrl);
//ptui_checkVC('0','!ZLE');返回这个就不需要获取验证码了。验证码就是!ZLE
//ptui_checkVC('1','95ab7db15e5ab17f50f25d33598259e83ccc098c4af2f8a4');这个长字符串就需要使用了
Pattern
p
=
Pattern.
compile("\\,\\'([!\\w]+)\\'");
Matcher
m
=
p.
matcher(res);
String
checkType
=
"";
if(m.find()){
checkType
=
m.group(1);
}
String
check
=
"";
if(!checkType.startsWith("!")){
//需要输入验证码
String
getCheckImageUrl
=
"/getimage?aid=1003903&uin="+qq+"&vc_type="+checkType;
String
file
=
readCheckImage(getCheckImageUrl);
log("请打开"+file+",并且在这里输入其中的字符串,然后回车:");
InputStreamReader
ins
=
new
InputStreamReader(System.in);
BufferedReader
br
=
new
BufferedReader(ins);
check
=
br.readLine();
}else{
//不需要输入验证码
check
=
checkType;
}
//开始登陆
String
loginUrl
=
"/login?u="+qq+"&"
+
"p="
+mdP(pwd,
check)+
"&verifycode="+check+"&remember_uin=1&aid=1003903"
+
"&u1=http%3A%2F%2F%2Floginproxy.html%3Fstrong%3Dtrue"
+
"&h=1&ptredirect=0&ptlang=2052&from_ui=1&pttype=1&dumy=&fp=loginerroralert";
res
=
getUrl(loginUrl);
//
ptuiCB('0','0','/loginproxy.html?strong=true','0','登录成功!');
//
ptuiCB('4','0','','0','您输入的验证码有误,请重试。');
p
=
Ppile("登录成功!");//提取最后一个字符串,看看是不是
登录成功!
m
=
p.
matcher(res);
if(m.find()){
log("登陆成功");
}else{
//登陆失败
log(checkType);
return
false;
}
//从cookie中提取ptwebqq,skey
p
=
Ppile("ptwebqq=(\\w+);");
m
=
p.matcher(cookie);
if(m.find()){
ptwebqq
=
m.group(1);
}
p
=
Ppile("skey=(@\\w+);");
m
=
p.matcher(cookie);
if(m.find()){
skey
=
m.group(1);
}
log("ptwebqq="+ptwebqq+",skey="+skey);
//再次登陆,只有这次登陆,才算真正登陆qq,这个时候,如果你qq已经登陆,会把你的qq踢下线,而且此次登陆才算上线。
String
channelLoginUrl
=
"/channel/login";
String
content
=
"{\"status\":\"\",\"ptwebqq\":\""+ptwebqq+"\",\"passwd_sig\":\"\",\"clientid\":\""+clientid+"\"}";
content
=
URLEncoder.encode(content);//urlencode
content
=
"r="+content;//post的数据
res
=
postUrl(channelLoginUrl,
content);//post
//这次登陆基本上不会发生什么问题
//下面提取很重要的2个数据psessionid
,vwebqq,通用采用正则表达式,虽然结果是个json
p
=
Ppile("\"vfwebqq\":\"(\\w+)\"");
m
=
p.matcher(res);
if(m.find()){
vfwebqq
=
m.group(1);
}
p
=
Ppile("\"psessionid\":\"(\\w+)\"");
m
=
p.matcher(res);
if(m.find()){
psessionid
=
m.group(1);
}
log("vwebqq="+vfwebqq+","+"psessionid="+psessionid);
//到此,登陆就算完成了,后面可以调用发送qq信息等接口了
return
true;
}
/**
*
调用tx的js来生成密钥
*/
public
String
mdP(String
p,
String
code){
try
{
ScriptEngineManager
m
=
new
ScriptEngineManager();
ScriptEngine
se
=
m.getEngineByName("javascript");
se.eval(new
FileReader(new
File("1.js")));
Object
t
=
se.eval("md5(md5_3(\""+p+"\")+\""+code.toUpperCase()+"\");");
return
t.toString();
}catch
(Exception
e)
{
e.printStackTrace();
}
return
null;
}
/**
*
POST一个url,contents是输入的内容
*/
private
String
postUrl(String
url,
String
contents){
try{
System.out.println("post>>>"+url);
URL
serverUrl
=
new
URL(url);
HttpURLConnection
conn
=
(HttpURLConnection)
serverUrl.openConnection();
conn.setRequestMethod("POST");//"POST"
,"GET"
if(refer
!=
null){
conn.addRequestProperty("Referer",
refer);
}
conn.addRequestProperty("Cookie",
cookie);
conn.addRequestProperty("Accept-Charset",
"UTF-8;");//GB2312,
conn.addRequestProperty("User-Agent",
"Mozilla/5.0
(Windows;
U;
Windows
NT
5.1;
zh-CN;
rv:)
Firefox/3.6.8");
conn.setDoOutput(true);
conn.connect();
conn.getOutputStream().write(contents.getBytes());
if(conn.getHeaderFields().get("Set-Cookie")
!=
null){
for(String
s:conn.getHeaderFields().get("Set-Cookie")){
cookie
+=
s;
}
}
InputStream
ins
=
conn.getInputStream();
String
charset
=
"UTF-8";
InputStreamReader
inr
=
new
InputStreamReader(ins,
charset);
BufferedReader
bfr
=
new
BufferedReader(inr);
String
line
=
"";
StringBuffer
res
=
new
StringBuffer();
do{
res.append(line);
line
=
bfr.readLine();
//System.out.println(line);
}while(line
!=
null);
System.out.println(">>>==="+res);
return
res.toString();
}catch(Exception
e){
e.printStackTrace();
return
null;
}
}
/**
*
GET
一个url
*/
private
String
getUrl(String
url){
try{
System.out.println("get>>>"+url);
URL
serverUrl
=
new
URL(url);
HttpURLConnection
conn
=
(HttpURLConnection)
serverUrl.openConnection();
conn.setRequestMethod("GET");//"POST"
,"GET"
//
conn.setDoOutput(true);
if(refer
!=
null){
conn.addRequestProperty("Referer",
refer);
}
conn.addRequestProperty("Cookie",
cookie);
conn.addRequestProperty("Accept-Charset",
"UTF-8;");//GB2312,
conn.addRequestProperty("User-Agent",
"Mozilla/5.0
(Windows;
U;
Windows
NT
5.1;
zh-CN;
rv:)
Firefox/3.6.8");
conn.connect();
if(conn.getHeaderFields().get("Set-Cookie")
!=
null){
for(String
s:conn.getHeaderFields().get("Set-Cookie")){
cookie
+=
s;
}
}
InputStream
ins
=
conn.getInputStream();
String
charset
=
"UTF-8";
InputStreamReader
inr
=
new
InputStreamReader(ins,
charset);
BufferedReader
bfr
=
new
BufferedReader(inr);
String
line
=
"";
StringBuffer
res
=
new
StringBuffer();
do{
res.append(line);
line
=
bfr.readLine();
//System.out.println(line);
}while(line
!=
null);
System.out.println(">>>==="+res);
return
res.toString();
}catch(Exception
e){
e.printStackTrace();
return
null;
}
}
/**
*
读取验证码。返回验证码文件保存的路径
*/
private
String
readCheckImage(String
url){
try{
System.out.println("get>>>"+url);
URL
serverUrl
=
new
URL(url);
HttpURLConnection
conn
=
(HttpURLConnection)
serverUrl.openConnection();
conn.setRequestMethod("GET");//"POST"
,"GET"
conn.addRequestProperty("Accept-Charset",
"UTF-8;");//GB2312,
conn.addRequestProperty("User-Agent",
"Mozilla/5.0
(Windows;
U;
Windows
NT
5.1;
zh-CN;
rv:)
Firefox/3.6.8");
conn.connect();
//返回的cookie
if(conn.getHeaderFields().get("Set-Cookie")
!=
null)
for(String
s:conn.getHeaderFields().get("Set-Cookie")){
cookie
+=
s;
}
InputStream
ins
=
conn.getInputStream();
BufferedImage
bi
=
ImageIO.read(ins);
File
f
=new
File("qqimg.jpg");
ImageIO.write(bi,
"jpg",
f);
return
f.getAbsolutePath();
}catch(Exception
e){
e.printStackTrace();
}
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
评论
0/150
提交评论