FaiChou

折腾了个Web应用

25 Aug 2016

环境

  1. SAE
  2. 个人公众号
  3. Git
  4. Python

SAE

新浪云应用(Sina App Engine简称SAE).

在SAE上搭建python应用

在SAE上搭建python应用

公众号

手持身份证的大头照
申请 + 等待
开发者模式 && 基本配置

在基本配置中,我们只需要修改URLTokenEncodingAESKey三项配置即可.

URL, 在SAE上python应用的域名 http://faichoudemo.applinzi.com/weixin

Token, 随便填写英文或者数字faichoudemo

EncodingAESKey, 随机生成吧~

Code

$ mkdir faichoudemo && cd faichoudemo
$ touch config.yaml
$ open -a 'sublime text2' config.yaml

config.yaml

name: faichoudemo
version: 1

libraries:
- name: webpy 
  version: "0.36"

- name: lxml
  version: "2.3.4"
$ touch index.wsgi
$ open -a 'sublime text2' index.wsgi

index.wsgi

# coding: UTF-8
import os

import sae
import web

from weixinInterface import WeixinInterface

urls = (
'/weixin','WeixinInterface'
)

app_root = os.path.dirname(__file__)
templates_root = os.path.join(app_root, 'templates')
render = web.template.render(templates_root)

app = web.application(urls, globals()).wsgifunc()        
application = sae.create_wsgi_app(app)
$ touch index.wsgi
$ open -a 'sublime text2' weixinInterface

weixinInterface.py

# -*- coding: utf-8 -*-
import hashlib
import web
import lxml
import time
import os
import urllib2,json
from lxml import etree

class WeixinInterface:

    def __init__(self):
        self.app_root = os.path.dirname(__file__)
        self.templates_root = os.path.join(self.app_root, 'templates')
        self.render = web.template.render(self.templates_root)

    def GET(self):
        #获取输入参数
        data = web.input()
        signature=data.signature
        timestamp=data.timestamp
        nonce=data.nonce
        echostr=data.echostr
        #自己的token
        token="faichoudemo" #这里改写你在微信公众平台里输入的token
        #字典序排序
        list=[token,timestamp,nonce]
        list.sort()
        sha1=hashlib.sha1()
        map(sha1.update,list)
        hashcode=sha1.hexdigest()
        #sha1加密算法        

        #如果是来自微信的请求,则回复echostr
        if hashcode == signature:
            return echostr

config.yamlindex.wsgi是基本配置,首先需要将公众号和web应用连接起来,根据微信公众平台的要求,通过Get方法进行验证,验证方法是判断echostr是否相等,token,timestamp,nonce排序,通过sha1()算出结果echostr,将其返回。

使用Git代码管理
$ git init 
$ git remote add sae https://git.sinacloud.com/faichoudemo
编辑代码并将代码部署到 `sae` 的版本1。
$ git add .
$ git commit -m 'Init my first app'
$ git push sae master:1

初始化web应用Done

用户发送消息到公众号,微信公众号服务器会post消息到绑定的接口(http://faichoudemo.applinzi.com/weixin), 接下来编写python程序分析数据,处理数据,返回信息.

在weixinInterface中继续添加

def POST(self):        
        str_xml = web.data() #获得post来的数据
        xml = etree.fromstring(str_xml)#进行XML解析
        content=xml.find("Content").text#获得用户所输入的内容
        msgType=xml.find("MsgType").text
        fromUser=xml.find("FromUserName").text
        toUser=xml.find("ToUserName").text
        return self.render.reply_text(fromUser,toUser,int(time.time()),u"我现在还在开发中,还没有什么功能,您刚才说的是:"+content)

现在就有了一个最简单的鹦鹉学舌功能了~

当然还不能运行,因为缺少render

$ mkdir templates && cd templates
$ touch reply_text.xml
$ open -a 'sublime text 2' reply_text.xml

reply_text.xml

$def with (toUser,fromUser,createTime,content)
<xml>
<ToUserName><![CDATA[$toUser]]></ToUserName>
<FromUserName><![CDATA[$fromUser]]></FromUserName>
<CreateTime>$createTime</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[$content]]></Content>
</xml>
$ cd ..

至此,公众号具备了第一个功能:鹦鹉学舌。

照片分析年龄功能

# -*- coding: utf-8 -*-
import requests
import re
def img(picurl):
    s = requests.session()
    url = 'http://how-old.net/Home/Analyze?isTest=False&source=&version=001'
    header = {
    'Accept-Encoding':'gzip, deflate',
    'User-Agent': "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:34.0) Gecko/20100101 Firefox/34.0",
    'Host': "how-old.net",
    'Referer': "http://how-old.net/",
    'X-Requested-With': "XMLHttpRequest"
        }


    data = {'file':s.get(picurl).content}
    #data = {'file': open(sid+'.jpg', 'rb')}
     #此处打开指定的jpg文件

    r = s.post(url, files=data, headers=header)
    h = r.content
    i = h.replace('\\','')
    #j = eval(i)

    gender = re.search(r'"gender": "(.*?)"rn', i)
    age = re.search(r'"age": (.*?),rn', i)
    if gender.group(1) == 'Male':
        gender1 = '男'
    else:
        gender1 = '女'
    #print gender1
    #print age.group(1)
    datas = [gender1, age.group(1)]
    return datas

当然要在你的目录下创建一个vendor文件夹并将requests包放进去

$ mkdir vendor
$ pip install -t vendor requests

之后编辑 index.wsgi,在顶部添加代码即可。

# coding: UTF-8
import os
import sae
import web
sae.add_vendor_dir('vendor')
from weixinInterface import WeixinInterface

...

随机播放一首音乐

首先咱得有音乐

我用的新浪云存储SCS,都是坑,打不开~~

用户发送一条消息到公众号,公众号会post到接口。

消息有类型MsgType:

  • event
  • image
  • text

判断了image后可以将照片读年龄的代码放进去

if mstype == 'image':
    try:
        picurl = xml.find('PicUrl').text
        datas = imageIdentify.img(picurl)
        return self.render.reply_text(fromUser, toUser, int(time.time()), '图中人物性别为'+datas[0]+'\n'+'年龄为'+datas[1])
    except:
        return self.render.reply_text(fromUser, toUser, int(time.time()),  '识别失败,换张图片试试吧')

判断了event后可以将特定的关注或取关的消息放进去

if mstype == "event":
mscontent = xml.find("Event").text
if mscontent == "subscribe":
    replayText = u'''欢迎关注大灰狼的订阅号,这个号是本人业余爱好所建立,也是想一边学习一边玩的东西,它现在还没有什么功能,只是弄了个小工具,你们有什么好的灵感也欢迎反馈给我,我会不定期的分享给大家,输入help或帮助查看操作指令'''
    return  self.render.reply_text(fromUser,toUser,int(time.time()),replayText)
if mscontent == "unsubscribe":
    replayText = u'我现在功能还很简单,知道满足不了您的需求,但是我会慢慢改进,欢迎您以后再来~'                
    return  self.render.reply_text(fromUser,toUser,int(time.time()),replayText)

判断了text后可以继续判断接受数据的content

如果是’m’将音乐加上

如果是’快递00000000’将快递加上

如果是’help’将帮助加上

if mstype == 'text':
    content=xml.find("Content").text
    if content.lower() == 'm':
        musicList = [
                             [r'http://cdn.sinacloud.net/faichou-music/Damien%20Rice%20-%20The%20Blower%27s%20Daughter.mp3?KID=sina,1cryhovVErbP8hWkzDAL&Expires=1472113441&ssig=rmNXPCOkha','The Blower\'s Daughter',u'献给我的小亲亲'],                          
                             [r'http://cdn.sinacloud.net/faichou-music/Damien%20Rice%20-%20Connoisseur%20of%20Great%20Excuse.mp3?KID=sina,1cryhovVErbP8hWkzDAL&Expires=1472113441&ssig=OpX85B4dwv','Damien Rice - Connoisseur of Great Excuse',u'献给我的小亲亲'],
                             [r'http://cdn.sinacloud.net/faichou-music/Bob%20Dylan%20-%20You%20Belong%20to%20Me.mp3?KID=sina,1cryhovVErbP8hWkzDAL&Expires=1472113441&ssig=iN5qHBSjCs','You Belong To Me',u'献给我的小亲亲'],
                             [r'http://cdn.sinacloud.net/faichou-music/Don%20McLean%20-%20Vincent.mp3?KID=sina,1cryhovVErbP8hWkzDAL&Expires=1472113441&ssig=5LdAsD%2F5Gd','Vincent',u'献给我的小亲亲'],
                             [r'http://cdn.sinacloud.net/faichou-music/John%20Lennon%20-%20Watching%20The%20Wheels.mp3?KID=sina,1cryhovVErbP8hWkzDAL&Expires=1472113441&ssig=XEixfD1h0j','John Lennon - Watching The Wheels',u'献给我的小亲亲'],
                             [r'http://cdn.sinacloud.net/faichou-music/Krystian%20Zimerman%20-%20Ballade%20No.1%20in%20G%20minor,%20op.23%20%27Polish%27.mp3?KID=sina,1cryhovVErbP8hWkzDAL&Expires=1472113441&ssig=BdyXdnBhHy','肖邦-第一叙事曲-克里斯蒂安齐默尔曼弹奏',u'献给我的小亲亲'],
                             [r'http://cdn.sinacloud.net/faichou-music/Krystian%20Zimerman%20-%20Fantasie%20in%20F%20minor,%20op.49.mp3?KID=sina,1cryhovVErbP8hWkzDAL&Expires=1472113441&ssig=PB3W%2FoO28k','肖邦-幻想曲-齐默尔曼弹奏',u'献给我的小亲亲'],
                             [r'http://cdn.sinacloud.net/faichou-music/Neil%20Young%20-%20Heart%20of%20Gold.mp3?KID=sina,1cryhovVErbP8hWkzDAL&Expires=1472113441&ssig=EZgAIrdpAK','Neil Young - Heart of Gold',u'献给我的小亲亲'],
                             [r'http://cdn.sinacloud.net/faichou-music/Neil%20Young%20-%20See%20The%20Sky%20About%20To%20Rain.mp3?KID=sina,1cryhovVErbP8hWkzDAL&Expires=1472113441&ssig=68D%2Fjuc%2FcL','Neil Young - See The Sky About To Rain',u'献给我的小亲亲'],
                             [r'http://cdn.sinacloud.net/faichou-music/Tom%20Waits%20-%20If%20I%20Have%20To%20Go.mp3?KID=sina,1cryhovVErbP8hWkzDAL&Expires=1472113441&ssig=MtMRf%2Bvuwo','Tom Waits - If I Have To Go',u'献给我的小亲亲'],
                    ]
        music = random.choice(musicList)
        musicurl = music[0]
        musictitle = music[1]
        musicdes =music[2]
        return self.render.reply_music(fromUser,toUser,int(time.time()),musictitle,musicdes,musicurl)
    elif content[0:2] == u"快递":
        post = str(content[2:])
        kuaidi = fckd.detect_com(post)
        return self.render.reply_text(fromUser,toUser,int(time.time()), kuaidi)
    elif content == 'help' or content == u"帮助":
        replayText = u'''1. 输入m随机听一首音乐~
2. 放一张自拍看看什么效果^_^
3. 随时可以挑逗小灰灰,查询天气,笑话,新闻,百科,快递,菜谱,列车,航班,计算..'''
        return self.render.reply_text(fromUser,toUser,int(time.time()),replayText)

图灵机器人

官网上注册用户,创建机器人,获取APIkey

$ touch tulingRobot.py
$ open -a 'sublime text 2' tulingRobot.py
# -*- coding: utf-8 -*-
import requests
import json
global s
s = requests.session()


def talk(content):
    url = 'http://www.tuling123.com/openapi/api'
    da = {"key": "YOU RAPIKEY", "info": content}
    data = json.dumps(da)
    r = s.post(url, data=data)
    j = eval(r.text)
    code = j['code']
    if code == 100000:
        recontent = j['text']
    elif code == 200000:
        recontent = j['text']+j['url']
    elif code == 302000:
        recontent = j['text']+j['list'][0]['info']+j['list'][0]['detailurl']
    elif code == 308000:
        recontent = j['text']+j['list'][0]['info']+j['list'][0]['detailurl']
    else:
        recontent = '这货还没学会怎么回复这句话'
    return recontent

继续在weixinInterface.py的POST添加


else:
    try:
        msg = tulingRobot.talk(content)
        return self.render.reply_text(fromUser,toUser,int(time.time()), msg)
    except:
        return self.render.reply_text(fromUser,toUser,int(time.time()), '这货还不够聪明,换句话聊天吧')

待完善功能

  1. 接受语音识别结果
  2. 歌曲链接被禁
  3. ..

后记

公众号:sillyTimberWolf

sillyTimberWolf

PS

新浪云没续费, 公众号功能已失效.


comments powered by Disqus