最近公司需要做个qq机器人获取qq好友列表,并且能够自动向选定的qq好友定时发送消息。没有头绪,硬着头皮上

甘甜的心情瞬间变得苦涩了 哇 多捞吆

1.WEBQQ3.0登陆协议

进入WEBQQ, http://web.qq.com/
通过工具分析,可以知道,用户在输入密码之前(也就是输入帐号后),会首先GET一个请求过去

https://ssl.ptlogin2.qq.com/check?uin=1432334894&appid=1003903&r=0.5534069868735969

我们只详细分析下这一个请求,看看,这个请求到底携带了什么样的数据

这个GET请求返回ptui_checkVC(’0′,’!TMX’,'\x00\x00\x00\x00\x0e\xe9\x41\xc1′);这样的字符串,其中第一个字符串,’0′代表不需要验证码,’!TMX’这个数据,是等会登陆需要的,第三个字符串加密密码的时候会用到。
附PHP代码如下:

<?php
/*** 获取验证码* * @access public* @param int $uid* @return array*/
function check_verify($uid)
{$ch = curl_init("https://ssl.ptlogin2.qq.com/check?uin={$uid}&appid=1003903&r=0.14233942252344134");$cookie = "confirmuin=0; ptvfsession=b1235b1729e7808d5530df1dcfda2edd94aabec43bf450d8cf037510802aa1a7dbed494c66577479895c62efa3ef35ab; ptisp=cnc";curl_setopt($ch, CURLOPT_COOKIE, $cookie);curl_setopt($ch, CURLOPT_COOKIEFILE, temp_dir."cookie");curl_setopt($ch, CURLOPT_COOKIEJAR, temp_dir."cookie");curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);$data = curl_exec($ch);if (preg_match("/ptui_checkVC\('(.*)','(.*)','(.*)'\);/", $data, $verify)){   return array_slice($verify, 1);}
}
/* WebQQ3.0 core part end of */

密码登陆后,监控到这样一个请求

http://ptlogin2.qq.com/login?u={$uid}&p={$passwd}&verifycode={$verify}&webqq_type=10&remember_uin=1&login2qq=1&aid=1003903&u1=http%3A%2F%2Fweb.qq.com%2Floginproxy.html%3Flogin2qq%3D1%26webqq_type%3D10&h=1&ptredirect=0&ptlang=2052&from_ui=1&pttype=1&dumy=&fp=loginerroralert&action=8-38-447467&mibao_css=m_webqq&t=3&g=1

其中有三个参数需要解释一下
u:QQ号
p:加密后的密码
verifycode:验证码
附PHP版登录函数以及加密函数代码如下:

<?php
/*** WEBQQ3.0 新版登陆加密函数* * @access public* @param string $p* @param string $pt* @param string $vc* @param boolean $md5* @return string*/
function jspassword($p,$pt,$vc,$md5 = true)
{if ($md5){$p = strtoupper(md5($p));}$len = strlen($p);$temp = null;for ($i=0; $i < $len ; $i = $i + 2){$temp .= '\x'.substr($p, $i,2);}return strtoupper(md5(strtoupper(md5(hex2asc($temp).hex2asc($pt))).$vc));
}/*** 十六进制转字符* * @access private* @param string $str* @return string*/
function hex2asc($str)
{$str = join('', explode('\x', $str));$len = strlen($str);$data = null;for ($i=0;$i<$len;$i+=2){$data .= chr(hexdec(substr($str,$i,2)));}return $data;
}/*** 登录* * @access public* @param int $uid* @param string $passwd* @param string $verify* @return array*/
function login($uid, $passwd, $verify)
{$url = "http://ptlogin2.qq.com/login?u={$uid}&p={$passwd}&verifycode={$verify}&webqq_type=10&remember_uin=1&login2qq=1&aid=1003903&u1=http%3A%2F%2Fweb.qq.com%2Floginproxy.html%3Flogin2qq%3D1%26webqq_type%3D10&h=1&ptredirect=0&ptlang=2052&from_ui=1&pttype=1&dumy=&fp=loginerroralert&action=8-38-447467&mibao_css=m_webqq&t=3&g=1";$ch = curl_init($url);curl_setopt($ch, CURLOPT_COOKIEFILE, temp_dir."cookie");curl_setopt($ch, CURLOPT_COOKIEJAR, temp_dir."cookie");curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);$data = curl_exec($ch);if (preg_match("/ptuiCB\('(.*)','(.*)','(.*)','(.*)','(.*)',\s'(.*)'\);/U", $data, $verify)){   return array_slice($verify, 1);}
}
/* WebQQ3.0 core part end of */

登录成功后返回值类似:
ptuiCB(’0′,’0′,’http://web.qq.com/loginproxy.html?login2qq=1&webqq_type=10′,’0′,’登录成功!’, ‘秋风’);
还有一组COOKIE,COOKIE值全都保存起来,待会儿会用到。
到这一步其实还没有真正的登录QQ的聊天接口,继续往下看。

第一次登录成功后,紧接着发送一个POST到http://d.web2.qq.com/channel/login2
POST值(请把参数值用urlencode函数编码)如下:
r={“status”:”online”,”ptwebqq”:”{$ptwebqq}”,”passwd_sig”:”",”clientid”:”{$clientid}”,”psessionid”:null}&clientid={$clientid}&psessionid=null
其中ptwebqq的值来自第一次登录时候的COOKIE值ptwebqq
clientid是个随机数,自己定义就行了
请求后的返回值是一个JSON格式的值,保存起来,后边收发信息时会用到:
到此为止,登陆就完成了。
附PHP版解析Cookie File函数以及登录函数代码如下:

<?php
/*** 解析cookie** @access public* @return array*/
function parse_cookie()
{// Netscape HTTP Cookie File$cookies = file(temp_dir."cookie");$data = array();foreach ($cookies as $v) {   if (preg_match("/(.*\.qq\.com)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\n/U", $v, $p)){   $data[] = array_slice($p, 1); }   }   return $data;
}/*** 获取cookie* * public * @param array $cookie* @return array*/
function get_cookie($cookie = NULL)
{if ($cookie === NULL){   $cookie = parse_cookie();}   if (is_array($cookie) && count($cookie)<=6){return FALSE;}foreach ($cookie as $v){$data[$v[5]] =$v[6];}return $data;
}/*** 真正的登录(上线)* * @access public* @param string $ptwebqq* @return string*/
function login2($ptwebqq,$clientid)
{$url = "http://d.web2.qq.com/channel/login2";$ch = curl_init($url);curl_setopt($ch, CURLOPT_POSTFIELDS, "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");// 必须要来路域名curl_setopt($ch, CURLOPT_REFERER, "http://d.web2.qq.com/proxy.html?v=20110331002&callback=1&id=2");
//  curl_setopt($ch, CURLOPT_HEADER, TRUE);curl_setopt($ch, CURLOPT_COOKIEFILE, temp_dir."cookie");curl_setopt($ch, CURLOPT_COOKIEJAR, temp_dir."cookie");curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);return curl_exec($ch);
}
/* WebQQ3.0 core part end of */

2.传说中的心跳包

顾名思义,心跳包,就是维持一个长连接,让WEBQQ保持在线的一种机制,.这个心跳包非常简单,只需要每隔几秒,或者写一个死循环发起请求就好(长时间不触发此步骤,会导致QQ掉线)
POST地址:http://d.web2.qq.com/channel/poll2
POST值(请把参数值用urlencode函数编码)如下:
r={“clientid”:”{$clientid}”,”psessionid”:”{$psessionid}”,”key”:0,”ids”:[]}&clientid={$clientid}&psessionid={$psessionid}
其中psessionid的值,在第二次登录返回的JSON信息里边能找到
clientid与第二次登录时候的clientid相同
附PHP版心跳请求函数代码如下:

<?php
/*** 心跳包(获取消息)* * @access public* @param string $psessionid* @param int $clientid* @return string*/
function poll($psessionid,$clientid)
{$post = "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}";$ch = curl_init("http://d.web2.qq.com/channel/poll2");// 必须要来路域名curl_setopt($ch, CURLOPT_REFERER, "http://d.web2.qq.com/proxy.html?v=20110331002&callback=1&id=3");curl_setopt($ch, CURLOPT_COOKIEFILE, temp_dir."cookie");curl_setopt($ch, CURLOPT_POSTFIELDS, $post);curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);return curl_exec($ch);
}
/* WebQQ3.0 core part end of */

3.获取QQ群列表

POST地址:http://s.web2.qq.com/api/get_group_name_list_mask2
POST值(请把参数值用urlencode函数编码)如下:
r={“vfwebqq”:”{$vfwebqq}”}
只有一个参数,很爽对吧?这个值在第二次登录的时候可得到,回头去找找看吧
附PHP版获取群列表函数代码如下:

<?php
/*** 获取群列表* * @access public* @param string $vfwebqq* @return string*/
function get_group_name_list_mask($vfwebqq)
{$post = "r=%7B%22vfwebqq%22%3A%22{$vfwebqq}%22%7D";$ch = curl_init("http://s.web2.qq.com/api/get_group_name_list_mask2");curl_setopt($ch, CURLOPT_REFERER, "http://d.web2.qq.com/proxy.html?v=20110331002&callback=1&id=3");curl_setopt($ch, CURLOPT_COOKIEFILE, temp_dir."cookie");curl_setopt($ch, CURLOPT_POSTFIELDS,$post);curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);return curl_exec($ch);
}
/* WebQQ3.0 core part end of */

4.获取好友列表

POST地址:http://s.web2.qq.com/api/get_user_friends2
POST值(请把参数值用urlencode函数编码)如下:
r={“h”:”hello”,”vfwebqq”:”{$vfwebqq}”}
vfwebqq的值在第二次登录的时候可得到,回头去找找看吧
(ps:在编辑本文时,发现这个请求链接的POST值已经加了一个参数hash,分析出来源后尽快补上,这对全局影响并不大)
附PHP版获取好友列表函数代码如下:

<?php
/*** 获取好友列表* * @access public* @param string $vfwebqq* @return string*/
function get_user_friend($vfwebqq)
{$post = "r=%7B%22h%22%3A%22hello%22%2C%22vfwebqq%22%3A%22{$vfwebqq}%22%7D";$ch = curl_init("http://s.web2.qq.com/api/get_user_friends2");curl_setopt($ch, CURLOPT_REFERER, "http://d.web2.qq.com/proxy.html?v=20110331002&callback=1&id=3");curl_setopt($ch, CURLOPT_COOKIEFILE, temp_dir."cookie");curl_setopt($ch, CURLOPT_POSTFIELDS,$post);curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);return curl_exec($ch);
}
/* WebQQ3.0 core part end of */

5.发送QQ消息

POST地址:http://d.web2.qq.com/channel/send_buddy_msg2
POST值(请把参数值用urlencode函数编码)如下:
r={“to”:{$from_uin},”face”:606,”content”:”[\"{$msg}\\n\",[\"font\",{\"name\":\"宋体\",\"size\":\"10\",\"style\":[0,0,0],\”color\”:\”000000\”}]]”,”msg_id”:{$msg_id},”clientid”:”{$clientid}”,”psessionid”:”{$psessionid}”}&clientid={$clientid}&psessionid={$psessionid}
部分参数解释:
to:好友的uin(非QQ号)
content:发送的消息内容
psessionid:在第二次登录返回的JSON信息里边能找到
clientid:与第二次登录时候的clientid相同
附PHP版发送QQ消息函数代码如下:

<?php
/*** 发送QQ消息* * @access public* @param int $from_uin* @param string $msg* @param string $psessionid* @param int $clientid* @return string*/
function send_buddy_msg($from_uin, $msg, $psessionid, $clientid)
{static $msg_id=71830055;$msg_id++;$post = "r=%7B%22to%22%3A{$from_uin}%2C%22face%22%3A606%2C%22content%22%3A%22%5B%5C%22{$msg}%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}";$ch = curl_init("http://d.web2.qq.com/channel/send_buddy_msg2");// 必须要来路域名curl_setopt($ch, CURLOPT_REFERER, "http://d.web2.qq.com/proxy.html?v=20110331002&callback=1&id=3");curl_setopt($ch, CURLOPT_COOKIEFILE, "cookie");curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
//  curl_setopt($ch, CURLOPT_HEADER, TRUE);curl_exec($ch);
}
/* WebQQ3.0 core part end of */

6.发送QQ群消息

POST地址:http://d.web2.qq.com/channel/send_qun_msg2
POST值(请把参数值用urlencode函数编码)如下:
r={“group_uin”:{$group_id},”content”:”[\"{$msg}\\n\",[\"font\",{\"name\":\"宋体\",\"size\":\"10\",\"style\":[0,0,0],\”color\”:\”000000\”}]]”,”msg_id”:{$msg_id},”clientid”:”{$clientid}”,”psessionid”:”{$psessionid}”}&clientid={$clientid}&psessionid={$psessionid}
部分参数解释:
group_uin:群的uin(非QQ群号)
content:发送的消息内容
psessionid:在第二次登录返回的JSON信息里边能找到
clientid:与第二次登录时候的clientid相同
附PHP版发送QQ群消息函数代码如下:

<?php
/*** 发送群消息* * @access public* @param int $group_id* @param string $msg* @param string $psessionid* @param int $clientid* @return string*/
function send_qun_msg($group_id, $msg, $psessionid, $clientid)
{static $msg_id = 77860003;$msg_id++;$post = "r=%7B%22group_uin%22%3A{$group_id}%2C%22content%22%3A%22%5B%5C%22{$msg}%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}";$ch = curl_init("http://d.web2.qq.com/channel/send_qun_msg2");curl_setopt($ch, CURLOPT_REFERER, "http://d.web2.qq.com/proxy.html?v=20110331002&callback=1&id=3");curl_setopt($ch, CURLOPT_COOKIEFILE, "cookie");curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
//  curl_setopt($ch, CURLOPT_HEADER, TRUE);curl_exec($ch);
}
/* WebQQ3.0 core part end of */

事实上,做到心跳包的时候,再往下已经没有技术含量了,已经属于体力活了,有兴趣的朋友可以研究研究。

转载于:https://www.cnblogs.com/jasonxiaoqinde/p/8022189.html

基于WebQQ3.0协议写一个QQ机器人相关推荐

  1. 教你用javascript写一个QQ机器人

    先放项目地址:https://github.com/sunft1996/qqRobot.js 目前的qq机器人基本上都依赖于smartqq协议,在PC上跑程序,那有没有简单一点的方法呢?正好在前段时间 ...

  2. iQQ 基于WebQQ3.0协议Java开发 跨平台QQ客户端

    iQQ 使用Java语言跨平台开发,基于腾讯WebQQ 3.0网络协议.可以使用于Java所支持的各种平台上运行.作者基于Linux(Ubuntu 12.04)系统,使用IDE NetBeans?开发 ...

  3. java iqq_iQQ 基于WebQQ3.0协议Java开发 跨平台QQ客户端

    iQQ 使用Java语言跨平台开发,基于腾讯WebQQ 3.0网络协议.可以使用于Java所支持的各种平台上运行.作者基于Linux(Ubuntu 12.04)系统,使用IDE NetBeans?开发 ...

  4. python开发酷q插件_基于python和酷Q的QQ机器人开发实践(1)

    基本框架 (1) 酷Q:目前最常用的QQ机器人软件(尤其是在smartQQ失效以后). (2) 酷Q HTTP插件:通过HTTP对酷Q的事件进行上报以及接收HTTP请求来调用酷Q的DLL接口,从而可以 ...

  5. python开发酷q插件gui_基于python和酷Q的QQ机器人开发实践(1)

    基本框架 (1) 酷Q:目前最常用的QQ机器人软件(尤其是在smartQQ失效以后). (2) 酷Q HTTP插件:通过HTTP对酷Q的事件进行上报以及接收HTTP请求来调用酷Q的DLL接口,从而可以 ...

  6. 互联网API开放平台安全设计-基于OAuth2.0协议方式

    基于OAuth2.0协议方式 什么是OAuth OAuth: OAuth(开放授权)是一个开放标准,允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方网站 ...

  7. 如何用Java写一个聊天机器人

    文章目录 建议结合新版教程看 写在前面的的话 免责声明 你需要提前会的东西 我们要使用的框架 首先我们先下载一个Demo 文件配置 Demo里面的的目录结构 在配置文件中加上你小号的QQ名字和密码 我 ...

  8. 详细介绍如何从0开始写一个数据通信,将数据从单片机发送到上位机(或者虚拟示波器)进行数据或图像显示,以及常见问题或注意事项解答,本文主要以匿名上位机为例,适合新手和小白

      本文主要内容:详细介绍如何从0开始写一个数据通信,将数据从单片机发送到上位机(或者虚拟示波器)进行数据或图像显示,帮助我们调节一些参数,比如电机PID的调节.波形融合等,以及在我们写通信协议的时候 ...

  9. c语言编写对答机器人_来,你也可以用 C 语言写一个聊天机器人

    来,你也可以用 C 语言写一个聊天机器人 你是不是一直在面对着枯燥的 C 语言特性.摸索着前人写过的各种算法,不是因为自己的兴趣,而是依靠自身的毅力,学得很苦吧. 好吧,我们找一个好玩一点的东西,一起 ...

最新文章

  1. 通过Auto Layout深入了解SizeClasses的好处和使用
  2. html ip输入框效果,html5 input文本框输入动画特效
  3. POJ 3186Treats for the Cows(区间DP)
  4. TensorFLow 常用错误总结
  5. 如何把nodejs应用和SAP云平台上的Redis实例做绑定
  6. Flink-Java版单词计数(批处理流处理)
  7. Linux的下载命令wget详解
  8. JAVA中實現鏈表 LinkedList的使用
  9. 4核处理器_买电脑选4核、6核还是8核,从业是十年的专家终于讲清楚了差异
  10. 【历史上的今天】8 月 18 日:硅谷神话惠普的衰落
  11. 【转】7个顶级心理预言
  12. 金融壹账通加马美国研究院“壹账通记忆增强网络”获对话系统学术竞赛佳绩...
  13. 此计算机怎样连接未识别的网络连接,电脑插入网线后显示“未识别网络”怎么办?...
  14. android头条的状态栏_今日头条如何设置电脑版 今日头条苹果手机任务栏在哪
  15. 股票交易接口的分类webService接口
  16. codewars day1
  17. 苹果白屏一直显示苹果_苹果6白屏如何解决,iPhone6白苹果开不了机怎么办
  18. B站下载姿势合集——亲测
  19. 安卓和苹果对于https域名下的引用http域的文件
  20. iOS如何转让 App 给公司或个人

热门文章

  1. Spring MVC小DEMO
  2. ZNYW.20180201_02_YunWeiJianXiu_ShouYe.svg
  3. windows 创建不可见账户
  4. UINavigationBar的系统渲染方式
  5. NOIP2013/day1/1/转圈游戏
  6. inside the C++ Object model总结
  7. linux 网络 PING IP可以通,ping域名ping不通
  8. 程序员的幽默--火车
  9. MySQL增量备份及恢复
  10. HBase的Row Key设计