版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
\o"webqq2協(xié)議分析和qq聊天機器人簡單實現(xiàn)"webqq2協(xié)議分析和qq聊天機器人簡單實現(xiàn)發(fā)表于
梁龍
25February,2011
8368046764001D636F6E6E7365727665725F77656271714031302E3133332E332E3234300000235100000B79026E040043F60C166D0000000A404746365677767041316D00000028F72A8722C988252AEF4E0268F1D26A3D647F06F6
FF353A5C6CDAAA49ABB2FCDF0CEE2D8D64373AC2"}}
記住其中的psessionid。后面在發(fā)送消息和獲取qq消息都需要這個參數(shù)。
4。發(fā)送一個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一下再發(fā)送,否則會返回錯誤。
發(fā)送成功返回:{"retcode":0,"result":"ok"}
5。循環(huán)獲取消息接口:
通過這個接口你可以實時的不間斷的獲取最新的消息。
/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消息,可以看到發(fā)送人,發(fā)送時間,以及消息的內(nèi)容等。
此接口很特殊,在實現(xiàn)時,需要循環(huán)不間斷調(diào)用,如果沒有消息返回,該接口會一直等待到,有消息,讀取完后要立即再調(diào)用該接口。
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
獲取最近聯(lián)系人
/api/get_recent_contact
r
{"vfwebqq":"8f1383ba2239bb7295b100af215274aff1ee4be177b467cbc386fc53ff6606a8e5941aca61d0eb51"}
等等。。。
7.附件這是本人通過java寫的一個實例客戶端,啟動后,處于接受qq消息狀態(tài),當收到好友發(fā)來的消息時,回返回"然后呢?"。。。。
類似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();//開始循環(huán)接收
log("啟動成功");
}
}
catch
(Exception
e)
{
e.printStackTrace();
}
}
/*****************華麗的分界線*****************/
//測試
public
static
void
main(String[]
args)
throws
Exception{
QQClient
q
=
new
QQClient(qq號碼,
"123");
q.getPoolThread().join();
}
/*****************華麗的分界線*****************/
/**
*
給toQQ發(fā)送一個msg消息,前提是toQQ是你的好友,要不然他收不到
*/
public
boolean
sendMsg(int
toQQ,
String
message){
try
{
JSONObject
json
=
new
JSONObject();
json.put("to",
toQQ);//要發(fā)送的人
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);//需要這個才能發(fā)送
String
sendMsgUrl
=
"/channel/send_msg";
String
content
=
json.toString();
content
=
URLEncoder.encode(content);//他要需要編碼
content
="r="+content;
//發(fā)送
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已經(jīng)登陸,會把你的qq踢下線,而且此次登陸才算上線。
String
channelLoginUrl
=
"/channel/login";
String
content
=
"{\"status\":\"\",\"ptwebqq\":\""+ptwebqq+"\",\"passwd_sig\":\"\",\"clientid\":\""+clientid+"\"}";
content
=
URLEncoder.encode(content);//urlencode
content
=
"r="+content;//post的數(shù)據(jù)
res
=
postUrl(channelLoginUrl,
content);//post
//這次登陸基本上不會發(fā)生什么問題
//下面提取很重要的2個數(shù)據(jù)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);
//到此,登陸就算完成了,后面可以調(diào)用發(fā)送qq信息等接口了
return
true;
}
/**
*
調(diào)用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是輸入的內(nèi)容
*/
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. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五版美發(fā)培訓學校師資聘用標準合同4篇
- 2025年度門面租賃合同電子版(含租金遞增與調(diào)整機制)
- 2025年度簽競業(yè)協(xié)議打工人財產(chǎn)保全及職業(yè)規(guī)劃合同
- 二零二五年度酒店前臺員工權益保障與勞動合同
- 二零二五年度超市與物流公司貨物扣點運輸合同
- 2025年度復雜地質(zhì)條件頂管施工安全協(xié)議書
- 2025年度住宅室內(nèi)裝修工程保修協(xié)議
- 2025年度簽競業(yè)協(xié)議打工人財產(chǎn)保全及心理支持合同
- 2025年度跆拳道青少年運動員培養(yǎng)合作協(xié)議
- 二零二五年度退休人員教育輔助教學勞務合同
- 2024年國家焊工職業(yè)技能理論考試題庫(含答案)
- 特魯索綜合征
- 《向心力》 教學課件
- 結構力學數(shù)值方法:邊界元法(BEM):邊界元法的基本原理與步驟
- 2024年山東省泰安市高考語文一模試卷
- 北師大版物理九年級全一冊課件
- 2024年第三師圖木舒克市市場監(jiān)督管理局招錄2人《行政職業(yè)能力測驗》高頻考點、難點(含詳細答案)
- RFJ 006-2021 RFP型人防過濾吸收器制造與驗收規(guī)范(暫行)
- 盆腔炎教學查房課件
- 110kv各類型變壓器的計算單
- 新概念英語課件NCE3-lesson15(共34張)
評論
0/150
提交評論