1. 程式人生 > >python-flask-SAE微信公眾號

python-flask-SAE微信公眾號

  • 最近實名認證了新浪雲,送了三百雲豆,本來以為可以長期有效,但是沒想到坑爹的新浪雲即使沒有使用,居然也每天自動扣除雲豆。這也就解釋了為什麼我首次開通時候送的兩百顆在沒有使用的情況下平白無故消失的原因。
  • 言歸正傳,也正是新浪雲的每天扣豆促使了我這種早有想法卻一直懶癌發作的人花了一週來寫了個微信公眾號功能的開發,使用python+flask寫了一個簡單的傳遞訊息的頁面並部署在sae(新浪雲)上來實現功能的傳送與回覆,用了我在公司實習的一週時間,寫下這篇文章記錄一下前因後果。
  • 要開發公眾號,首先你得有個公眾號對吧,不會的滾去面壁,很簡單,去微信公眾平臺申請一下,然後繫結一下管理員微訊號,再登入官網成為開發者設定一下基本配置,如圖,url是你sae應用建立後的url,建立之後直接複製過來就可以了,token是自己設定的,目的是為了驗證是不是你自己在使用,聽說是出於安全考慮,然並卵,但是後面開發中對接的時候會用到,然後就可以進行微信公眾號開發者了。

     

  • 接下來是去sae新建一個web應用,選的是建立雲應用,目前只支援python2.7版本。

  • 自己填好二級域名之後和應用名稱之後就建立好了,域名可以隨便填,只要不和別人已建立的衝突就行。然後這個域名就是上文中微信開發中需要的url直接搬過去就可以啦。
  • 然後接下來就是程式碼事情了,我使用的是git,如圖,選擇GIt之後上傳程式碼即可。

  • 接下來就是程式碼的事情了。。。

  • 程式碼中有一共三個檔案,功能比較多的話可以自行擴充套件,在此僅開發了部分功能,一個檔案已足夠寫入功能模組。兩個配置檔案中的資訊如圖所示,一個申明一下名字和版本資訊,另一個引入sae,然後從程式碼中引入flask例項app,然後使用sae建立一下即可。
  • 本次實現的功能有天氣查詢、講個笑話還有有道翻譯,本來網上還有實現機器人對話的實現例項,但是我也試了一下,查到網路上有那種可以直接一鍵對接的,根本不需要自己開發的,所以覺得沒意思,就放棄這個功能了。
  • 其實以上功能的實現也並沒有多大難度,因為都有現成的api直接呼叫,自己只需對接然後實現一下資料的格式化就可以了。本次實驗主要體驗一下微信公眾號開發的具體實現過程,並沒有花太多時間在更多功能的實現,而且新浪雲每天都在扣雲豆,很快就會失效,所以僅做學習交流。
  • 首先是理解一下資料的具體傳輸過程,其實flask就起了個傳遞值的作用。

  • 然後是具體接入微信公眾號,文件解釋得很清楚了。

  • python具體對接實現。
@app.route('/',methods=['GET','POST'])
def wechat():
if request.method=='GET':
token='你的token'
data=request.args
signature=data.get('signature','')
timestamp=data.get('timestamp','')
nonce =data.get('nonce','')
echostr=data.get('echostr','')
s=[timestamp,nonce,token]
s.sort()
s=''.join(s)
if(hashlib.sha1(s).hexdigest()==signature):
return make_response(echostr)
else:
rec=request.stream.read()
xml_rec=ET.fromstring(rec)
tou = xml_rec.find('ToUserName').text
fromu = xml_rec.find('FromUserName').text
content = xml_rec.find('Content').text
xml_rep = "<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[%s]]></Content><FuncFlag>0</FuncFlag></xml>"
  • 功能函式的判斷
if content.lower()=='joke':#笑話功能
            response = make_response(xml_rep % (fromu,tou,str(int(time.time())),joke()))
            response.content_type='application/xml'
            return response
        elif 'tianqi' in content.lower():#天氣功能判斷,實現漢字查詢天氣
            if type(content).__name__ == "unicode":
                content = content.encode('UTF-8')
                place=content.lower().replace('+tianqi','')
                response = make_response(xml_rep % (fromu,tou,str(int(time.time())),weather(place)))
                response.content_type='application/xml'
                return response
            else:
                place=content.lower().replace('+tianqi','')
                response = make_response(xml_rep % (fromu,tou,str(int(time.time())),weather(place)))
                response.content_type='application/xml'
                return response
        else:
            if type(content).__name__ == "unicode":#實現漢譯英
                content = content.encode('UTF-8')
                new_word=youdao(content)
                response = make_response(xml_rep % (fromu,tou,str(int(time.time())),new_word))
                response.content_type='application/xml'
                return response
            else:
                new_word=youdao(content)
                response = make_response(xml_rep % (fromu,tou,str(int(time.time())),new_word))
                response.content_type='application/xml'
                return response

  • 公眾號傳送和回覆的訊息格式都是xml格式,開發者文件中有具體的解釋,傳送和接收訊息格式如下,然後使用python中的xml.etree.ElementTree提取資料,傳遞給第三方呼叫的API,處理後返回值,再繼續轉化成xml格式經web響應返回給微信。

  • 接下來就是具體功能函式的實現了,首先要有有道的API key和百度API store的賬號才能呼叫,去有道官網申請一下就可以,百度API store只需要有個百度賬號就可以了,API key在直接複製一下就可以用了。
  • 翻譯和笑話因為使用json格式比較方便,直接解析後獲取字典的值就可以了,然後返回格式按個人喜好設計。天氣的返回值雖然也是json格式,但是因為他裡面套了多層字典,一層一層找比較麻煩,所以就使用了正則表示式簡單粗暴一點提取資料,然後自己寫一下返回格式,再套入xml格式中返回給微信使用者。
  • 程式碼:
#-*- coding: UTF-8 -*-
import time
import urllib2
from flask import Flask,g,request,make_response
import hashlib
import xml.etree.ElementTree as ET
import json
import random
import re
import urllib

app=Flask(__name__)
app.debug=True

def youdao(word):
quary=urllib2.quote(word)
baseurl=r'http://fanyi.youdao.com/openapi.do?keyfrom=自己的&key=自己的&type=data&doctype=json&version=1.1&q='
url=baseurl+quary
resp=urllib2.urlopen(url)
data=json.loads(resp.read())
if data['errorCode'] == 0:
if 'basic' in data.keys():
trans=u'%s:\\n%s\\n%s\\n網路釋意:\\n%s'%(data['query'],''.join(data['translation']),' '.join(data['basic']['explains']),''.join(data['web'][0]['value']))
return trans
else:
trans =u'%s:\\n基本翻譯:%s\\n'%(data['query'],''.join(data['translation']))
return trans
elif data['errorCode'] == 20:
return u'對不起,要翻譯的文字過長'
elif data['errorCode'] == 30:
return u'對不起,無法進行有效的翻譯'
elif data['errorCode'] == 40:
return u'對不起,不支援的語言型別'
else:
return u'對不起,你輸入的單詞%s無法翻譯,請檢查拼寫'% word

def joke():
try:
for i in random.sample(range(335),1):
page='page='+str(i)
full_url='http://apis.baidu.com/showapi_open_bus/showapi_joke/joke_text?'+page
req = urllib2.Request(full_url)
req.add_header("apikey", "自己的key")
resp = urllib2.urlopen(req,timeout=5)
data= json.loads(resp.read())
for i in random.sample(range(len(data['showapi_res_body']['contentlist'])),1):
return data['showapi_res_body']['contentlist'][i]['title']+'\\n'+data['showapi_res_body']['contentlist'][i]['text']+'\\n'
except Exception:
return u'抱歉,你運氣不好,沒有人願意給你講笑話,請重試。'

def weather(city_name):
str_city='city='+str(city_name)
url='http://apis.baidu.com/heweather/weather/free?'+str_city
req = urllib2.Request(url)
req.add_header("apikey", "自己的key")
resp = urllib2.urlopen(req)
content= resp.read().decode('utf-8')
city=re.findall(r'"city":"(.*?)"',content,re.S)
update=re.findall(r'"loc":"(.*?)"',content,re.S)
txt=re.findall(r'"txt_d":"(.*?)"',content,re.S)
max_t=re.findall(r'"max":"(.*?)"',content,re.S)
min_t=re.findall(r'"min":"(.*?)"',content,re.S)
hum=re.findall(r'"hum":"(.*?)"',content,re.S)
pcpn=re.findall(r'"pcpn":"(.*?)"',content,re.S)
vis=re.findall(r'"vis":"(.*?)"',content,re.S)
wind_dir=re.findall(r'"dir":"(.*?)"',content,re.S)
wind_sc=re.findall(r'"sc":"(.*?)"',content,re.S)
wind_spd=re.findall(r'"spd":"(.*?)"',content,re.S)
return u'城市:'+city[0]+'\\n'+u'更新時間:'+update[0]+'\\n'+u'天氣情況:'+txt[0]+'\\n'+u'最高溫度:'+max_t[0]+u'度'+'\\n'+u'最低溫度:'+min_t[0]+u'度'+'\\n'+u'相對溼度:'+hum[0]+'%'+'\\n'+u'降水量:'+pcpn[0]+'mm'+'\\n'+u'能見度:'+vis[0]+'km'+'\\n'+u'風向:'+wind_dir[0]+'\\n'+u'風力:'+wind_sc[0]+'\\n'+u'風速:'+wind_spd[0]+'km/h'+'\\n'
  • 至此,功能已全部實現,使用git上傳程式碼到新浪雲之後就可以使用啦。下面是使用演示,公眾號應該過不了多久功能就會失效,可惡的sae,就不貼出啦。對於回覆圖片功能和語音功能沒有繼續深入,有興趣的小夥伴可以自行研究。回覆語音訊息基本原理與文字訊息類似,但是還需要呼叫一下微信另外的介面先返回一個media_id,然後再傳遞。

作者:HalShaw 連結:https://www.jianshu.com/p/264d55f8d652 來源:簡書 簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授權並註明出處。