python調用圖靈機器人實現微信公衆號的自動回覆功能(下)

​圖靈機器人接口調用限制的解決

昨天咱們的文章中說到:使用圖靈機器人做爲應答機器人能夠知足要求,可是天天的回覆條數在不花錢的狀況下只能有100條。對於我這樣貧困線人口怎麼可能每月花費99元就爲了自動回覆呢。因而我就在想還有沒有其它的方式可以快速作一個請求和應答表呢? 結合我以前工做上的經驗,那我理解就是直接將請求語句的關鍵詞和須要的回覆放在一個Excel表格中,而後直接經過查詢Excel表格這樣也能作到自動回覆,說幹就幹。整個流程以下圖: python

在這裏插入圖片描述

從流程圖上看咱們仍是在昨天的總體框架上新增後續的容錯處理,一旦檢測到圖靈機器人API請求已用完以後,咱們便啓動咱們的容錯機制,在咱們的Excel表格中去查找咱們須要返回的內容,若沒有找到的話,咱們就直接返回一個固定語句告訴粉絲朋友,咱們如今可能沒有聽懂。flask

總體已經說完了,接下來咱們就開始實幹了。首先咱們須要去讀取一個Excel表格,我使用的是xlrd這個庫(同樣啊,安裝方法參考以前的python學習三——庫安裝),因爲以前咱們已經整理了一個Excel表格的讀寫模塊——ReadAndWriteExcel.py,因此在這裏我直接將這個模塊拿過來調用就行了,具體代碼見下:服務器

# _*_coding=utf-8_*_
import xlwt
import xlrd

class WriteExcel:
    def __init__(self, sheet_name=None):
        """初始化寫表格對象 ​ :param sheet_name: 寫表格的sheet名,默認爲1 """
        if sheet_name:
            self.sheetname = sheet_name
        else:
            self.sheetname = "1"
        self.workbook = xlwt.Workbook()
        self.worksheet = self.workbook.add_sheet(sheetname=self.sheetname)
​
    def write_values(self, row, col, values):
        """向目標sheet的某個行列寫入值​ :param row: 目標行 :param col: 目標列 :param values: 想要寫入的值 """
        self.worksheet.write(row, col, values)
​
    def save_file(self, filename=None):
        """保存表格 :param filename: 保存的文件名 """
        if filename:
            self.filename = filename
        else:
            self.filename = "test.xls"
        self.workbook.save(self.filename)
class OpenExcel:
    def __init__(self, file_name=None, sheet_id=None):
        """初始化讀取Excel表格 ​ :param file_name: 須要讀取的表格名 :param sheet_id: 須要讀取的表格sheet """
        if file_name:
            self.file_name = file_name
            self.sheet_id = sheet_id
        else:
            self.file_name = 'example.xlsx'
            self.sheet_id = 0
        self.data = self.get_data()
    def get_data(self):
        """讀取表格數據 ​ :return: 返回讀取的表格數據 """
        data = xlrd.open_workbook(self.file_name)
        tables = data.sheets()[self.sheet_id]
        return tables
​
    def get_lines(self):
        """讀取表格總行數 ​ :return: 返回表格總行數 """
        tables = self.data
        return tables.nrows
​
    def get_cols(self):
        """讀取表格總行數 ​ :return: 返回表格總列數 """
        tables = self.data
        return tables.ncols
​
    def get_value(self, row, col):
        """讀取表格中具體的行、列對應的值 ​ :param row: 目標行 :param col: 目標列 :return: 返回目標行、列的值 """
        return self.data.cell_value(row, col)

if __name__ == '__main__':
    openexcel = OpenExcel(file_name="work.xls",sheet_id=0)
    print (openexcel.get_lines())
    write_excel = WriteExcel()
    for j in range(0,openexcel.get_cols()):
        for i in range(0,openexcel.get_lines()):
            write_excel.write_values(i,j,openexcel.get_value(i,j))
    write_excel.write_values(100,100,"我是誰")
    write_excel.save_file()
複製代碼

接下來咱們以下弄一個調用程序來調用ReadAndWriteExcel.py,實現咱們根據第一列的關鍵詞返回第二列的回覆內容。代碼以下:微信

import ReadAndWriteExcel
​
def excel_reply(msg):
    """關鍵字回覆"""
    keyword_read = ReadAndWriteExcel.OpenExcel(file_name="KeyWord.xlsx",sheet_id=0)
    for i in range(0,keyword_read.get_lines()):
        if msg in keyword_read.get_value(i,0):
            return keyword_read.get_value(i,1)
    if '你叫啥' in msg or '你叫啥名字' in msg:
        return '沃德天·維森莫·拉莫帥·帥德布耀'
    elif '我愛你' in msg:
        return  "我也愛你"
    elif '早安'in msg:
        return "早安啊,朋友"
    else:
        return '我沒有聽懂你在說什麼,\n或許我休息一天,\n明天就能智商上線了~'
    pass
複製代碼

這裏咱們不只僅是經過讀取Excel,也將一些固定的回覆放在代碼中進行調試了。接下來咱們來看看主程序的代碼。app

# -*- coding:utf-8 -*-
from flask import Flask
from flask import request
import hashlib
import tyuling_replay
import time
import re
import ReplayFromExcel
import xml.etree.ElementTree as ET
​
​
app = Flask(__name__)
​
@app.route("/")
def index():
    return "Hello World!"@app.route("/wechat", methods=["GET","POST"])
def weixin():
    if request.method == "GET":     # 判斷請求方式是GET請求
        my_signature = request.args.get('signature')     # 獲取攜帶的signature參數
        my_timestamp = request.args.get('timestamp')     # 獲取攜帶的timestamp參數
        my_nonce = request.args.get('nonce')        # 獲取攜帶的nonce參數
        my_echostr = request.args.get('echostr')         # 獲取攜帶的echostr參數
        # my_token = request.args.get('token')
        print(my_signature)
        print(my_timestamp)
        print(my_nonce)
        print(my_echostr)
        # print(my_token)
        token = '123456'     # 必定要跟剛剛填寫的token一致# 進行字典排序
        data = [token,my_timestamp ,my_nonce ]
        data.sort()
        # 拼接成字符串,進行hash加密時需爲字符串
        data = ''.join(data)
        #建立一個hash對象
        s = hashlib.sha1()
        #對建立的hash對象更新須要加密的字符串
        s.update(data.encode("utf-8"))
        #加密處理
        mysignature = s.hexdigest()
​
        print("handle/GET func: mysignature, my_signature: ", mysignature, my_signature)
​
        # 加密後的字符串可與signature對比,標識該請求來源於微信
        if my_signature == mysignature:
            return my_echostr
        else:
            return ""
    else:
            # 解析xml
            xml = ET.fromstring(request.data)
            toUser = xml.find('ToUserName').text
            fromUser = xml.find('FromUserName').text
            msgType = xml.find("MsgType").text
            createTime = xml.find("CreateTime")
            # 判斷類型並回復
            if msgType == "text":
                content = xml.find('Content').text
                #根據公衆號粉絲的ID生成符合要求的圖靈機器人userid
                if len(fromUser)>31:
                    tuling_userid = str(fromUser[0:30])
                else:
                    tuling_userid = str(fromUser)
                tuling_userid=re.sub(r'[^A-Za-z0-9]+', '', tuling_userid)
                #調用圖靈機器人API返回圖靈機器人返回的結果
                tuling_replay_text = tyuling_replay.get_message(content,tuling_userid)
                #將圖靈機器人返回的內容發送給粉絲
                if '4003' in tuling_replay_text:
                    return reply_text(fromUser, toUser,ReplayFromExcel.excel_reply(content))
                else:
                    return reply_text(fromUser, toUser, tuling_replay_text)
            else:
                return reply_text(fromUser, toUser, "我只懂文字")
​
def reply_text(to_user, from_user, content):
    """ 以文本類型的方式回覆請求 """
    return """ <xml> <ToUserName><![CDATA[{}]]></ToUserName> <FromUserName><![CDATA[{}]]></FromUserName> <CreateTime>{}</CreateTime> <MsgType><![CDATA[text]]></MsgType> <Content><![CDATA[{}]]></Content> </xml> """.format(to_user, from_user, int(time.time() * 1000), content)
​
if __name__ == "__main__":
    app.run(host='0.0.0.0', port=80)
複製代碼

咱們在查看圖靈機器人的API文檔發現返回碼爲4003時爲API接口調用次數已用完,因此咱們以前判斷4003是否在API接口的返回信息中,若存在,則圖靈機器人API調用已用完,須要使用Excel備選方案進行答覆。 框架

在這裏插入圖片描述
這樣咱們的微信公衆號就不再會出現服務器異常的報錯了。

圖片和關注的自動回覆

這樣配置了以後,咱們還發現了一些問題,如:因爲使用了API開發接口,致使公衆號默認的自動化回覆沒法使用了。1、一樣的關注的自動回覆也不能同時使用了;2、上面咱們的回覆也一直都是針對的文字,對於圖片消息沒法進行應答。針對這兩個問題,咱們再次對咱們的程序進行了優化,新增了關注自動回覆和圖片回覆原圖的狀況。先上代碼:學習

if msgType == "text":
                content = xml.find('Content').text
                #根據公衆號粉絲的ID生成符合要求的圖靈機器人userid
                if len(fromUser)>31:
                    tuling_userid = str(fromUser[0:30])
                else:
                    tuling_userid = str(fromUser)
                tuling_userid=re.sub(r'[^A-Za-z0-9]+', '', tuling_userid)
                #調用圖靈機器人API返回圖靈機器人返回的結果
                tuling_replay_text = tyuling_replay.get_message(content,tuling_userid)
                #將圖靈機器人返回的內容發送給粉絲
                if '4003' in tuling_replay_text:
                    return reply_text(fromUser, toUser,ReplayFromExcel.excel_reply(content))
                else:
                    return reply_text(fromUser, toUser, tuling_replay_text)
            #關注公衆號的自動答覆
            elif msgType == "event":
                Event = xml.find('Event').text
                if Event == "subscribe":
                    subscribe_reply = "菜鳥小白終於等到你~\n" \
                                      "咱們能夠一塊兒學習打卡,\n" \
                                      "一塊兒努力成長。\n" \
                                      "你煩悶時,我還能夠陪你聊天解悶哦~"
                    return reply_text(fromUser, toUser, subscribe_reply)
            elif msgType == "image":
                mediaId = xml.find('MediaId').text
                return reply_image(fromUser, toUser, mediaId)
            else:
                return reply_text(fromUser, toUser, "我只懂文字")
​
def reply_text(to_user, from_user, content):
    """ 複製代碼

以文本類型的方式回覆請求優化

return """ <xml> <ToUserName><![CDATA[{}]]></ToUserName> <FromUserName><![CDATA[{}]]></FromUserName> <CreateTime>{}</CreateTime> <MsgType><![CDATA[text]]></MsgType> <Content><![CDATA[{}]]></Content> </xml> """.format(to_user, from_user, int(time.time() * 1000), content)
def reply_image(to_user, from_user, mediaId):
複製代碼

以圖片類型的方式回覆請求,返回原圖片加密

return """ <xml> <ToUserName><![CDATA[{}]]></ToUserName> <FromUserName><![CDATA[{}]]></FromUserName> <CreateTime>{}</CreateTime> <MsgType><![CDATA[image]]></MsgType> <Image> <MediaId><![CDATA[{}]]></MediaId> </Image> </xml> """.format(to_user, from_user, int(time.time() * 1000), mediaId)
複製代碼

經過對微信公衆號開發文檔的閱讀,咱們發現文字類消息和圖片類消息的區分在於msgType,文字類型消息爲text,圖片類消息爲image。對於圖片類的消息圖片是保存在MediaId字段中,咱們只須要將這個在返回給粉絲就行了,就是原圖返給粉絲。spa

咱們也發現新增粉絲關注時,咱們收到的是一個msgType是event,當event中的包含的內容是subscribe時爲粉絲關注,咱們判斷收到這樣的消息,就返回須要回覆粉絲的內容便可。

固然這樣還會有一些其餘的問題,如怎麼回覆音頻、視頻。這個方法都是相似的,大家能夠參考微信公衆號的開發手冊,本身想一想該如何解決。 關注微信公衆號「菜鳥小白的學習分享」回覆「101」獲取微信公衆號自動回覆機器人源碼哦。 關注微信公衆號「菜鳥小白的學習分享」回覆「100」獲取微信公衆號自動回覆機器人可執行程序哦。 關注微信公衆號——菜鳥小白的學習分享 媽媽不再用擔憂我找不到路了

在這裏插入圖片描述
一我的的學習——孤單 一羣人的學習——幸福
相關文章
相關標籤/搜索