Python搭建聊天機器人微信訂閱號

mzzg3278 9年前發布 | 26K 次閱讀 Python Python開發

AIML ,全名為Artificial Intelligence Markup Language(人工智能標記語言),是一種創建自然語言軟件代理的XML語言,是由Richard Wallace和世界各地的自由軟件社區在1995年至2002年發明的。

它的雛形是一個名為”A.L.I.C.E.” (“Artificial Linguistic Internet Computer Entity”)的高度擴展的Eliza機器人。ALICE總共贏得3次每年度的Loebner獎,并且在2004年獲得了Chatterbox Challenge的冠軍。由于A.L.I.C.E. 的AIML設置是在GNU GPL協議下發布的,所以已經有許多基于該程序和AIML庫的“克隆ALICE”出現。目前AIML已經有了Java,Ruby,Python, C ,C#,Pascal等語言的版本。

TornadoFriendFeed 使用的可擴展的非阻塞式 web 服務器及其相關工具的開源版本。這個 Web 框架看起來有些像 web.py 或者 Google 的 webapp,不過為了能有效利用非阻塞式服務器環境,這個 Web 框架還包含了一些相關的有用工具 和優化。

Tornado 和現在的主流 Web 服務器框架(包括大多數 Python 的框架)有著明顯的區別:它是非阻塞式服務器,而且速度相當快。得利于其 非阻塞的方式和對 epoll 的運用,Tornado 每秒可以處理數以千計的連接,這意味著對于實時 Web 服務來說,Tornado 是一個理想的 Web 框架。我們開發這個 Web 服務器的主要目的就是為了處理 FriendFeed 的實時功能 ——在 FriendFeed 的應用里每一個活動用戶都會保持著一個服務器連接。

微信公眾平臺 是運營者通過公眾號為微信用戶提供資訊和服務的平臺,而公眾平臺開發接口則是提供服務的基礎,開發者在公眾平臺網站中創建公眾號、獲取接口權限后,可以通過閱讀本接口文檔來幫助開發。

Python可以很方便地利用Tornado框架以及AIML搭建一個聊天機器人微信公眾號,本文簡單介紹下如何用Python編寫簡單的聊天機器人。不過由于目前AIML上缺少高質量的中文語料庫而不支持中文聊天。因此本文搭建的為英文聊天機器人。

此搭建方式需要一臺具有固定公網ip地址的主機一臺。也可以利用現有的云主機或者云平臺,例如 sina app engine

此微信訂閱號的完整源代碼可以通過此鏈接下載:聊天機器人訂閱號源代碼

1 實現效果

搭建的微信訂閱號可以直接回復用戶發送的英文消息與用戶聊天。

 

效果截圖:
Chat with CuriousGuys

2 安裝相關Python庫

需要用到Tornado以及aiml庫。

Linux下安裝Tornado可以直接用以下腳本:

pip install tornado

其它操作系統下安裝Tornado可以參考Tornado官方網站

Linux下安裝aiml也可以直接pip安裝:

pip install aiml

其它操作系統下的安裝請參考AIML官方網站

3 獲取alice資源

Python aiml安裝完成后在Python安裝目錄下的 Lib/site-packages/aiml下會有alice子目錄,將此目錄復制到工作區。
或者在Google code上下載alice brain: aiml-en-us-foundation-alice.v1-9.zip

4 訂閱號申請

要搭建訂閱號,需要在微信官網進行注冊,注冊網址:微信公眾平臺

目前個人用戶可以免費申請微信訂閱號,雖然很多權限申請不到,但是基本的消息回復是沒有問題的。

5 服務器接入

具體的接入步驟可以參考官網上的接入指南

本訂閱號的配置為:
CuriousGuys服務器配置

配置里的URL為服務器提供訂閱號后臺的url路徑,本文用到的源代碼配置的是 http://server_ip/wx 其中 server_ip 是運行源代碼的主機的公網ip地址。這個可以通過修改源代碼里的config.py來配置。

Token 可以設置為任意字符串,不過要將源代碼config.py里的settings[‘wx_token’]改為設置的字符串。

EncodingAESKey 可以選擇隨機生成。

消息加密方式可以設置為比較簡單的明文模式。

接受并處理微信服務器發送的接入請求的關鍵代碼為Tornado的一個Handle(在源代碼里的handle/wx.py中):

class WX(tornado.web.RequestHandler):
    def get(self):
        signature = self.get_argument('signature', 'default')
        timestamp = self.get_argument('timestamp', 'default')
        nonce = self.get_argument('nonce', 'default')
        echostr = self.get_argument('echostr', 'default')
        if config.settings['wx_test'] or (signature != 'default' and timestamp != 'default' and nonce != 'default' and echostr != 'default' and check_wx_request(signature, timestamp, nonce)):
            self.write(echostr)
        else:
            self.write('Not Open')

此代碼的作用就是驗證消息是來自微信官方服務器后直接返回echostr。

配置好程序源代碼后運行,確認運行無誤后再點擊 提交 ,如果程序運行沒問題,會顯示接入成功。

6 程序編寫

關鍵部分為利用aiml回復用戶發送的消息。

aiml載入語料庫的代碼為(在config.py中):

import aiml
cur_dir = os.getcwd()
print 'cur_dir:', cur_dir
os.chdir('./res/alice')
alice = aiml.Kernel()
alice.learn("startup.xml")
alice.respond('LOAD ALICE')
os.chdir(cur_dir)
print 'cur_dir:', os.getcwd()

服務器回復用戶消息的關鍵代碼為(在handle/wx.py中):

# -*- coding: utf-8 -*-
import tornado.escape
import tornado.web

from BaseHTTPServer import HTTPServer
import base64
import sys
import json
import time

import config
import time
import hashlib
import urllib
import os
import random

from util.xml2json import *

# 處理xml格式的用戶消息
def wx_proc_msg(msg_body):
    try:
        jmsg = xml2json(msg_body)
        msgjson = json.loads(jmsg)
        msg = msgjson['xml']
        MsgType = msg['MsgType']

        main_content = {}
        main_content['MsgType'] = msg['MsgType']
        main_content['CreateTime'] = msg['CreateTime']
        main_content['ToUserName'] = msg['FromUserName']
        main_content['FromUserName'] = msg['ToUserName']

        if MsgType == 'text':
            req = msg['Content']
            respond = config.alice.respond(req)
            if respond == None or len(respond) < 1:
                respond = '''Sorry I can't understand you'''
            main_content['Content'] = respond
            result = {}
            result['xml'] = main_content.copy()

            result = json2xml(result)
            return result

        elif MsgType == 'image':
            main_content['MsgType'] = 'text'
            main_content['Content'] = '''Sorry I can't read picture.'''
            result = {}
            result['xml'] = main_content

            return json2xml(result)

        elif MsgType == 'voice':
            pass
        elif MsgType == 'video':
            pass
        elif MsgType == 'shortvideo':
            pass
        elif MsgType == 'location':
            pass
        elif MsgType == 'link':
            pass
        else:
            pass

    except Exception, e:
        print 'Error when process this message:', msg_body
        print e
    return ''

# 驗證消息是否來自微信官方服務器
def check_wx_request(signature, timestamp, nonce):
    token = config.settings['wx_token']
    arr = [token, timestamp, nonce]
    arr.sort()
    sh = hashlib.sha1(arr[0] + arr[1] + arr[2]).hexdigest()
    if sh == signature:
        return True
    else:
        return False

# Tornado的Handle,用于接收并處理用戶消息
class WX(tornado.web.RequestHandler):
    def post(self):
        signature = self.get_argument('signature', 'default')
        timestamp = self.get_argument('timestamp', 'default')
        nonce = self.get_argument('nonce', 'default')
        if config.settings['wx_test'] or (signature != 'default' and timestamp != 'default' and nonce != 'default' and check_wx_request(signature, timestamp, nonce)):
            body = self.request.body
            try:
                self.write(wx_proc_msg(body))
            except IOError, e:
                return

來自: http://blog.csdn.net/tobacco5648/article/details/50600310 

 本文由用戶 mzzg3278 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!