webqq2协议分析和qq聊天机器人简单实现
更新时间:2023-06-08 22:46:01 阅读量: 实用文档 文档下载
- webqq2推荐度:
- 相关推荐
webqq2协议分析和qq聊天机器人简单实现
webqq2协议分析和qq聊天机器人简单实现
通过webqq接口,可以实现发送qq消息接收qq消息等,这样,想实现一个qq聊天机器人,就不是什么难事情了了,下面开始一步步做。
1。首先调用/check?appid=1003903&uin=qq号码,来获取该qq号码验证码之类的信息。看返回结果决定是不是要输入验证码登陆。
如果返回:ptui_checkVC('1','95ab7db15e5ab17f50f25d33598259e83ccc098c4af2f8a4');需要输入验证码,这里需要记住这个长字符串(获取验证码图片用)以及cookie
如果返回:ptui_checkVC('0','!MPG');不需要输入验证码,验证码值用!MPG代替。可能为其他字符串,但是以感叹号开头
如果需要输入验证码:则调用
/getimage?aid=1003903&&uin=qq号码&vc_type=95ab7db15e5ab17f50f25d33598259e83ccc098c4af2f8a4
获取验证码图片。。。
2。开始登陆,在登陆之前,需要将密码加密,tx的加密方法很复杂,不过还好,弄到了他的js文件,然后通过java的ScriptEnginee来执行这个js来获取加密后的字符串。。。
代码:
Java代码
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();
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();
现在调用登陆接口,以获得相关的cookie。注意Referer。这个一定得加上,否则不成功:Referer : /proxy.html
/login?u=qq号码&p=密码和验证码加密后的字符串&verifycode=验证码&remember_uin=1&aid=1003903&u1=http%3A%2F%%2Floginproxy.html%3Fstrong%
3Dtrue&h=1&ptredirect=0&ptlang=2052&from_ui=1&pttype=1&dumy=&fp=loginerroralert
登陆成功后,要记住返回的cookie值。
如其中ptwebqq,skey等。
3。这还没有完成,还需要再次登录,这个好像就是qq聊天接口登陆了(刚才的登陆可以理解为登陆qq网站),只有这次登陆,才算真正登陆qq,这个时候,如果你qq已经登陆,会把你的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","ind
ex":1055,"port":38138,"status":"online","vfwebqq":"f72a8722c988252aef4e0268f1d26a3d647f06f6ff3
webqq2协议分析和qq聊天机器人简单实现
53a5c6cdaaa49abb2fcdf0cee2d8d64373ac2","psessionid":"
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"}
需要把这个json UrlEncode一下再发送,否则会返回错误。
发送成功返回:{"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"}],"hello world"],"raw_content":"hello world"}}]}
其中的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=8368046764001D636F6E6E7365727665725F77656271714031302E3133332E332E323430000062F000000B86026E040043F60C166D0000000A404F526B7558357668476D000000288F1383BA2239BB729
5B100AF215274AFF1EE4BE177B467CBC386FC53FF6606A8E5941ACA61D0EB51&t=1288751548600
获取最近联系人
/api/get_recent_contact
r
webqq2协议分析和qq聊天机器人简单实现
{"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 net.sf.json.JSONArray;
import net.sf.json.JSONException;
import net.sf.json.JSONObject;
public class QQClient {
private int qq = -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(903695452, "fafengongzuo");
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();
font1.put("name", "宋体");
font1.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("ms
webqq2协议分析和qq聊天机器人简单实现
g_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();
rh.getJSONObject(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 = pile("\\,\\'([!\\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%%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 = pile("登录成功!");// 提取最后一个字符串,看看是不是 登录成功!
m = p.matcher(res);
if (m.find()) {
log("登陆成功");
} else {
// 登陆失败
log(checkType);
return false;
}
// 从cookie中提取ptwebqq,skey
p = pile("ptwebqq=(\\w+);");
m = p.matcher(cookie);
if (m.find()
) {
ptwebqq = m.group(1);
}
p = pile("skey=(@\\w+);");
m = p.matcher(cookie);
if (m.find()) {
skey = m.gr
webqq2协议分析和qq聊天机器人简单实现
oup(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 = pile("\"vfwebqq\":\"(\\w+)\"");
m = p.matcher(res);
if (m.find()) {
vfwebqq = m.group(1);
}
p = pile("\"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:1.9.2.8) 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();
webqq2协议分析和qq聊天机器人简单实现
} 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:1.9.2.8) 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:1.9.2.8) 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();
}
return null;
}
/**
* 当有qq消息是回调此函数
*/
public void receiveMsg(String message, int fromQQ) {
log("qq:" + fromQQ + "说:" + message);
// test
sendMsg(fromQQ, "然后呢?");
}
/**
* 通过poll一直等待服务器回应。比如收到消息啊,好友上线啊,申请好友啊之类的各类消息都会通过此接口返回,在获得数据后,应该继续poll获取下个数据
*
/channel/poll
*/
class PollThread extends Thread {
private String pollUrl = "/channel/po
webqq2协议分析和qq聊天机器人简单实现
ll";
@Override
public void run() {
String url = pollUrl + "?clientid=" + clientid + "&psessionid="
+ psessionid;
try {
while (isrun) {
// 线程一直等待知道服务器有返回数据
String res = getUrl(url);
JSONObject retJ = new JSONObject();
retJ.getJSONObject(res);
JSONObject rh = new JSONObject();
rh.getJSONObject(res);
if (retJ.getInt("retcode") == 0) {
JSONArray result = retJ.getJSONArray("result");
String poll_type = result.getJSONObject(0).getString(
"poll_type");
if ("message".equals(poll_type)) {
// 说明有人发qq消息给我,
String raw_content = result.getJSONObject(0)
.getJSONObject("value").get("raw_content")
.toString();
int from_uin = result.getJSONObject(0)
.getJSONObject("value").getInt("from_uin");
log("收到来自:" + from_uin + ":" + raw_content);
// 通知客
户端收到了
receiveMsg(raw_content, from_uin);
}
// system_message 是系统消息
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}
正在阅读:
新改建扩建项目安全管理规定12-22
乡镇2021年度上半年新农村建设多篇工作总结精选汇报08-03
佛教祈请文(打印版)09-09
广西烟草考试真题07-23
Burster10-01
2015年无忧学习网考研专业课高清课程陆续发布中,欢迎试听!03-10
传统解剖钢板联合自体植骨与锁定钢板非植骨疗法在 Sanders、型跟03-09
模糊推理系统在DSP上的实现和优化05-15
《机械设计基础》第1章:绪论05-16
- 教学能力大赛决赛获奖-教学实施报告-(完整图文版)
- 互联网+数据中心行业分析报告
- 2017上海杨浦区高三一模数学试题及答案
- 招商部差旅接待管理制度(4-25)
- 学生游玩安全注意事项
- 学生信息管理系统(文档模板供参考)
- 叉车门架有限元分析及系统设计
- 2014帮助残疾人志愿者服务情况记录
- 叶绿体中色素的提取和分离实验
- 中国食物成分表2020年最新权威完整改进版
- 推动国土资源领域生态文明建设
- 给水管道冲洗和消毒记录
- 计算机软件专业自我评价
- 高中数学必修1-5知识点归纳
- 2018-2022年中国第五代移动通信技术(5G)产业深度分析及发展前景研究报告发展趋势(目录)
- 生产车间巡查制度
- 2018版中国光热发电行业深度研究报告目录
- (通用)2019年中考数学总复习 第一章 第四节 数的开方与二次根式课件
- 2017_2018学年高中语文第二单元第4课说数课件粤教版
- 上市新药Lumateperone(卢美哌隆)合成检索总结报告
- 机器人
- 协议
- 简单
- 实现
- 聊天
- 分析
- webqq2