qq聊天机器人 群发工具 (java版) (三)

本篇简单讲解一下如何接收QQ消息。

在成功登陆QQ后,要每隔一段时间发一个POST请求,用来维持登陆状态,同时也是用来接收消息的,请求如下:

Request URL:http://d.web2.qq.com/channel/poll2
Request Method:POST
Content-Type:application/x-www-form-urlencoded
Referer:http://d.web2.qq.com/proxy.html?v=20130916001&callback=1&id=2
Form-Data:r={"ptwebqq":"97b4ceaed7cc09c57e331db5785b7ee96253652a66f54ba1465176ac24b5d5dd","clientid":53999199,"psessionid":"8368046764001d636f6e6e7365727665725f77656271714031302e3133392e372e3136300000084800000c0c026e04003654298d6d0000000a403659485759383574506d00000028ac185599dd47fa9fbed98f818cf0219db1c21dc1b8d71c4309b1c1d60d1d5a6d99b14133835981f4","key":""}
post请求所带的数据参数前面都已经介绍过了,key默认为空就好。json字符串依旧要经过url编码。不过这个请求成功返回的时间不一定,不过最长也有一个时间限制。一般情况下若有消息发给你(或者刚登陆会收到离线消息),请求会立刻返回,但若一直没收到消息,腾讯服务器那边也会返回给你一个结果(一般是1分钟左右就返回)。所以,这个请求的延迟时间要设的长一点。下面附上我的代码:

// 获取QQ消息 收到消息就立刻再执行一次
public static String getQQMessage() throws Exception {
	// post 请求
	DefaultHttpClient client = new DefaultHttpClient();
	HttpPost postjson = new HttpPost("http://d.web2.qq.com/channel/poll2");

	postjson.setHeader("Referer",
			"http://d.web2.qq.com/proxy.html?v=20130916001&callback=1&id=2");

	HttpClientParams.setCookiePolicy(client.getParams(),
			CookiePolicy.BROWSER_COMPATIBILITY);

	client.getParams().setParameter(
			CoreConnectionPNames.CONNECTION_TIMEOUT, 1000 * 300);
	client.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT,
			1000 * 300);

	StringEntity entity = new StringEntity(poll2Str);
	entity.setContentType("application/x-www-form-urlencoded");
	postjson.setEntity(entity);

	// 设置CookieStore
	if (cs != null) {
		client.setCookieStore(cs);
	}

	// 获得返回的json数据包
	HttpResponse httpResponse = client.execute(postjson);
	HttpEntity httpent = httpResponse.getEntity();

	// 保存CookieStore
	cs = client.getCookieStore();

	String code = String.valueOf(httpResponse.getStatusLine()
			.getStatusCode());

	String line;
	StringBuffer sb = new StringBuffer();

	if (httpent != null) {
		BufferedReader br = new BufferedReader(new InputStreamReader(
				httpent.getContent(), "UTF-8"));
		while ((line = br.readLine()) != null) {
			sb.append(line);
		}
		br.close();
	}
	return sb.toString();
}
这边我是单独做了一个线程接收消息,在登陆成功后发送一次这个post请求,在得到返回值后再次post这个请求,如此来维持登陆状态,并一直获取消息(webqq就是这样实现的)。下面简单分析一下几种返回格式:

1.1分钟内无消息,则返回以下数据:

{"retcode":102,"errmsg":""}
这样的话直接再post下一个请求就好。

2.好友消息

{"retcode":0,"result":[{"poll_type":"message","value":{"msg_id":27785,"from_uin":2208444277,"to_uin":2368295990,"msg_id2":538127,"msg_type":9,"reply_ip":178854715,"time":1433158432,"content":[["font",{"size":10,"color":"000000","style":[0,0,0],"name":"\u5FAE\u8F6F\u96C5\u9ED1"}],"123 "]}}]}
poll_type为消息类型,message为好友消息,group_message为群消息,sess_message为临时会话。同样的,我没去分析讨论组的消息类型,有兴趣的可以自己试试。

value内即为消息的基本信息。msg_id和msg_id2不知道有什么区别,不管不知道也不影响大局。from_uin为发送好友相对于你的uin,和你获取好友时他的uin一样,to_uin即是你自己的标识(QQ号),msg_type是哪几种类型我也不清楚,我一般也无视了,reply_ip应该是发送人的ip地址,不过处理过了,我不知道该如何解密。time即发送的说剑戳,content内即是msg的主要信息,同发送消息一样,提取出消息文字即可。

注:如果发送了表情消息,内容中会带上表情的格式 如[face],或自定义表情[cface],这个时候提取消息的过程会变的比较复杂,所以我在接收到带有图片的消息时都直接无视了。

3.群消息

{"retcode":0,"result":[{"poll_type":"group_message","value":{"msg_id":18042,"from_uin":2381142083,"to_uin":2368295990,"msg_id2":793507,"msg_type":43,"reply_ip":180064295,"group_code":478233785,"send_uin":2208444277,"seq":3615,"time":1433158906,"info_seq":189429357,"content":[["font",{"size":10,"color":"000000","style":[0,0,0],"name":"\u5FAE\u8F6F\u96C5\u9ED1"}],"123 "]}}]}
如之前所说,poll_type为group_message,代表群消息,from_uin和上篇提到的gid一样即群标识,to_uin依旧是自己的标识,send_uin即发送人的uin,即群内成员相对于你的uin,和上篇介绍的获取群成员的uin一样。消息内容的格式同好友消息一致。

4.临时会话消息

{"retcode":0,"result":[{"poll_type":"sess_message","value":{"msg_id":2329,"from_uin":3921021009,"to_uin":2368295990,"msg_id2":62551,"msg_type":140,"reply_ip":180061935,"time":1433159288,"id":2381142083,"ruin":3277086849,"service_type":0,"flags":{"text":1,"pic":1,"file":1,"audio":1,"video":1},"content":[["font",{"size":9,"color":"000000","style":[0,0,0],"name":"\u5FAE\u8F6F\u96C5\u9ED1"}],"123 "]}}]}
from_uin为这个陌生人相对于你的标识,其他参数没什么区别了。


前几天我也仔细看过关于聊天机器人的实现方式。事实上真正的智能聊天机器人(能学习,会成长)实现难度太大了。现在的QQ聊天机器人一般都是设定关键字和回复内容,在消息内容中出现指定字段匹配上了即发送设定好的回复内容,这样的机器人实在是无趣,太僵硬了。不过,若是只做一个客服机器人,那么还是挺合适的。用以上方法接收消息,回复制定内容给客户即可,也不需要多高的智商,回答内容自己设定好即可。

今天又看了下各种免费的API,在百度API开放接口上看到了图灵机器人的API。相对我们自己设计而言算不错了,词库也比较强大(毕竟每个人教它的内容,都入了同一个库,而我们调用的也是同一个库)。不仅能进行简单的聊天,也提供了很多其他功能,所以如果觉得自己设计麻烦,可以把程序当成一个中转站,在接收到消息内容后,调用图灵机器人的API,再将返回的数据发送回对象即可。(不过图灵机器人API返回的格式并不是固定的,因为功能比较强大,会有很多种类型的返回结果,我也不太懂它的API,所以我不知道该如何去控制返回结果,结果处理起来比较麻烦)






郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。