环境和工具公众号一个云服务器一个Python环境Flask(Python第三方库)图灵机器人账号以上就是我们实现公众号后台智能对话所需要的robot环境和工具,前两个就不多说了。我们的代码是用Python开发的,所以需要配置Python开发环境,安装Flash库。最后,您需要注册一个图灵机器人账号,并调用它的API接口。欢迎来到我的公众号码小白TM来玩机器人,看看这个机器人聪明不聪明!Web服务器搭建我们要接收公众号后台发送的消息,我们需要搭建一个Web服务器。我们在云服务器上安装好Python和Flask之后,就可以搭建web服务器了。我们首先构建一个非常简单的Web服务器,它显示HelloWorld!在网页上运行我们的代码。我们来看看主要的程序代码。main.pyfromflaskimportFlaskapp=Flask(__name__)@app.route("/")defindex():return"HelloWorld!"if__name__=="__main__":app.run(host='0.0.0.0')代码很简单,我们直接运行代码,启动web服务器:pythonmain.py运行成功后,我们就可以在云服务器机器的浏览器上访问127.0.0.1了。如果我们能看到HelloWorld!,就说明我们的服务器启动成功了。我们也可以在外网机器浏览器上访问你的云服务器的外网IP,查看web服务器是否启动成功。公众号后台配置与验证然后我们进入公众号后台开发->基础配置页面找到服务器配置,可以看到我们需要一个服务器URL地址,Token令牌,消息加解密密钥。公众号后台配置服务器的URL地址为:http://服务器外网IP/wechat,/前面是你的云服务外网IP地址,后面是我们在代码中定义的路由入口(你可以自己定义),我们稍后会在代码中看到。Token是我们自己定义的,后面的代码中会用到。可自动生成消息加解密密钥,在明文模式下可选择消息加解密方式。第一次配置时,底部会有一个保存按钮。这个时候我们先不要点击,因为我们需要在web服务器端对message字段进行解析处理,然后返回结果进行校验。我们来看看微信公众号开发文档中的消息验证流程。验证过程按照上面的过程,我们编写我们的代码。main.pyfromflaskimportFlaskfromflaskimportrequestimporthashlibapp=Flask(__name__)@app.route("/")defindex():返回“HelloWorld!”#公众号后台消息路由入口@app.route("/wechat",methods=["GET","POST"])defwechat():#验证使用GET方式ifrequest.method="GET":signature=request.args.get('signature')timestamp=request.args.get('timestamp')nonce=request.args.get('nonce')echostr=request.args.get('echostr')token="公众号token后台填写"#排序dataList=[token,timestamp,nonce]dataList.sort()result="".join(dataList)#Hash加密算法得到hashcodesha1=hashlib.sha1()sha1.update(result.encode("utf-8"))hashcode=sha1.hexdigest()ifhashcode==signature:returnechostrelse:return""if__name__=="__main__":app.run(host='0.0.0.0',port=80)#公众号后台只开放80端口这里需要注意http的固定端口号要使用80,其他不能填写。卡在这里好久了,因为我的服务器上还有自己的博客,80端口被博客占用了。为了把80端口放出去,我重新建立了我的博客,修改了端口,导致现在访问我的博客,后面必须加上修改后的端口。如果这里有同学有更高的方法,请告诉我!好了,现在我们的验证过程已经完成,我们的网络服务器正在运行。然后进入公众号后台配置,点击保存。如果提示验证通过,恭喜你,你已经完成了验证。如果提示验证失败,我们可以根据错误提示查看问题出在哪里。我们已经成功验证了“你让我回答”和“图片”之间的通信,我们将开始处理公众号上粉丝发送的消息。我们先实现一个简单的“你问我答”。粉丝发短信给公众号,公众号立即回复同一条短信给粉丝;回复同一张图片给粉丝。我们从公众号文档中得知,普通用户使用POST方式向公众号发送消息。消息分为文字消息、图片消息、语音消息、视频消息等多种类型。这里我们只处理和回复短信和彩信(您也可以稍后处理和回复其他消息)。消息的格式是XML数据包。我们来看一个文本消息示例:13488318601234567890123456ToUserName开发者微信FromUserName发件人账号(一个OpenID)CreateTime消息创建时间(整数)MsgType消息类型,text为文本,image为图片Content短信内容MsgId消息id,64位整数被动回复文本消息,即消息的类型短信我们回复用户:1460541339Content回复消息内容回复图片消息类型:12345678MediaId通过素材管理中的接口上传多媒体文件,我们知道收到的id和回复消息的格式。让我们来看看整个过程。让我们根据流程修改我们的代码。我们添加两个文件来处理收到的消息,以及回复消息receive.py、reply.py。receive.pyimportxml.etree.ElementTreeasETdefparse_xml(web_data):iflen(web_data)==0:returnNonexmlData=ET.fromstring(web_data)msg_type=xmlData.find('MsgType').textifmsg_type=='text':returnTextMsg(xmlData)elifmsg_type=='image':returnImageMsg(xmlData)classMsg(object):def__init__(self,xmlData):self.ToUserName=xmlData.find('ToUserName').textself.FromUserName=xmlData.find('FromUserName').textself。CreateTime=xmlData.find('CreateTime').textself.MsgType=xmlData.find('MsgType').textself.MsgId=xmlData.find('MsgId').textclassTextMsg(Msg):def__init__(self,xmlData):消息.__init__(self,xmlData)self.Content=xmlData.find('Content').textclassImageMsg(Msg):def__init__(self,xmlData):Msg.__init__(self,xmlData)self.PicUrl=xmlData.find('PicUrl').textself.MediaId=xmlData.find('MediaId').textreply.pyimporttimeclassMsg(object):def__init__(self):passdefsend(self):return"成功"classTextMsg(Msg):def__init__(self,toUserName,fromUserName,内容):self.__dict=dict()self.__dict['ToUserName']=toUserNameself.__dict['FromUserName']=fromUserNameself.__dict['CreateTime']=int(time.time())self.__dict['Content']=contentdefsend(self):XmlForm="""{CreateTime}"""returnXmlForm.format(**self.__dict)classImageMsg(Msg):def__init__(self,toUserName,fromUserName,mediaId):self.__dict=dict()self.__dict['ToUserName']=toUserNameself.__dict['FromUserName']=fromUserNameself.__dict['CreateTime']=int(time.time())self.__dict['MediaId']=mediaIddefsend(self):XmlForm="""{CreateTime}"""returnXmlForm.format(**self.__dict)main.pyfromflaskimportFlaskfromflaskimportrequestimporthashlibimportreceiveimportreplyapp=Flask(__name__)@app.route("/")defindex():return"HelloWorld!"#公众号后台消息路由entry@app.route("/wechat",methods=["GET","POST"])defwechat():#验证使用的GET方法ifrequest.method="GET":signature=request.args.get('signature')timestamp=request.args.get('timestamp')nonce=request.args.get('nonce')echostr=request.args.get('echostr')token="公众号后台填写的token》#排序dataList=[token,timestamp,nonce]dataList.sort()result="".join(dataList)#Hash加密算法得到hashcodesha1=hashlib.sha1()sha1.更新(result.encode("utf-8"))哈希码=sha1.hexdigest()ifhashcode==signature:returnchostrelse:return""else:recMsg=receive.parse_xml(request.data)ifisinstance(recMsg,receive.Msg):toUser=recMsg.FromUserNamefromUser=recMsg.ToUserNameifrecMsg.MsgType=='文本':content=recMsg.ContentreplyMsg=reply.TextMsg(toUser,fromUser,content)returnreplyMsg.send()elifrecMsg.MsgType=='image':mediaId=recMsg.MediaIdreplyMsg=reply.ImageMsg(toUser,fromUser,mediaId)returnreplyMsg.send()其他:returnreply.Msg().send()else:returnreply.Msg().send()if__name__=="__main__":app.run(host='0.0.0.0',port=80)#公众号仅后台开启80端口后,我们启动web服务器,进入公众号后台发送消息和图片进行测试。如果成功,我们将立即以相同的文字和图片回复您。微信提供了在线测试平台,非常方便开发。的各种测试。访问图灵机器人首先,我们去图灵机器人官网注册一个账号。然后在后台创建一个机器人。然后我们按照图灵机器人接入文档的使用说明:编码方式:调用图灵API的各个环节编码方式为UTF-8接口地址:http://openapi.tuling123.com/openapi/api/v2请求方式:HTTPPOST请求参数:参数格式为json请求参数示例:{"reqType":0,"perception":{"inputText":{"text":"Nearbyhotels"},"inputImage":{"url":"imageUrl"},"selfInfo":{"location":{"city":"北京","province":"北京","street":"信息路"}}},"userInfo":{"apiKey":"","userId":""}}输出参数示例:{"intent":{"code":10005,"intentName":"","actionName":"","parameters":{"nearby_place":"hotel"}},"results":[{"groupType":1,"resultType":"url","values":{"url":"http://m.elong.com/hotel/0101/nlist/#indate=2016-12-10&outdate=2016-12-11&keywords=%E4%BF%A1%E6%81%AF%E8%B7%AF"}},{"groupType":1,"resultType":"text","values":{"text":"亲爱的,已经帮你找到相关的酒店信息"}}]}其中apiKey可以在我们创建的机器人的参数中找到,userId是用户的唯一标识。下面写我们的代码。我们添加一个tuling.py文件访问图灵界面。tuling.pyimportjsonimporturllibapiKey='从你创建的机器人中获取'tulingUrl="http://openapi.tuling123.com/openapi/api/v2"#content是接收到的消息,userId是用户的唯一标识deftulingReply(content,userId):requestData={"reqType":0,"perception":{"inputText":{"text":content},"selfInfo":{"location":{"city":"北京"}}},"userInfo":{"apiKey":apiKey,"userId":userId}}requestData=json.dumps(requestData).encode('utf8')http_post=urllib.request.Request(tulingUrl,data=requestData,headers={'content-type':'application/json'})response=urllib.request.urlopen(http_post)response_str=response.read().decode('utf8')response_dic=json.loads(response_str)results_code=response_dic['intent']['code']#免费版每天有固定次数。超过则返回4003错误码'结果'][0]['值']['文本']returnresults_textModifymain.pyfromflaskimportFlaskfromflaskimportrequestimporthashlibimportreimporttulingimportreceiveimportreplyapp=Flask(__name__)@app.route("/")defindex():return"HelloWorld!"#公众号后台消息路由entry@app.route("/wechat",methods=["GET","POST"])defwechat():#验证使用的GET方法ifrequest.method=="GET":signature=request.args.get('signature')timestamp=request.args.get('timestamp')nonce=request.args.get('nonce')echostr=request.args.get('echostr')token="公众号token后台填充"#排序dataList=[token,timestamp,nonce]dataList.sort()result="".join(dataList)#hash加密算法得到hashcodesha1=hashlib.sha1()sha1.update(result.encode("utf-8"))hashcode=sha1.hexdigest()ifhashcode==signature:returnchostrelse:return""else:recMsg=receive.parse_xml(request.data)ifisinstance(recMsg,receive.Msg):toUser=recMsg.FromUserNamefromUser=recMsg.ToUserNameifrecMsg.MsgType=='text':content=recMsg.Content用户名#userId长度小于等于32位iflen(toUser)>31:userid=str(toUser[0:30])else:userid=str(toUser)userid=re.sub(r'[^A-Za-z0-9]+','',userid)tulingReplay=tuling.tulingReply(content,userid)replyMsg=reply.TextMsg(toUser,fromUser,tulingReplay)returnreplyMsg.send()elifrecMsg.MsgType=='图像':mediaId=recMsg.MediaIdreplyMsg=reply.ImageMsg(toUser,fromUser,mediaId)returnreplyMsg.send()else:returnreply.Msg().send()else:returnreply.Msg().send()if__name__=="__main__":app.run(host='0.0.0.0',port=80)#公众号后台只开放了80端口,我们的机器人就完成了,迫不及待的想马上试试,可以愉快的和你的机器人对话了。后来发现第一次关注公众号后的欢迎信息没有了,因为你自己的服务器接管了公众号的消息,所以原来后台设置的欢迎信息失效了。在公众号文档中看到关注/取消关注是一个事件。其消息格式如下。123456789我们只需要判断MsgType是event,那么Event就是subscribe,然后回复我们的欢迎信息没关系,很简单,这个我们就不细说了。