Python快速搭建自动回复微信公众号

BillieFoust 8年前
   <p>在之前的一篇文章 <a href="http://www.open-open.com/lib/view/open1461049274371.html">Python利用 <strong>AIML</strong> 和 <strong>Tornado</strong> 搭建聊天机器人微信订阅号</a> 中用 <strong>aiml</strong> 实现了一个简单的英文聊天机器人订阅号。但是只能处理英文消息,现在用 <a href="/misc/goto?guid=4959668049987440652"><strong>图灵机器人</strong></a> 来实现一个中文的聊天机器人订阅号。</p>    <p>这里主要介绍如何利用 <strong>Python</strong> 的 <a href="/misc/goto?guid=4958874019002200766"><strong>Tornado</strong></a> Web框架以及<a href="/misc/goto?guid=4959671249855802118">wechat-python-sdk</a> 微信公众平台 <strong>Python</strong> 开发包来快速搭建微信公众号。</p>    <p>完整的公众号代码 <strong>GitHub</strong> 地址:<a href="/misc/goto?guid=4959671249949731424">green</a> ,由于目前此公众号有一些功能正在开发中,此完整代码会与下文所描述的代码有不一致的地方,但是自动回复的功能会一直保留。</p>    <p>自动回复效果:<br> <img alt="自动回复" src="https://simg.open-open.com/show/fbdb3dc24ecff83f65db91bbefdf3d4e.png"></p>    <h2>安装Python库</h2>    <p>通过 <strong>pip</strong> 安装 <strong>wechat-python-sdk</strong> , <strong>Requests</strong> 以及 <strong>Tornado</strong></p>    <pre>  <code class="language-python">pip install tornado  pip install wechat-sdk  pip install requests</code></pre>    <h2>订阅号申请</h2>    <p>要搭建订阅号,首先需要在微信公众平台官网进行注册,注册网址: <a href="/misc/goto?guid=4959552464932701429">微信公众平台</a>。</p>    <p>目前个人用户可以免费申请微信订阅号,虽然很多权限申请不到,但是基本的消息回复是没有问题的。</p>    <h2>服务器接入</h2>    <p>具体的接入步骤可以参考官网上的<a href="/misc/goto?guid=4959664843674907744">接入指南</a>。</p>    <p>本订阅号的配置为:<br> <img alt="服务器配置" src="https://simg.open-open.com/show/3df656fecc49e9de78376a95802a0441.png"></p>    <p>配置里的URL为服务器提供订阅号后台的url路径,本文用到的源代码配置的是 <strong><a href="/misc/goto?guid=4959671250090935231">http://server_ip/wx</a></strong> 其中 <strong>server_ip</strong> 是运行源代码的主机的公网ip地址。</p>    <p><strong>Token</strong> 可以设置为任意字符串。</p>    <p><strong>EncodingAESKey</strong> 可以选择随机生成。</p>    <p>消息加密方式可以设置为比较简单的明文模式。</p>    <p>接受并处理微信服务器发送的接入请求的关键代码为Tornado的一个Handle, <code>wx.py</code> :</p>    <pre>  <code class="language-python">import tornado.escape  import tornado.web    from wechat_sdk import WechatConf  conf = WechatConf(      token='your_token', # 你的公众号Token      appid='your_appid', # 你的公众号的AppID      appsecret='your_appsecret', # 你的公众号的AppSecret      encrypt_mode='safe',  # 可选项:normal/compatible/safe,分别对应于 明文/兼容/安全 模式      encoding_aes_key='your_encoding_aes_key'  # 如果传入此值则必须保证同时传入 token, appid  )    from wechat_sdk import WechatBasic  wechat = WechatBasic(conf=conf)    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 signature != 'default' and timestamp != 'default' and nonce != 'default' and echostr != 'default' \                  and wechat.check_signature(signature, timestamp, nonce):              self.write(echostr)          else:              self.write('Not Open')</code></pre>    <p>此代码的作用就是验证消息是来自微信官方服务器后直接返回echostr。</p>    <p>启动后台的 <code>main.py</code> 代码:</p>    <pre>  <code class="language-python">import tornado.web  import tornado.httpserver  from tornado.options import define, options    settings = {              'static_path': os.path.join(os.path.dirname(__file__), 'static'),              'template_path': os.path.join(os.path.dirname(__file__), 'view'),              'cookie_secret': 'e440769943b4e8442f09de341f3fea28462d2341f483a0ed9a3d5d3859f==78d',              'login_url': '/',              'session_secret': "3cdcb1f07693b6e75ab50b466a40b9977db123440c28307f428b25e2231f1bcc",              'session_timeout': 3600,                'port': 5601,              'wx_token': 'weixin',              }    web_handlers = [          (r'/wx', wx.WX),          ]    define("port", default=settings['port'], help="run on the given port", type=int)    if __name__ == '__main__':      app = tornado.web.Application(web_handlers, **settings)      tornado.options.parse_command_line()      http_server = tornado.httpserver.HTTPServer(app)      http_server.listen(options.port)      tornado.ioloop.IOLoop.instance().start()</code></pre>    <p>配置好程序源代码后运行,确认运行无误后再在公众号设置页面点击 <strong>提交</strong> ,如果程序运行没问题,会显示接入成功。</p>    <h2>接入图灵机器人</h2>    <p>要接入图灵机器人,首先需要在官网申请API Key。</p>    <p>申请到之后可以利用以下代码包装一个自动回复接口:</p>    <pre>  <code class="language-python"># -*- coding: utf-8 -*-  import json  import requests  import traceback    class TulingAutoReply:      def __init__(self, tuling_key, tuling_url):          self.key = tuling_key          self.url = tuling_url        def reply(self, unicode_str):          body = {'key': self.key, 'info': unicode_str.encode('utf-8')}          r = requests.post(self.url, data=body)          r.encoding = 'utf-8'          resp = r.text          if resp is None or len(resp) == 0:              return None          try:              js = json.loads(resp)              if js['code'] == 100000:                  return js['text'].replace('<br>', '\n')              elif js['code'] == 200000:                  return js['url']              else:                  return None          except Exception:              traceback.print_exc()              return None</code></pre>    <h2>编写公众号自动回复代码</h2>    <p>利用 <a href="/misc/goto?guid=4959671249855802118">wechat-python-sdk</a> 微信公众平台 <strong>Python</strong> 开发包可以很容易地处理公众号的所有消息。</p>    <p>如下为处理来自微信官方服务器的微信公众号消息的 <strong>Tornado</strong> Handler对象(此代码会获取公众号收到的用户消息并调用刚刚包装的图灵机器人API自动回复) <code>wx.py</code>部分代码:</p>    <pre>  <code class="language-python"># -*- coding: utf-8 -*-  import tornado.escape  import tornado.web    auto_reply = TulingAutoReply(key, url) # key和url填入自己申请到的图灵key以及图灵请求url    class WX(tornado.web.RequestHandler):      def wx_proc_msg(self, body):          try:              wechat.parse_data(body)          except ParseError:              print 'Invalid Body Text'              return          if isinstance(wechat.message, TextMessage): # 消息为文本消息              content = wechat.message.content              reply = auto_reply.reply(content)              if reply is not None:                  return wechat.response_text(content=reply)              else:                  return wechat.response_text(content=u"不知道你说的什么")          return wechat.response_text(content=u'知道了')        def post(self):          signature = self.get_argument('signature', 'default')          timestamp = self.get_argument('timestamp', 'default')          nonce = self.get_argument('nonce', 'default')          if signature != 'default' and timestamp != 'default' and nonce != 'default' \                  and wechat.check_signature(signature, timestamp, nonce):              body = self.request.body.decode('utf-8')              try:                  result = self.wx_proc_msg(body)                  if result is not None:                      self.write(result)              except IOError, e:                  return</code></pre>    <p>来自: <a href="/misc/goto?guid=4959671250181133654" rel="nofollow">http://blog.csdn.net/tobacco5648/article/details/51190039</a> </p>