一. 引言

我们都知道微信提供了多种登录的方式包括手机端、电脑端以及web端。

web端的登录我们用Python程序完全可以模拟出来~~如果你不知道那也没关系稍微了解下Python request session即可

而所谓的机器人实际上就是后台一个智能的程序类似“微软小冰”“iPhone siri”。今天我们要用的是一个开放的机器人API“图灵机器人”

下面就让我们一步步分析如何通过模拟web端微信登录+“图灵机器人” 实现一个微信机器人

二. 深入分析

1. web版微信不是用用户名密码而是用扫描二维码登录如何实现的呢

让我们登录https://wx.qq.com/查看此时的网络请求情况 如下图所示

1). 实际上客户端会先发送一个js get请求请求url为https://login.wx.qq.com/jslogin?appid=wx782c26e4c19acffb&redirect_uri=https%3A%2F%2Fwx.qq.com%2Fcgi-bin%2Fmmwebwx-bin%2Fwebwxnewloginpage&fun=new&lang=zh_CN&_=1469852355025

仔细分析这个请求会发现有已下几个参数

appid: wx782c26e4c19acffb //这个值不变表示来自微信网页版

redirect_uri: https%3A%2F%2Fwx.qq.com%2Fcgi-bin%2Fmmwebwx-bin%2Fwebwxnewloginpage //这个也是一个固定值

fun: new //固定值位new

lang: zh_CN //表示中文

_: 1469852355025 //13位时间戳

2).然后服务端返回数据window.QRLogin.code = 200; window.QRLogin.uuid = "IatVataLfQ==";

2. 多刷新几次你会发现服务端的返回值中window.QRLogin.uuid的值每次都在变化。

实际上uuid是服务端用来标识一次登录的通信id

2. 当我们拿到uuid后就需要获取二维码继续查看当前的网络请求

1). 客户端继续发送一个js get 请求url为https://login.weixin.qq.com/qrcode/IatVataLfQ==

仔细分析这个请求会发现qrcode后跟着的值就是从上一个请求拿到的uuid值

2). 当拿到二维码之后还需用微信客户端进行扫描god都有客户端了为什么还需用用web登录~~~~

3. ok拿出手机扫描屏幕的二维码继续查看网络请求

1).  当我们在APP上点击登录按钮之后实际上客户端是向服务端发送了一个js的get 请求url为https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login?loginicon=true&uuid=od5FW4ipFw==&tip=0&r=-979422099&_=1469857970642

仔细分析这个请求会发现有以下几个参数

uuid: od5FW4ipFw== //从上面请求得到的数据

tip: 0 //表示等待用户扫描确认

r: -979422099 //随机9位数字

_: 1469857970642 //13位时间戳

2). 这个请求返回结果如下所示

window.code=200;
window.redirect_uri="https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=AUyRV3zm5RBTWt-mEvvDz8oz@qrticket_0&uuid=od5FW4ipFw==&lang=zh_CN&scan=1469858238";

code=200表示的是成功redirect_uri表示需要我们继续请求的url

4. 继续上一个请求得到的redirect_uri

1). ok分析这个uri请求https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=AUyRV3zm5RBTWt-mEvvDz8oz@qrticket_0&uuid=od5FW4ipFw==&lang=zh_CN&scan=1469858238&fun=new&version=v2对应参数如下所示

uuid: 同前面

scan: 1469858238 //表示用户扫描的时间戳10位

其它参数保持不变即可

2). 这个请求会返回我们登陆所需要的信息返回值是一个xml数据如下所示

<error><ret>0</ret><message>OK</message><skey>@crypt_b13bcf4_edeadfd5xxxxd5e6b289b614fac25e5ac</skey><wxsid>HON+SKvxxxxTihHV</wxsid><wxuin>8xxxx5640</wxuin><pass_ticket>um3UATy9MNzcwDDkVT4xxxxMn5B25G%2FcYIAVbpHnF8vU23yMflmUCFsZkMKbIJIP</pass_ticket><isgrayscale>1</isgrayscale></error>

为了我的隐私我把返回值做了一定的打码~~

ret: 表示请求返回状态码0表示成功

skey和wxsid以及wxuin都是具体微信用户的信息不会变的在后续的通信过程中需要用到

pass_ticket: 这个值在初始化登录页面的时候需要用到

5. 现在我们已经拿到了用户认证相关的信息包括skey和wxsid以及wxuin需要初始化登录页面

什么是初始化登录页面也就是我们平时登录APP客户端看到的那个页面我们需要发送一个请求到服务端拿到数据获取到常用的联系人和微信公众号

如下图所示这个请求是一个post请求需要我们带一些用户认证相关的信息到服务端

1). ok让我们分析一下这个请求url: https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r=-979155549&pass_ticket=um3UATy9MNzcwDDkVT4xxxxMn5B25G%252FcYIAVbpHnF8vU23yMflmUCFsZkMKbIJIP

r: 随机的9位数据

pass_ticke: 从上一步请求返回值中获取的数据

2). post请求所需要的data如下所示

{
          'BaseResponse': {
              'Uin': wxuin,
              'Sid': wxsid,
              'Skey': skey,
              'DeviceID': //15位随机串 'e'+str(random.random())[2:17]
          }
        }

3). 请求返回数据如下所示

Ret: 0表示返回成功ContactList表示的是联系人列表。

返回数据包含了当前登录账户的相关信息比如wxuid昵称 ...

{
"BaseResponse": {
"Ret": 0,
"ErrMsg": ""
}
,
"Count": 10,
"ContactList": [{
"Uin": 0,
"UserName": "filehelper",
"NickName": "xxxx",
"HeadImgUrl": "/cgi-bin/mmwebwx-bin/webwxgeticon?seq=653892799&username=filehelper&skey=@crypt_b13bcf4_edeadfd5615d5e6b289b614fac25e5ac",
"ContactFlag": 1,
"MemberCount": 0,
"MemberList": [],
"RemarkName": "",
"HideInputBarFlag": 0,
"Sex": 0,
"Signature": "",
"VerifyFlag": 0,
"OwnerUin": 0,
"PYInitial": "WJCSZS",
"PYQuanPin": "wenjianchuanshuzhushou",
"RemarkPYInitial": "",
"RemarkPYQuanPin": "" ...

6. 登录成功接下来我们要做的就是开启消息状态通知。

ok继续看此时的网络请求会发现客户端向服务端发送了一个post请求

https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxstatusnotify?pass_ticket=um3UATy9MNzcwDDkVT42sVxMn5xxxx%252FcYIAVbpHnF8vU23yMflmUCFsZkMKbIJIP

1). 对于这个请求相信大家都不会感到陌生就只有一个参数pass_ticket同上

2). post请求需要的data模式如下

{
          'BaseResponse': {
              'Uin': wxuin,
              'Sid': wxsid,
              'Skey': skey,
              'DeviceID': //15位随机串 'e'+str(random.random())[2:17]
          }
          'ClientMsgId': 13位时间戳,
          'Code': 3  //固定值
          'FromUserName':  userNmae, //从初始化登录信息那边取到
          'ToUserName': userNmae, //从初始化登录信息那边取到
       }

3. 请求返回一个json数据

{
"BaseResponse": {
"Ret": 0,
"ErrMsg": ""
},
"MsgID": "4049260553244269433"
}

Ret:0表示的是请求返回成功状态

7. ok到目前为止我们以及成功登录了微信并且开启了消息通知

让我继续查看网页客户端会发现有非常多如下图所示的请求。从请求名称中我们知道这些请求在进行 同步刷新轮询检查服务端的消息

1). 分析下当前get请求https://webpush.wx.qq.com/cgi-bin/mmwebwx-bin/synccheck?r=1469858460705&skey=%40crypt_b13bcf4_edeadfdxxxxx5e6b289b614fac25e5ac&sid=HON%2BSKxxxxxxxxxV&uin=828xxxx40&deviceid=e477405243870570&synckey=1_653921573%7C2_653921810%7C3_653921702%7C11_653919729%7C13_653890051%7C201_1469858241%7C1000_1469856425%7C1001_1469851411&_=1469857970652

a. r --> 13位时间戳
       b. skey 同上,需要url quote
       c. sid 同上
       d. devicedid 同上
       e. synckey由 初始化登录页面信息返回串中Sync的list列表组成, 需要url quote
       f. _ 13位时间戳

2). 请求返回json数据如下所示window.synccheck={retcode:"0",selector:"0"}

retcode:
        a. 0 正常
        b. 1100 失败/登出微信
        c. 1101 从其它设备登录微信网页版
       selector:
        a. 0 正常
        b. 2 新的消息
        c. 7 手机操作了微信

8. ok万事具备只需要知道如何获取消息和发送消息即可了。

让我们先看一下当我们在网页上收到消息的时候不断轮询的同步刷新请求会返回window.synccheck={retcode:"0",selector:"2"} 或者是 window.synccheck={retcode:"0",selector:"6"}

1). 这个时候我们发现客户端会向服务端发送一个post请求拉取新的消息数据如下图所示

post请求: https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsync?sid=HONxxxxxqSwTihHV&skey=@crypt_b13bcf4_edeadfd5615d5xxxxx9b614fac25e5ac&pass_ticket=um3UATy9MNzcwDDkVTxxxxxMn5B25G%252FcYI

请求所带的参数同上

2). 请求会返回json数据包含具体的消息数据和类型

{
"BaseResponse": {
"Ret": 0,
"ErrMsg": ""
}
,
"AddMsgCount": 1,
"AddMsgList": [{
"MsgId": "4937824389423381364",
"FromUserName": "@ca2e7ef4exxxxxd71ab5fd68ac405b70",
"ToUserName": "@c26fa48f87634xxxxxx1ada0a4fa30f",
"MsgType": 1,
"Content": "[投é™]",
"Status": 3,
"ImgStatus": 1,
"CreateTime": 1469861910,
"VoiceLength": 0,
"PlayLength": 0,
"FileName": "",
"FileSize": "",
"MediaId": "",
"Url": "",
"AppMsgType": 0,
"StatusNotifyCode": 0,
"StatusNotifyUserName": "",
"RecommendInfo": {
"UserName": "",
"NickName": "",
"QQNum": 0,
"Province": "",
"City": "",
"Content": "",
"Signature": "",
"Alias": "",
"Scene": 0,
"VerifyFlag": 0,
"AttrStatus": 0,
"Sex": 0,
"Ticket": "",
"OpCode": 0
}
,
"ForwardFlag": 0,
"AppInfo": {
"AppID": "",
"Type": 0
}
,
"HasProductId": 0,
"Ticket": "",
"ImgHeight": 0,
"ImgWidth": 0,
"SubMsgType": 0,
"NewMsgId": 4937824389423381364
}
],
"ModContactCount": 0,
"ModContactList": [],
"DelContactCount": 0,
"DelContactList": [],
"ModChatRoomMemberCount": 0,
"ModChatRoomMemberList": [],
"Profile": {
"BitFlag": 0,
"UserName": {
"Buff": ""
}
,
"NickName": {
"Buff": ""
}
,
"BindUin": 0,
"BindEmail": {
"Buff": ""
}
,
"BindMobile": {
"Buff": ""
}
,
"Status": 0,
"Sex": 0,
"PersonalCard": 0,
"Alias": "",
"HeadImgUpdateFlag": 0,
"HeadImgUrl": "",
"Signature": ""
}
,
"ContinueFlag": 0,
"SyncKey": {
"Count": 8,
"List": [{
"Key": 1,
"Val": 653921573
}
,{
"Key": 2,
"Val": 653921823
}
,{
"Key": 3,
"Val": 653921702
}
,{
"Key": 11,
"Val": 653919729
}
,{
"Key": 13,
"Val": 653890051
}
,{
"Key": 201,
"Val": 1469861910
}
,{
"Key": 1000,
"Val": 1469856425
}
,{
"Key": 1001,
"Val": 1469851411
}
]
}
,
"SKey": ""
}

a. BaseResponseRet位0表示返回成功
       b. AddMsgCount 表示新消息个数
       c. AddMsgList 表示新消息列表
          MsgType   说明
          1     文本消息
          3     图片消息
          34    语音消息
          37    VERIFYMSG
          40    POSSIBLEFRIEND_MSG
          42    共享名片
          43    视频通话消息
          47    动画表情
          48    位置消息
          49    分享链接
          50    VOIPMSG
          51    微信初始化消息
          52    VOIPNOTIFY
          53    VOIPINVITE
          62    小视频
          9999  SYSNOTICE
          10000     系统消息
          10002     撤回消息

10.  最后让我们来看一下如何发送一个消息

1). 当我发送一个消息给好友的时候实际是执行了一次post请求如下图

url: https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg?pass_ticket=um3UATy9MNzcwDDkVT42sVxxxxxxxxG%252FcYIAVbpHnF8vU23yMflmUCFsZkMKbIJIP

2). post请求需要的data如下所示

{
          'BaseResponse': {
              'Uin': wxuin,
              'Sid': wxsid,
              'Skey': skey,
              'DeviceID': //15位随机串 'e'+str(random.random())[2:17]
          }
          'Type': //消息类型同上
          'Content': //消息内容
          'FromUserName':  //发送用户
          'ToUserName': //接受用户
          'LocalID':  //13位时间戳+4位随机数
          'ClientMsgId': //同LocalId
        }

3). 当发送成功之后服务端返回json数据

{
"BaseResponse": {
"Ret": 0,
"ErrMsg": ""
},
"MsgID": "2882629525509760458",
"LocalID": "14698626523310328"
}

Ret0表示发送成功

ok到此我们就知道了整个微信网页版从登陆到数据发送的整个过程。

现在我们只剩下最后一步机器人了。

我们要实现的是收到消息后自动根据消息进行回复。

这个我们只需要在收到消息的时候利用收到的消息调用“图灵机器人”API获取智能回答的数据然后发送给朋友即可。

图灵机器人http://www.tuling123.com/

  欢迎来拍砖github源码: https://github.com/chenguolin/weixin_robot

二. 效果分析

我申请了个图灵机器人取名为[【呆萌小白】

下面是简单的和机器人的对话无聊~~

手把手教你编写-微信机器人相关推荐

  1. 手把手教你编写 QQ 机器人

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 课程介绍 ...

  2. 手把手教你逆向微信之朋友圈小视频转发(下)

    接上篇<手把手教你逆向微信之朋友圈小视频转发(上)> 代码编写及重签名打包安装 (下篇) 小视频的转发支持4个功能,转发至朋友圈.转发至好友.保存到本地相册.拷贝小视频链接到粘贴板.如果小 ...

  3. skywalking原理_Skywalking系列博客6手把手教你编写 Skywalking 插件

    点击上方 IT牧场 ,选择 置顶或者星标技术干货每日送达! 前置知识 在正式进入编写环节之前,建议先花一点时间了解下javaagent(这是JDK 5引入的一个玩意儿,最好了解下其工作原理):另外,S ...

  4. 手把手教大家搭建微信公众号查题功能

    手把手教大家搭建微信公众号查题功能 本平台优点: 多题库查题.独立后台.响应速度快.全网平台可查.功能最全! 1.想要给自己的公众号获得查题接口,只需要两步! 2.题库: 题库:题库后台(点击跳转) ...

  5. 堆垛机器人编程技巧_两步变身老鸟,手把手教你提升ABB机器人编程技巧!(二)...

    原标题:两步变身老鸟,手把手教你提升ABB机器人编程技巧!(二) 1 双机器人与变位机编程 第一:如下图,双机器人+变位机系统,使用Multimove,(即一台控制器,一个示教器,三个运动任务) 第二 ...

  6. 实例:用C#.NET手把手教你做微信公众号开发(20)--使用微信支付线上收款:jsapi方式

    在做线上.线下销售时,可以使用微信便捷支付,通过微信公众号收款有很多种收款方式,如下图: 今天我们来讲一下jsapi支付,场景就是在微信内打开某个页面,完成在线支付,同样一个网页,使用微信打开就是js ...

  7. android 自动化 微信,C#手把手教你玩微信自动化

    原标题:C#手把手教你玩微信自动化 转自:初久的私房菜 cnblogs.com/MrChuJiu/p/13959383.html 介绍 本文主要讲的内容是 C# + Appium 自动化玩微信. Ap ...

  8. 不求人,手把手教你学会微信WIFI!

    前言:好吧,这是作者开博的第一篇文章,在如今朋友圈文章泛滥的时代,再看过了那么多"心灵鸡汤"."技术神贴"之后,作者也在思考,自己能不能写点什么,也许过上一百年 ...

  9. 实例:用C#.NET手把手教你做微信公众号开发(21)--使用微信支付线上收款:H5方式

    在做线上.线下销售时,可以使用微信便捷支付,通过微信公众号收款有很多种收款方式,如下图: 今天我们来讲一下H5场景支付,使用手机浏览器打开就是H5方式,最常见的推广是短信内置链接,这种场景需要调用微信 ...

  10. 写字机上位机c语言,易懂 | 手把手教你编写你的第一个上位机

    一.前言 大家好,我是ZhengN,本次来教大家编写一个基于QT的简单的上位机. 学习一个新的东西我们都从最基础地实例开始,比如学习C语言我们会从编写一个hello程序开始.学习嵌入式我们从点灯开始. ...

最新文章

  1. 【CSS】【13】文字的排版
  2. 无人机飞控开发平台培训理论课程——MSP430最小系统
  3. TSRC白帽子,10亿用户的守护者
  4. fold函数_Java中使用Map and Fold进行函数式编程
  5. 字节流转化为文件流_字节流转成字符串之后,在通过字符串转成字节流后的文件为什么会不一样?...
  6. 在后台获取前台按钮里的值(如LinkButton)
  7. 2017.3.25 最长递增子序列 失败总结
  8. oracle学习笔记(4)
  9. opengl 关于glGenBuffers函数没有定义
  10. 算术表达式:前缀表达式、中缀表达式、后缀表达式相互转换(手算法)
  11. 服务器与交换机的lacp协议,IEEE 802.3ad 链路聚合与 LACP 的简单知识 EtherChannel 总结...
  12. 我对数据分析的几点感悟
  13. 如何更快地渲染?深入了解3D渲染性能的指南!(6)
  14. redis的主从同步及高可用集群
  15. matlab从excel第二行写,matlab从某行读excel
  16. 荣大速印机维修手册_荣大/佳文一体印刷机常见电机故障提示含义解释及排除...
  17. LabVIEW编程LabVIEW开发Andor CCD例程与相关资料
  18. python保留字-Python保留字
  19. 程序员绝不要做“IT民工”
  20. 热力学第二定律的局限性与对热寂说的反驳

热门文章

  1. Atitit.wrmi web rmi框架新特性
  2. Atitit.attilax的 case list 项目经验 案例列表
  3. 十大旗舰基金是怎样炼成的(主动权益)
  4. 超融合架构与传统IT架构的区别
  5. 云原生高可用技术体系的构建思路与难点分析
  6. android 视频录制 sdk,android视频录制实现方法
  7. 【运动学】基于matlab Singer模型算法机动目标跟踪【含Matlab源码 1157期】
  8. 【财务预警】基于matlab BP神经网络财务预警【含Matlab源码 494期】
  9. 【语音处理】基于matlab GUI声音信号频谱分析仪【含Matlab源码 325期】
  10. nlp gpt论文_GPT-3是未来。 但是NLP目前可以做什么?