基于python实现机器人
当时的我刚刚接触Python,急需要一个既不是太复杂,也不太难理解的项目练手,然后一个偶然的机会,在github上找到了类似的项目,所有就想着自己试试看,毕竟有比较成熟的项目作为参考,遇到问题也不会太卡项目进度,然而并没有那么顺利,貌似写代码都这样,一次次的修改最后成型,所以这是一个初学者的实践项目,所以不对的地方尽可以指出,所以不喜勿喷!
1.特别提醒
- 在所有需要发送json的地方,请注意使用『json.dumps()』将字典转换成Json字符串,不然接口会返回空
-
看源代码的朋友可能会发现,我对于
r
参数的理解更多的是随机整数,网上将r
和_
都做时间戳处理,但是13位时间戳还真不多见,可能是我见识短吧 -
对于等待扫描接口中的
_
参数,我的理解是首次是用的时间戳,后面的请求是依次加一,并不是每次的时间戳
2.执行流程
- 打开首页,分配一个随机uuid,
- 根据该uuid获取二维码图片。
- 微信客户端扫描该图片,在客户端确认登录。
- 浏览器不停的调用一个接口,如果返回登录成功,则调用登录接口
- 此时可以获取联系人列表,可以发送消息。然后不断调用同步接口。
- 如果同步接口有返回,则可以获取新消息,然后继续调用同步接口。
sh
+--------------+ +---------------+ +---------------+
| | | | | |
| Get UUID | | Get Contact | | Status Notify |
| | | | | |
+-------+------+ +-------^-------+ +-------^-------+
| | |
| +-------+ +--------+
| | |
+-------v------+ +-----+--+------+ +--------------+
| | | | | |
| Get QRCode | | Weixin Init +------> Sync Check <----+
| | | | | | |
+-------+------+ +-------^-------+ +-------+------+ |
| | | |
| | +-----------+
| | |
+-------v------+ +-------+--------+ +-------v-------+
| | Confirm Login | | | |
+------> Login +---------------> New Login Page | | Weixin Sync |
| | | | | | |
| +------+-------+ +----------------+ +---------------+
| |
|QRCode Scaned|
+-------------+
3.WebWechat API
3.1获取UUID(参考方法 getUUID)
API | 获取 UUID |
---|---|
url | https://login.weixin.qq.com/jslogin |
method | POST |
data | URL Encode |
params |
appid
:
应用ID
fun : new
应用类型
lang : zh_CN
语言
_ :
时间戳
|
返回数据(String):
window.QRLogin.code = 200; window.QRLogin.uuid = "xxx"
注:这里的appid就是在微信开放平台注册的应用的AppID。网页版微信有两个AppID,早期的是
wx782c26e4c19acffb
,在微信客户端上显示为应用名称为Web微信
;现在用的是wxeb7ec651dd0aefa9
,显示名称为微信网页版
。
3.2显示二维码(参考方法 showQrCode)
API | 显示二维码 |
---|---|
url | https://login.weixin.qq.com/qrcode/{uuid} |
method | POST |
params |
t
: webwx
_ : 时间戳 |
|
|
注:
在代码中我们的二维码内容并不是
https://login.weixin.qq.com/qrcode/{uuid}
而是
https://login.weixin.qq.com/l/{uuid}
|
3.3等待登录(参考方法 waitForLogin)这里是微信确认登录
API | 二维码扫描登录 |
---|---|
url | https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login |
method | GET |
params |
tip
:网上解释=》【1:未扫描 0:已扫描】据我观察=》第一次tip为1,后面不管有没有扫描都变为0
uuid : 获取到的uuid _ : 时间戳(13位整型) |
返回数据(String): ``` window.code=xxx;
xxx: 408 登陆超时 201 扫描成功 200 确认登录
当返回200时,还会有 window.redirect_uri="https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=xxx&uuid=xxx&lang=xxx&scan=xxx"; ```
3.4登录获取Cookie(参考方法 login)
API | webwxnewloginpage |
---|---|
url | https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage |
method | GET |
params |
ticket
: xxx
uuid : xxx lang : zh_CN scan : xxx fun : new |
返回数据(XML):
xml
<error>
<ret>0</ret>
<message>OK</message>
<skey>xxx</skey>
<wxsid>xxx</wxsid>
<wxuin>xxx</wxuin>
<pass_ticket>xxx</pass_ticket>
<isgrayscale>1</isgrayscale>
</error>
核心数据点:
在这一步获取xml中的
skey
,
wxsid
,
wxuin
,
pass_ticket
3.5微信初始化
API | webwxinit |
---|---|
url | https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit?pass_ticket=xxx&skey=xxx&r=xxx |
method | POST |
data | JSON |
header | Content-Type: application/json; charset=UTF-8 |
params |
{
BaseRequest: { Uin: xxx, Sid: xxx, Skey: xxx, DeviceID: xxx, } } |
返回数据(JSON):
json
{
"BaseResponse": {
"Ret": 0,
"ErrMsg": ""
},
"Count": 11,
"ContactList": [...],
"SyncKey": {
"Count": 4,
"List": [
{
"Key": 1,
"Val": 635705559
},
...
]
},
"User": {
"Uin": xxx,
"UserName": xxx,
"NickName": xxx,
"HeadImgUrl": xxx,
"RemarkName": "",
"PYInitial": "",
"PYQuanPin": "",
"RemarkPYInitial": "",
"RemarkPYQuanPin": "",
"HideInputBarFlag": 0,
"StarFriend": 0,
"Sex": 1,
"Signature": "Apt-get install B",
"AppAccountFlag": 0,
"VerifyFlag": 0,
"ContactFlag": 0,
"WebWxPluginSwitch": 0,
"HeadImgFlag": 1,
"SnsFlag": 17
},
"ChatSet": xxx,
"SKey": xxx,
"ClientVersion": 369297683,
"SystemTime": 1453124908,
"GrayScale": 1,
"InviteStartCount": 40,
"MPSubscribeMsgCount": 2,
"MPSubscribeMsgList": [...],
"ClickReportInterval": 600000
}
这一步中获取
SyncKey
,
User
后面的消息监听用。
3.6开启微信状态通知(参考方法 wxStatusNotify)
API | webwxstatusnotify |
---|---|
url | https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxstatusnotify?lang=zh_CN&pass_ticket=xxx |
method | POST |
data | JSON |
header | ContentType: application/json; charset=UTF-8 |
params |
{
BaseRequest: { Uin: xxx, Sid: xxx, Skey: xxx, DeviceID: xxx }, Code: 3, FromUserName:
自己ID
,
ToUserName:
自己ID
,
ClientMsgId:
时间戳
} |
返回数据(JSON):
{
"BaseResponse": {
"Ret": 0,
"ErrMsg": ""
},
...
}
3.7获取联系人列表(参考方法 getContact)
API | webwxgetcontact |
---|---|
url | https://wx.qq.com/cgi-bin/mmwebwx-bin//webwxgetcontact?pass_ticket=xxx&skey=xxx&r=xxx |
method | POST |
data | JSON |
header | ContentType: application/json; charset=UTF-8 |
注:
个人认为这个在做自动回复的机器人的时候没有获取的必要
返回数据(JSON):
json
{
"BaseResponse": {
"Ret": 0,
"ErrMsg": ""
},
"MemberCount": 334,
"MemberList": [
{
"Uin": 0,
"UserName": xxx,
"NickName": "Urinx",
"HeadImgUrl": xxx,
"ContactFlag": 3,
"MemberCount": 0,
"MemberList": [],
"RemarkName": "",
"HideInputBarFlag": 0,
"Sex": 0,
"Signature": "我是二蛋",
"VerifyFlag": 8,
"OwnerUin": 0,
"PYInitial": "URINX",
"PYQuanPin": "Urinx",
"RemarkPYInitial": "",
"RemarkPYQuanPin": "",
"StarFriend": 0,
"AppAccountFlag": 0,
"Statues": 0,
"AttrStatus": 0,
"Province": "",
"City": "",
"Alias": "Urinxs",
"SnsFlag": 0,
"UniFriend": 0,
"DisplayName": "",
"ChatRoomId": 0,
"KeyWord": "gh_",
"EncryChatRoomId": ""
},
...
],
"Seq": 0
}
3.8消息检查(参考方法 syncCheck)
API | synccheck |
---|---|
url | https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxbatchgetcontact?type=ex&r=xxx&pass_ticket=xxx |
method | POST |
data | JSON |
header | ContentType: application/json; charset=UTF-8 |
params |
{
BaseRequest: { Uin: xxx, Sid: xxx, Skey: xxx, DeviceID: xxx }, Count:
群数量
,
List: [ { UserName:
群ID
, EncryChatRoomId: "" },
... ], } |
返回数据(String): ``` window.synccheck={retcode:"xxx",selector:"xxx"}
retcode: 0 正常 1100 失败/登出微信 1101 在其他地方登录了微信 selector: 0 正常 2 新的消息 7 进入/离开聊天界面 ```
3.9获取最新消息(参考方法 webwxsync)
API | webwxsync |
---|---|
url | https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsync?sid=xxx&skey=xxx&pass_ticket=xxx |
method | POST |
data | JSON |
header | ContentType: application/json; charset=UTF-8 |
params |
{
BaseRequest: { Uin: xxx, Sid: xxx, Skey: xxx, DeviceID: xxx }, SyncKey: xxx, rr:
时间戳取反
} |
返回数据(JSON):
{
'BaseResponse': {'ErrMsg': '', 'Ret': 0},
'SyncKey': {
'Count': 7,
'List': [
{'Val': 636214192, 'Key': 1},
...
]
},
'ContinueFlag': 0,
'AddMsgCount': 1,
'AddMsgList': [
{
'FromUserName': '',
'PlayLength': 0,
'RecommendInfo': {...},
'Content': "",
'StatusNotifyUserName': '',
'StatusNotifyCode': 5,
'Status': 3,
'VoiceLength': 0,
'ToUserName': '',
'ForwardFlag': 0,
'AppMsgType': 0,
'AppInfo': {'Type': 0, 'AppID': ''},
'Url': '',
'ImgStatus': 1,
'MsgType': 51,
'ImgHeight': 0,
'MediaId': '',
'FileName': '',
'FileSize': '',
...
},
...
],
'ModChatRoomMemberCount': 0,
'ModContactList': [],
'DelContactList': [],
'ModChatRoomMemberList': [],
'DelContactCount': 0,
...
}
3.10消息接口
API | webwxsendmsg |
---|---|
url | https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg?pass_ticket=xxx |
method | POST |
data | JSON |
header | ContentType: application/json; charset=UTF-8 |
params |
{
BaseRequest: { Uin: xxx, Sid: xxx, Skey: xxx, DeviceID: xxx }, Msg: { Type: 1
文字消息
,
Content:
要发送的消息
,
FromUserName:
自己ID
,
ToUserName:
好友ID
,
LocalID:
与clientMsgId相同
,
ClientMsgId:
时间戳左移4位随后补上4位随机数
} } |
返回数据(JSON):
{
"BaseResponse": {
"Ret": 0,
"ErrMsg": ""
},
...
}
3.11发送表情
API | webwxsendmsgemotion |
---|---|
url | https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxsendemoticon?fun=sys&f=json&pass_ticket=xxx |
method | POST |
data | JSON |
header | ContentType: application/json; charset=UTF-8 |
params |
{
BaseRequest: { Uin: xxx, Sid: xxx, Skey: xxx, DeviceID: xxx }, Msg: { Type: 47
emoji消息
,
EmojiFlag: 2, MediaId:
表情上传后的媒体ID
,
FromUserName:
自己ID
,
ToUserName:
好友ID
,
LocalID:
与clientMsgId相同
,
ClientMsgId:
时间戳左移4位随后补上4位随机数
} } |
3.12图片接口
API | webwxgeticon |
---|---|
url | https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgeticon |
method | GET |
params |
seq
:
数字,可为空
username :
ID
skey : xxx |
|
API | webwxgetheadimg |
---|---|
url | https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetheadimg |
method | GET |
params |
seq
:
数字,可为空
username :
群ID
skey : xxx |
|
API | webwxgetmsgimg |
---|---|
url | https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetmsgimg |
method | GET |
params |
MsgID
:
消息ID
type : slave
略缩图
or
为空时加载原图
skey : xxx |
|
3.13多媒体接口
API | webwxgetvideo |
---|---|
url | https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetvideo |
method | GET |
params |
msgid
:
消息ID
skey : xxx |
|
API | webwxgetvoice |
---|---|
url | https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetvoice |
method | GET |
params |
msgid
:
消息ID
skey : xxx |
|
3.14账号类型
类型 | 说明 |
---|---|
个人账号 |
以
@
开头,例如:
@xxx
|
群聊 |
以
@@
开头,例如:
@@xxx
|
公众号/服务号 |
以
@
开头,但其
VerifyFlag
& 8 != 0
VerifyFlag
:
一般公众号/服务号:8 微信自家的服务号:24 微信官方账号
微信团队
:56
|
特殊账号 |
像文件传输助手之类的账号,有特殊的ID,目前已知的有:
filehelper
,
newsapp
,
fmessage
,
weibo
,
qqmail
,
fmessage
,
tmessage
,
qmessage
,
qqsync
,
floatbottle
,
lbsapp
,
shakeapp
,
medianote
,
qqfriend
,
readerapp
,
blogapp
,
facebookapp
,
masssendapp
,
meishiapp
,
feedsapp
,
voip
,
blogappweixin
,
weixin
,
brandsessionholder
,
weixinreminder
,
officialaccounts
,
notification_messages
,
wxitil
,
userexperience_alarm
,
notification_messages
|
|
3.15消息类型
消息一般格式:
json
{
"FromUserName": "",
"ToUserName": "",
"Content": "",
"StatusNotifyUserName": "",
"ImgWidth": 0,
"PlayLength": 0,
"RecommendInfo": {...},
"StatusNotifyCode": 4,
"NewMsgId": "",
"Status": 3,
"VoiceLength": 0,
"ForwardFlag": 0,
"AppMsgType": 0,
"Ticket": "",
"AppInfo": {...},
"Url": "",
"ImgStatus": 1,
"MsgType": 1,
"ImgHeight": 0,
"MediaId": "",
"MsgId": "",
"FileName": "",
"HasProductId": 0,
"FileSize": "",
"CreateTime": 1454602196,
"SubMsgType": 0
}
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 | 撤回消息 |
|
微信初始化消息
html
MsgType: 51
FromUserName: 自己ID
ToUserName: 自己ID
StatusNotifyUserName: 最近联系的联系人ID
Content:
<msg>
<op id='4'>
<username>
// 最近联系的联系人
filehelper,xxx@chatroom,wxid_xxx,xxx,...
</username>
<unreadchatlist>
<chat>
<username>
// 朋友圈
MomentsUnreadMsgStatus
</username>
<lastreadtime>
1454502365
</lastreadtime>
</chat>
</unreadchatlist>
<unreadfunctionlist>
// 未读的功能账号消息,群发助手,漂流瓶等
</unreadfunctionlist>
</op>
</msg>
文本消息
MsgType: 1
FromUserName: 发送方ID
ToUserName: 接收方ID
Content: 消息内容
图片消息
html
MsgType: 3
FromUserName: 发送方ID
ToUserName: 接收方ID
MsgId: 用于获取图片
Content:
<msg>
<img length="6503" hdlength="0" />
<commenturl></commenturl>
</msg>
小视频消息
html
MsgType: 62
FromUserName: 发送方ID
ToUserName: 接收方ID
MsgId: 用于获取小视频
Content:
<msg>
<img length="6503" hdlength="0" />
<commenturl></commenturl>
</msg>
地理位置消息
MsgType: 1
FromUserName: 发送方ID
ToUserName: 接收方ID
Content: http://weixin.qq.com/cgi-bin/redirectforward?args=xxx
// 属于文本消息,只不过内容是一个跳转到地图的链接
名片消息
```js
MsgType: 42
FromUserName: 发送方ID
ToUserName: 接收方ID
Content:
<?xml version="1.0"?>
RecommendInfo: { "UserName": "xxx", // ID "Province": "xxx", "City": "xxx", "Scene": 17, "QQNum": 0, "Content": "", "Alias": "xxx", // 微信号 "OpCode": 0, "Signature": "", "Ticket": "", "Sex": 0, // 1:男, 2:女 "NickName": "xxx", // 昵称 "AttrStatus": 4293221, "VerifyFlag": 0 } ```
语音消息
html
MsgType: 34
FromUserName: 发送方ID
ToUserName: 接收方ID
MsgId: 用于获取语音
Content:
<msg>
<voicemsg endflag="1" cancelflag="0" forwardflag="0" voiceformat="4" voicelength="1580" length="2026" bufid="216825389722501519" clientmsgid="49efec63a9774a65a932a4e5fcd4e923filehelper174_1454602489" fromusername="" />
</msg>
动画表情
html
MsgType: 47
FromUserName: 发送方ID
ToUserName: 接收方ID
Content:
<msg>
<emoji fromusername = "" tousername = "" type="2" idbuffer="media:0_0" md5="e68363487d8f0519c4e1047de403b2e7" len = "86235" productid="com.tencent.xin.emoticon.bilibili" androidmd5="e68363487d8f0519c4e1047de403b2e7" androidlen="86235" s60v3md5 = "e68363487d8f0519c4e1047de403b2e7" s60v3len="86235" s60v5md5 = "e68363487d8f0519c4e1047de403b2e7" s60v5len="86235" cdnurl = "http://emoji.qpic.cn/wx_emoji/eFygWtxcoMF8M0oCCsksMA0gplXAFQNpiaqsmOicbXl1OC4Tyx18SGsQ/" designerid = "" thumburl = "http://mmbiz.qpic.cn/mmemoticon/dx4Y70y9XctRJf6tKsy7FwWosxd4DAtItSfhKS0Czr56A70p8U5O8g/0" encrypturl = "http://emoji.qpic.cn/wx_emoji/UyYVK8GMlq5VnJ56a4GkKHAiaC266Y0me0KtW6JN2FAZcXiaFKccRevA/" aeskey= "a911cc2ec96ddb781b5ca85d24143642" ></emoji>
<gameext type="0" content="0" ></gameext>
</msg>
普通链接或应用分享消息
html
MsgType: 49
AppMsgType: 5
FromUserName: 发送方ID
ToUserName: 接收方ID
Url: 链接地址
FileName: 链接标题
Content:
<msg>
<appmsg appid="" sdkver="0">
<title></title>
<des></des>
<type>5</type>
<content></content>
<url></url>
<thumburl></thumburl>
...
</appmsg>
<appinfo>
<version></version>
<appname></appname>
</appinfo>
</msg>
音乐链接消息 ```html MsgType: 49 AppMsgType: 3 FromUserName: 发送方ID ToUserName: 接收方ID Url: 链接地址 FileName: 音乐名
AppInfo: // 分享链接的应用 { Type: 0, AppID: wx485a97c844086dc9 }
Content:
群消息
MsgType: 1
FromUserName: @@xxx
ToUserName: @xxx
Content:
@xxx:<br/>xxx
红包消息
MsgType: 49
AppMsgType: 2001
FromUserName: 发送方ID
ToUserName: 接收方ID
Content: 未知
注:根据网页版的代码可以看到未来可能支持查看红包消息,但目前走的是系统消息,见下。
系统消息
MsgType: 10000
FromUserName: 发送方ID
ToUserName: 自己ID
Content:
"你已添加了 xxx ,现在可以开始聊天了。"
"如果陌生人主动添加你为朋友,请谨慎核实对方身份。"
"收到红包,请在手机上查看"
参考文献
- 基于微信客户端的健康管理系统的设计与实现(山东大学·郑运良)
- 基于ROS的云机器人微服务架构软件平台的设计与实现(浙江理工大学·徐彬怀)
- 基于爬虫的小企业搜索系统的设计与实现(大连理工大学·范能科)
- 基于树莓派的牛舍巡检机器人系统的研究与设计(北方民族大学·张策)
- 基于微信客户端的健康管理系统的设计与实现(山东大学·郑运良)
- 基于特定场景的智能问答系统的设计与实现(北京交通大学·李梦莎)
- 基于微信客户端的健康管理系统的设计与实现(山东大学·郑运良)
- 基于微服务架构的通用爬虫系统的设计与实现(北京交通大学·杨红光)
- 基于SSH架构的个人空间交友网站的设计与实现(北京邮电大学·隋昕航)
- 基于微信公众平台的商城系统的设计与实现(西安电子科技大学·齐艳丽)
- 基于微信客户端的健康管理系统的设计与实现(山东大学·郑运良)
- 基于微服务的聊天机器人设计与实现(华中科技大学·尹荣杰)
- 基于MQTT协议和ROS的机器人任务规模化分发与部署(国防科技大学·魏菁)
- 基于Python Web的运动社交微信小程序(大连理工大学·赵兴东)
- 基于知识图谱的聊天机器人的设计与实现(哈尔滨工业大学·丁浩天)
本文内容包括但不限于文字、数据、图表及超链接等)均来源于该信息及资料的相关主题。发布者:源码工厂 ,原文地址:https://bishedaima.com/yuanma/35650.html