打造微信聊天机器人1

摘要:利用微信公众号开发一个聊天机器人。

前置条件

  • Linux基础
  • 一点儿CGI和Python基础
  • 一台运行Linux系统的云主机或VPS虚拟主机
  • 最好有个域名

原理

聊天机器人原理图

上图给出了聊天机器人的基本原理。用户A在微信客户端中给公众号发送一条消息,这条消息会通过微信服务器,转发到公众号指定的服务器上,也就是图中的“聊天机器人服务器”,聊天机器人服务器收到消息之后,经过“思考”,给出一个回复到微信服务器,然后微信服务器就会把这个回复发送到用户A的客户端,一次“对话”就完成了。整个过程中的大部分工作,都已经由微信包办了,我们要做的,只是红框中的聊天机器人服务器,让它按照微信指定的协议,接收消息和发送回复,就是这么简单!

微信服务器和聊天机器人之间通过HTTP通信,所以我们的聊天机器人服务器,实际上就是一个符合微信标准的CGI,基本上你可以用任何语言进行开发。本文将使用Python和Bottle框架进行开发。

申请微信公众号

微信公众平台注册一个帐号,注意这里使用的邮箱不能跟微信其他服务所绑定的邮箱相同,包括个人微信号、微信开放平台、微信小程序等等。幸好只是换邮箱注册,不是换手机注册。注册之后请按照官方的指引填写相关信息。公众平台提供了编辑和发布图文消息的功能,但是要实现一个聊天机器人,必须使用开发者模式。在"开发" -> "接口权限"下,可以查看当前公众号能够使用的接口,目前个人用户只能申请订阅号,并且不能进行认证,因此权限最低,能使用的接口有限。不过接收消息和自动回复的权限还是有的,并且没有调用次数的限制,这就足够了。

进入"开发" -> "基本配置" -> "服务器配置",修改服务器配置,这里的关键选项是URL和Token。URL就是原理图中,微信服务器和你的聊天机器人服务器之间通信的接口。Token让你的聊天机器人可以验证消息的来源,防止微信服务器之外的恶意调用。微信服务器发送的每条消息,都会带上一个使用Token加密的签名,我们只要使用相同的Token和算法,就能验证收到的消息是否来自微信服务器。关于签名的方法,微信官方的接入指南里有更详细的描述,以及对应的PHP实现。"消息加解密方式"选择"明文模式",EncodingAESKey直接点"随机生成",这样省去了消息加解密的麻烦。

此时直接点击“提交”是不能成功的,因为微信公众平台会立刻发送一个验证消息,检验URL是否可用。我们必须先让自己的服务器跑起来,才能通过验证。

一个最小的公众号服务器

这里我们使用Bottle这个小巧而美丽的Web框架来编写一个能通过验证的最简单的服务器。在你的云主机或者VPS上创建robot.py文件,内容如下:

from bottle import request, route, run
from hashlib import sha1

TOKEN = '这里填写你的Token'

def valid():
    l = [TOKEN, request.query.timestamp, request.query.nonce]
    l.sort()
    h = sha1()
    h.update("".join(l))
    if request.query.signature == h.hexdigest():
        return True
    return False

@route('/wx/chatbot')
def check():
    if valid():
        return request.query.echostr
    return "failed"

run(host='0.0.0.0', port=80)

这段端程序的含义是,服务器收到一个访问/wx/chatbot的GET请求时,按照微信指定的算法计算签名,跟请求中的signature参数进行对比,如果二者相符,就把请求中的echostr原样返回。事实上,这个服务器还不是最简单的。因为微信服务器只要收到了echostr,就会认为验证成功,因此我们完全可以跳过签名验证的过程,直接返回echostr。

运行这段程序必须要bottle模块,可以直接从这里下载压缩包,解压出里面的bottle.py放在你程序的目录下。不过更推荐的方法是使用pip,安装方法见这里

pip install bottle

现在让我们的服务器运行起来,然后回到微信公众平台的配置页面,在URL里填写“http://你的域名或ip/wx/chatbot”, 点击“提交”完成配置,再点击“启用”让我们的配置生效。

python robot.py

A Dumb Robot

到这里,我们已经有了一个可以接收微信消息的服务器了。微信发过来的消息是下面这个样子:

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1348831860</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[this is a test]]></Content>
<MsgId>1234567890123456</MsgId>
</xml>

这是一个XML文件,我们只关注3个字段:ToUserName、FromUserName和Content,分别表示消息的接收者(这里是我们的公众号ID,可以在公众平台的"设置" -> "公众号设置" -> "原始ID"中看到),发送者和内容。要回复消息给用户,也要返回一个指定格式的XML给微信服务器:

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>12345678</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[你好]]></Content>
</xml>

知道了往返消息的格式(详细信息参见微信的开发文档),我们就可以开始“对话”了。在代码中添加下面内容:

from time import time

@route('/wx/chatbot', method='POST')
def chat():
    if not valid():
        return "invalid msg"
    return """
    <xml>
    <ToUserName><![CDATA[toUser]]></ToUserName>
    <FromUserName><![CDATA[fromUser]]></FromUserName>
    <CreateTime>12345678</CreateTime>
    <MsgType><![CDATA[text]]></MsgType>
    <Content><![CDATA[Hello]]></Content>
    </xml>
    """ % int(time()) 

chat()函数将接收来自微信服务器的POST请求,然后返回一个固定的回复。要让发消息的用户能够收到回复,还需要正确的填写回复中的toUser和fromUser。由于是回复消息,toUser和fromUser跟用户发送给公众号的消息正好是反过来的,我们可以用print语句把收到的消息打印出来,找到对应的字段填在回复里,这样就可以成功的回复消息了。因为toUser是写死的,这个公众号只能给固定的用户回复消息,而且只能say hello。不过,它总算是“活过来”了。在后续的内容里,我们将真正打造一个能够跟用户对话,并且具备一定智能的聊天机器人。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 点击查看原文 Web SDK 开发手册 SDK 概述 网易云信 SDK 为 Web 应用提供一个完善的 IM 系统...
    layjoy阅读 14,739评论 0 15
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,369评论 19 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 175,277评论 25 709
  • 既然爱,为什么不说出口,有些东西失去了,就在也回不来了! 人最软弱的地方,是舍不得。舍不得一段不再精采的感情,舍不...
    爱你的wo阅读 2,688评论 0 0
  • 大家好,今天是2016年里的最后一天。 此刻的你是否会对即将逝去的一年感到不舍?或者深叹口气觉得终于熬过了这一年?...
    遇见卡米拉阅读 1,339评论 0 0