使用websocket开发智能聊天机器人
前面我们学习了异步web框架(sanic)和http异步调用库httpx,今天我们学习websocket技术。
websocket简介
我们知道HTTP协议是:请求->响应,如果没有响应就一直等着,直到超时;但是有时候后台的处理需要很长时间才能给到结果,比如30分钟,那HTTP的请求不可能等这么久,所以,可以通过 Ajax 轮询来解决。那就是每间隔一段时间就请求一次。
这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。
HTML5 定义的 WebSocket 协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。
浏览器通过 JavaScript 向服务器发出建立 WebSocket 连接的请求,连接建立以后,客户端和服务器端就可以通过 TCP 连接直接交换数据。
好了,WebSocket就是为了解决这个问题的,感兴趣去看其他资料!
智能聊天机器人
我一开始只是为了学习WebSocket找个例子,不少例子使用了聊天功能。我稍加改进就变成了智能聊天功能了。
通过异步sanic异步框架实现Web功能。官方文档里面给个WebSocket使用的例子。
https://sanic.readthedocs.io/en/latest/sanic/websocket.html
snaic部分核心代码如下:
import sanic import httpx from sanic import Sanic from sanic.response import json from sanic.websocket import WebSocketProtocol from sanic.exceptions import NotFound from sanic.response import html from jinja2 import Environment, PackageLoader env = Environment(loader=PackageLoader(‘app‘, ‘templates‘)) app = Sanic(__name__) @app.route(‘/‘) async def index(request): """ 聊天页面 """ template = env.get_template(‘index.html‘) html_content = template.render(title=‘聊天机器人‘) return html(html_content) @app.websocket(‘/chat‘) async def chat(request, ws): """ 处理聊天信息,并返回消息 """ while True: user_msg = await ws.recv() print(‘Received: ‘ + user_msg) intelligence_data = {"key": "free", "appid": 0, "msg": user_msg} r = httpx.get("http://api.qingyunke.com/api.php", params=intelligence_data) chat_msg = r.json()["content"] print(‘Sending: ‘ + chat_msg) await ws.send(chat_msg) if __name__ == "__main__": app.error_handler.add( NotFound, lambda r, e: sanic.response.empty(status=404) ) app.run(host="192.168.0.7", port=8000, protocol=WebSocketProtocol, debug=True)
- index() 函数,返回聊天页面。这里用到了jinja2 模板渲染库。
- chat() 函数,通过webSocket实现消息的接收、处理和返回。
智能聊天是怎么做到的,这里要感谢 青云客网络,他们提供了免费的接口。(我当时也只是抱着试试看的态度,没想到,duang~! )
user_msg = "你好!" intelligence_data = {"key": "free", "appid": 0, "msg": user_msg} r = httpx.get("http://api.qingyunke.com/api.php", params=intelligence_data) chat_msg = r.json()["content"] print(chat_msg)
是不是超简单。
再来看前端代码,主要部分:
<div class="container theme-showcase" role="main" style="margin-top: 80px;"> <div id="contents" style="height: 600px; background-color:#eee;"></div> <div> <textarea class="form-control" id="msg"></textarea> <button class="btn btn-lg btn-info" onclick="sendMsg()" style="float: right;">发送</button> </div> </div> <script src="http://code.jquery.com/jquery-2.1.1.min.js"></script> <script type="text/javascript"> var ws = new WebSocket("ws://192.168.0.7:8000/chat"); ws.onmessage = function(e) { $("#contents").append(‘<div class="alert alert-info" role="alert" style="float: left;">‘ + "机器人: " + e.data + "</div><br><br><br><br>"); } function sendMsg() { var msg = $("#msg").val(); $("#contents").append(‘<div class="alert alert-info" role="alert" style="float:right">‘ + msg + "</div><br><br><br><br>"); ws.send(msg); $("#msg").val(""); } </script>
这里使用到了 bootstrap 前端框架,主要 调用部分在:
var Socket = new WebSocket(url, [protocol] );
- Socket.send(msg): 使用连接发送数据。
- Socket.onmessage: 客户端接收服务端数据时触发。
我知道,你迫不及待想要完整的代码了: