最近又要做一个微信公众平台项目了。
距离前一次做项目已经过去了一年的时间,在这一年的时间里面微信公众平台的变化很大啊!添加了很多功能,再使用简单的web.py开发起来就有一些难度了(也不是难度,就是工作量问题)。果断开始寻找python版的微信框架。

于是我找到了WeRobot框架,框架的开发者仍然是一名高中生,但不妨碍这是一个很好用的框架。截止这篇文章的时候版本到了0.53,微信平台截止目前所有的功能都支持。而且这个框架甚至提供了在SAE上部署的教程。甚为方便。

直接点开该项目的sae-demo,照着其示例代码进行werobot安装,在此之前你需要git和virtualenv,这两者的安装不赘述。WeRobot SAE安装代码如下:

[code]
git clone git://github.com/whtsky/WeRoBot-SAE-demo.git
cd WeRoBot-SAE-demo
virtualenv –no-site-packages .
source bin/activate #如果是windows环境请使用Scripts\activate代替
pip install sae-python-dev
saecloud install werobot
[/code]

注意作者在这个地方的代码有误,bin/active应该为上面的bin/activate,windows环境下的代码也不相同。
如果没有什么错误的话,本地代码就应该创建好了现在去修改config.yaml文件中的name属性,再使用

[code]
saecloud deploy .
[/code]

命令就可以上传了,需要注意的是一定要记得在本地先安装svn再使用saecloud deploy,不然肯定会遇到error2,我找这个问题找了好久,读了源代码才发现,结果sae的官方文档里面就有,怪我读文档不仔细。

成功之后还是发现index.wsgi,有错误,检查多遍才发现仍然是找不到lib路径的问题,除了官方示例中robot.py中的sys.path.insert(0, os.path.join(root, ‘site-packages’))之外,还需要加一句:sys.path.insert(1, os.path.join(root, ‘Lib/site-packages’)),robot.py的完整代码如下:

[python]
import os
import sys

root = os.path.dirname(__file__)

sys.path.insert(0, os.path.join(root, ‘site-packages’))
sys.path.insert(1, os.path.join(root, ‘Lib/site-packages’))

import werobot

robot = werobot.WeRoBot(token=’tokenhere’)

@robot.handler
def echo(message):
return ‘Hello World!’
[/python]

此时访问主页仍然出错,查看原因后发现,与文档中写的不一样,0.53版本的session是默认开启的,sae又不允许文件io,所以出错,修改办法是在创建WeRobot实例时再传入参数enable_session=False。
如果想要使用session,可以使用sae的kvdb来保存session信息,首先在sae的控制面板中开启kvdb,然后将如下代码保存为site-packages/werobot/session/kvdbstorage.py

[python]
# -*- coding: utf-8 -*-
”’
Author: Howard
Page: http://www.nilday.com
”’

from werobot.session import SessionStorage
from werobot.utils import json_loads, json_dumps
import sae.kvdb

class KVDBStorage(SessionStorage):
"""
SAE KVDB Storage
需要开启SAE的KVDB服务
"""
def __init__(self):
self.kv = sae.kvdb.KVClient()

def get(self, id):
stringvalue=self.kv.get(id)
if stringvalue==None:
return {}
value=json_loads(stringvalue)
return value

def set(self, id, value):
session = json_dumps(value)
self.kv.set(id,session)

def delete(self, id):
self.kv.delete(id)
[/python]

在robot.py文件中修改如下:

[python]
import os
import sys

root = os.path.dirname(__file__)

sys.path.insert(0, os.path.join(root, ‘site-packages’))
sys.path.insert(1, os.path.join(root, ‘Lib/site-packages’))

import werobot
from werobot.session.kvdbstorage import KVDBStorage

session_storage=KVDBStorage()
robot = werobot.WeRoBot(token=’tokenhere’,enable_session=True,session_storage=session_storage)

@robot.handler
def hello(message, session):
count = session.get("count", 0) + 1
session["count"] = count
return "Hello! You have sent %s messages to me" % count
[/python]

到此为止我们的微信公众平台就搭建好了,大家可以把token换成自己的token,此时直接访问主要会得到一个403错误页面这是由于微信公众平台不允许直接get方式访问导致,在微信公众平台的控制面板上设置好调用地址和token,就可以使用了。
以上提到的一些bug都已经反馈给了开发者,希望他越做越好,真是后生可畏啊!

参考文献:

https://werobot.readthedocs.org/en/latest/

https://github.com/whtsky/WeRoBot-SAE-demo

http://sae.sina.com.cn/doc/python/tools.html#saecloud

上一篇文章:利用SAE搭建微信公众平台(二)

上篇文章讲了如何在SAE搭建Hello World,那么这篇文章主要写如何实现微信的验证和自动回复。

首先修改SAE中的index.wsgi文件如下:

[python]
# coding: UTF-8
import os

import sae
import web

from weixinInterface import WeixinInterface

urls = (
‘/’, ‘Hello’,
‘/weixin’,’WeixinInterface’
)

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

class Hello:
def GET(self):
#print "你好"
return render.hello("你好")

app = web.application(urls, globals()).wsgifunc()

application = sae.create_wsgi_app(app)
[/python]

即创建一个weixinInterface类来处理微信的请求。
在目录下创建weixinInterface文件,定义WeixinInterface类。

一、实现微信验证。

回顾微信开发者的验证方式(一下摘自微信官方文档):

填写信息

公众平台用户提交信息后,微信服务器将发送GET请求到填写的URL上,并且带上四个参数:

参数 描述
signature 微信加密签名
timestamp 时间戳
nonce 随机数
echostr 随机字符串

开发者通过检验signature对请求进行校验(下面有校验方式)。若确认此次GET请求来自微信服务器,请原样返回echostr参数内容,则接入生效,否则接入失败。

signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。

加密/校验流程:
1. 将token、timestamp、nonce三个参数进行字典序排序
2. 将三个参数字符串拼接成一个字符串进行sha1加密
3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信

那么首先要解决的就是get方法的问题。在WeixinInterface模块中添加代码如下:

[python]
#coding:UTF-8
import hashlib
import web
class WeixinInterface:

def GET(self):
#获取输入参数
data=web.input()

signature=data.signature
timestamp=data.timestamp
nonce=data.nonce
echostr=data.echostr
#自己的token
token="yourtoken"
#字典序排序
list=[token,timestamp,nonce]
list.sort()
#sha1加密算法
sha1=hashlib.sha1()
map(sha1.update,list)
hashcode=sha1.hexdigest()
#如果是来自微信的请求,则回复echostr
if hashcode == signature:
#print "true"
return echostr
[/python]

现在,放回微信公众平台的注册界面,填上你的验证地址即:http://yourdomain.sinaapp.com/weixin,token填自己的token,要和上面程序中一致。点击提交,如果没有意外现在就应该验证成功了。

二、实现简单的文本回复

现在阅读微信公众平台的文档,先只注意接收文本信息和回复文本信息的格式:

消息推送

当普通微信用户向公众账号发消息时,微信服务器将POST该消息到填写的URL上。结构如下:

文本消息

[xml]
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1348831860</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[this is a test]]></Content>
<MsgId>1234567890123456</MsgId>
</xml>
[/xml]


参数 描述
ToUserName 开发者微信号
FromUserName 发送方帐号(一个OpenID)
CreateTime 消息创建时间 (整型)
MsgType text
Content 文本消息内容
MsgId 消息id,64位整型

消息回复

对于每一个POST请求,开发者在响应包中返回特定xml结构,对该消息进行响应(现支持回复文本、图文、语音、视频、音乐和对收到的消息进行星标操作)。 微信服务器在五秒内收不到响应会断掉连接。 回复xml结构如下:

回复文本消息

[xml]
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>12345678</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[content]]></Content>
<FuncFlag>0</FuncFlag>
</xml>
[/xml]

参数 描述
ToUserName 接收方帐号(收到的OpenID)
FromUserName 开发者微信号
CreateTime 消息创建时间
MsgType text
Content 回复的消息内容,长度不超过2048字节
FuncFlag 位0x0001被标志时,星标刚收到的消息。

那么显然的是,我们需要解析xml文件。SAE预装了lxml库,能够方便的解析xml。首先切换到config.yaml,添加代码,效果如下:

[code]

name: tedxfactory798
version: 1
libraries:
– name: webpy
version: "0.36"
– name: lxml
version: "2.3.4"
[/code]

下面切换回weixinInterface文件,代码如下:

[python]
#coding:UTF-8
import hashlib
import web
import lxml
import time
import os
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="yourtoken"
#字典序排序
list=[token,timestamp,nonce]
list.sort()
#sha1加密算法
sha1=hashlib.sha1()
map(sha1.update,list)
hashcode=sha1.hexdigest()
#如果是来自微信的请求,则回复echostr
if hashcode == signature:
#print "true"
return echostr

def POST(self):
#从获取的xml构造xml dom树
str_xml=web.data()
xml=etree.fromstring(str_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)
[/python]

那么我们还需要建立一个模板,在template目录下,reply_text.xml:

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

保存全部文件,注意一下toUser和fromUser的顺序,和接受的时候正好相反。

如果没有错的话~在微信上加上自己的公众账号测试吧!

上一篇文章:利用SAE搭建微信公众平台(一)

下一篇文章:利用SAE搭建微信公众平台(三)

微信在国内已经越来越火了,特别是有了公众平台之后,出现了很多好玩的聊天机器人。比如武大助手,号称在24小时只能搭建完成。给了同学们很多方便。

最近在TEDxFactory798从事志愿者工作,负责技术部分。因为工作需要而想到了搭建TEDxFactory798的微信平台,而SAE(Sina App Engine)是国内最早开始提供云服务的平台之一,而且几乎是免费的。所以希望能够通过SAE平台快速的搭建好一个微信公众账号。在一边摸索一边学习的情况下,小半天就搭好了一个简易的微信公众平台。

首先注册微信公众账号:http://mp.weixin.qq.com,点击注册,通过很简单的几步就能快速注册好公众账号,需要注意的是这里是需要注册一个新的微信号,而不是通过已有的私人微信号绑定。可能需要注册一个专用的邮箱。注册过程很简单,不赘述。

第二步是注册SAE,访问http://sae.sina.com.cn,SAE整个的文档都比较完整,很好上手。注册完成后会送500云豆,合人民币5元。再申请实名认证,送云豆2000。对于一个刚上手的开发者来说完全够了。等应用开发好后,还可以申请开发者认证。每月有固定额度的云豆赠送,基本就不用花钱了。另外还有教育机构认证,公益组织认证等。同样十分简单,不赘述。

第三步,登录公众平台后,点击高级功能。首先要关闭编辑模式,才能进入开发模式。(可以先不关闭, 等自己的服务器假设好之后再关闭)。阅读微信公众平台文档:http://mp.weixin.qq.com/wiki/index.php?title=%E9%A6%96%E9%A1%B5。我们看到需要提供一个接入信息:

接口配置

接口配置

那么我们需要一个网址作为接口,Token呢,就是相当于我们和微信之间约定的“密码”,以验证是微信平台的访问。再阅读接下来的要求:

网址接入

公众平台用户提交信息后,微信服务器将发送GET请求到填写的URL上,并且带上四个参数:

参数 描述
signature 微信加密签名
timestamp 时间戳
nonce 随机数
echostr 随机字符串

开发者通过检验signature对请求进行校验(下面有校验方式)。若确认此次GET请求来自微信服务器,请原样返回echostr参数内容,则接入生效,否则接入失败。

signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。

加密/校验流程:
1. 将token、timestamp、nonce三个参数进行字典序排序
2. 将三个参数字符串拼接成一个字符串进行sha1加密
3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信

那么很明确我们接下来需要做的事情了:为微信提供一个接口。

第四步:在SAE上创建一个应用。在我的应用中点击创建应用:

创建应用

创建应用

填好二级域名和应用名称等,选择好语言。这里我们使用Python开发选择web应用。创建好应用之后,在代码管理中创建一个新的版本。而后我们可以选择编辑代码。能够实现在线编辑,根本用不着配置本地环境,SVN等等。当然如果你觉得需要也可以根据文档配置本地环境开发。:

代码管理

代码管理

代码编辑页

代码编辑页

那么下一步我们就要开始Hello World了。

第五步:编写Hello World。

我们这里选择web.py框架编写网页应用。该框架非常小,学习代价很低。有中文文档:http://webpy.org/cookbook/index.zh-cn。SAE平台有两个很重要的文件,一个是config.yaml,是应用的配置文件,另一个是index.wsgi,是应用的入口文件。这两个文件在创建应用的时候就已经生成了。现在打开config.yaml文件,修改为:

[code]

name: youappnapp
version: 1
libraries:
– name: webpy
version: "0.36"
[/code]

name为你的应用名,版本为1,库应用webpy,这个是SAE预装的库。预装版本为0.36。我们也就使用0.36版。修改完成后使用Ctrl+S保存,这个细节做得很好,和本地保存一样,非常方便,当然也可以使用右上角的全部保存按钮。

接下来打开index.wsgi文件,修改如下(与官方文档的hello world略有不同):

[python]
# coding: UTF-8
import os

import sae
import web

urls = (
‘/’, ‘Hello’
)

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

class Hello:
def GET(self):
return render.hello("你好")

app = web.application(urls, globals()).wsgifunc()

application = sae.create_wsgi_app(app)
[/python]

这里的coding:UTF-8告诉python文件的编码是UTF-8,对于带中文的应用来说必不可少。简单解释一下,最下面显而易见的是应用的入口,那么url配置到我们用那个类来实现路由,比如上述代码中的url是指根目录用Hello类来处理。在类中实现GET和POST方法就能处理相应的http请求。还需要注意到的是有个templates目录,在其中有个hello.html文件来实现模板。模板参数传递进一个”你好”。具体可见webpy教程。

接下来我们点击左上角的创建目录,创建一个叫做templates的目录,双击进入目录,再创建一个叫做hello.html的文件。代码如下:

[html]
$def with (name)
Hello $name!
[/html]

即定义一个name的参数(就是我们传进来的“你好”),在模板中任意地方引用$name就会被参数替代掉。

至此,Hello World已经写完了。访问应用根目录就能看到:

Hello 你好

的页面了。

待续。

下一篇文章:利用SAE搭建微信公众平台(二)

最近在准备毕设开题,要写论文,有各种参考文献。网上找了一下word中插入参考文献的方法,主要是尾注的形式。想起来之前在学校图书馆网站上下载过一个叫做NoteExpress的软件,可以方便的管理和插入参考文献,把具体使用方法写出来分享一下。

一、下载软件:http://www.reflib.org/download_chs.htm。这里面有各个大学、科研单位图书馆以及国图版的软件下载。可以免费获得正版授权。找自己对应的学校下载。

二、安装软件:过程不赘述。跟大多数软件安装过程一样,如果没有意外的话,Word插件也会同时装好。只是64位的Word需要单独下载和安装,下载连接中有安装说明,并且插件暂时只有英文版,我的就是,所以只能在用英文的插件来进行演示,好在非常简单。

三、管理文献:

3.1新建数据库:

1.文件->新建数据库

新建数据库1

新建数据库1

2.选择数据库路径。并选择复制文件到附件文件夹,这样可以更方便管理论文集。

新建数据库2

新建数据库2

3.2检索文献:

其实可以跳过这步,完全可以用手动输入文献的相关信息来代替。但是如果想偷懒的话,就完全可以利用NoteExpress的检索功能来帮你自动完成文献信息。

1.检索->在线检索->选择在线数据库。选择一个数据库,可以选选择你下载文献的数据库,保证一定有该文献。

检索1

检索1

或者:选择一个已经检索过的数据库:

检索2

检索2

2.检索。选择检索的方式,点击开始检索。

检索3

检索3

3.双击检索出来的文件,可以编辑信息。如果不全可以补全。

检索4

检索4

4.保存检索结果:选择保存勾选的题录->至文件夹:题录

检索5

检索5

3.3插入附件:可以使的题录与文件关联。选择要要关联的题录,附件标签,右键添加文件。

附件

附件

3.4选择插入样式:设置出入到word中的样式

1.工具->样式->样式管理器

样式1

样式1

2.选择合适的样式,比如国标样式,可以直接收缩GB

样式2

样式2

3.双击样式名,可以更改样式。比如点击布局。

样式3

样式3

四、在word中插入和删除参考文献:

4.1插入

1.在word工具栏中选择NoteExpress 工具栏,点击双窗口显示,这样比较好操作。

插入1

插入1

2.选择你要插入的文献,光标保持在腰插入的位置,点击插入引用。

插入2

插入2

3.这是插入后的参考文献列表,已经已国标形式展示。

插入3

插入3

4.2删除:和官方某些文档上不太一样,因为没有直接的删除引用按钮。但是可以用如下方式实现

1.选择编辑引用

删除1

删除1

2.选择要删除的引用,点击删除,确定。

删除2

删除2

3.删除之后的参考文献,对比插入的参考文献。

删除3

删除3

五、更多帮助:

1.NoteExpress 与endNote的比较。

2.NoteExpress使用教程,百度文库