Web QQ协议分析(一):前言
项目地址
ScienJus/qqbot 基于 Smart QQ(Web QQ)的 QQ 机器人
欢迎 Star、Fork 和提交 Issue、Pull Request。
做这个项目的初衷
几个月前我写了一个 Pixiv 的爬图程序,当时有一个阿拉伯小哥用这个程序做了一个 Telegram 的搜图机器人放在他的 ACG 群中。但是由于外国人(除日本人)都习惯用罗马音,而 Pixiv 的联想功能又弱的一比,所以这个玩意最后的效果不尽人意。
看到自己的作品失败的感觉肯定不会很好,在此之后我一直在想如何能改善这个问题,当时想到了两种方法:
- 寻找或自己整理出一个包含中文、日文和罗马音的 ACG 数据库。
做一个中国人用的机器人给自己和周围小伙伴玩(因为中国人还是比较能接受用日文搜索的,不像外国人只认罗马音)
前者的资源很少,并且这些资源站的爬虫难度也很大,所以至今没有进展。而后者当时考虑了几个国内的社交平台,微博和微信公众号总觉得在未授权的情况下直接转载发布有些不礼貌(毕竟个人收藏和私下传播还勉强说得过去,直接发布到公共平台上就不太好了),所以也就 QQ 还值得尝试一下。
后来因为工作和其他原因暂时把这事抛到了脑后,直到前几天偶然在 GitHub 上看到了这样一个 轮子,看起来好像不麻烦,于是决定自己也写一个。
可能有人会问我为什么明明有现成的轮子了还要自己写一个,原因很简单:因为 Ruby 没有。我当时正在学习 Ruby,所以希望能写一些东西巩固一下(所以这个项目的源码质量很低…),并且 Ruby 写起来很爽,我很享受这个过程,最后是因为 Ruby 很适合这个轮子,使用者只需要安装这个 Gem,然后自定义一些逻辑,调用一下 API 就可以写出自己独一无二的 QQ 机器人了。
但是写到一半我才发现 Web QQ 在某个版本将收发图片的功能移除了,所以我这个 Pixiv 搜图机器人的初衷最后还是 GG 了。
对 Web QQ 协议的一些看法
- 整个鉴权模块 Cookie、Session、Token 全都用上了,真是折腾人
- 加密函数压缩混淆后放在 JS 还是会被找出来,不过只要偶尔换换也很折腾人
- 整个登录流程分了 5 步,偶尔加一步、减一步或者改一步同样折腾人(我在写这个项目的时候,正好登录流程就变了,当时还顺便给刚才提到的轮子的作者发了封邮件告诉他 这个地方 改了)
- 返回数据只提供了返回码而没有描述,因为什么失败了自己猜去吧
- 大部分请求都同时检查了 Cookie、Referer、User-Agent 和 Origin(只有 Post 请求有)
- 对一些不合理的情况进行了判断,比如登录后却没有发起接收消息的请求
对访问频率进行了控制,太频繁的请求也会被拒绝
综上所述,作为一个 Web 应用,想要不被开发者抓包并模拟请求是很难的。你唯一能做的就是去尽量的恶心他们。并且利用 Web 项目迭代方便的特性,频繁的进行鉴权等模块的修改,淘汰掉那些开发者没有足够精力维护的项目。
写本文的目的
接下来我将介绍一下当前(2015年12月)版本的 Web QQ 协议,数据来源基本上都是通过 Chrome 控制台对 Smart QQ 进行抓包得到的,如果你也想自己实现一个这样的轮子,这些资料可以避免你走很多弯路。
不过在此之前先说一些公共约定:
- 保证请求头中包含正常的
User-Agent
、Referer
、Cookie
等信息,如果是Post
请求需要额外加上Origin
- 在大部分情况下(除了获取二维码和确认二维码状态),返回内容均为 JSON,其中
retcode
为请求结果(0
为成功),response
为返回数据 - 不过还有个特例是发送消息的接口,成功时返回的字段是
errCode
,失败时才是retcode
- 请求失败后,返回的错误码如果是
1000000
或1000001
,几乎可以认为是缺少了第一条中的某个数据 - 如果请求参数中有
t
,当前版本不会检验它的值,所以我统一设为0.1
,但是实际上它的值一般情况下均为当前时间的unix timestamp
如果返回的返回的错误码为
1000003
,很有可能是你的请求频率过于频繁了解了以上信息后,便可以开始愉快地写接口了