您的位置:首页 > 移动开发 > 微信开发

Flask+SAE快速打造微信公众帐号

2015-06-09 02:16 597 查看
/article/10203346.html

微信公众平台是个很牛逼的东西。大大节约了我们这些玩客的开发成本。Django也不错,但是开发这种东西,太笨重了,大材小用。还是推荐Flask。

本文以我自己的作品为例,介绍一种简单方法,可以快速地从零开始开发一个微信公众帐号,提供简单的搜索歌词的功能,输入“歌曲名 歌手名”,返回歌词。

作品已开源,欢迎围观。

使用技术:Python, Flask框架, SAE

成本:两罐汽水,一个下午一个晚上(或更快)

产出:一个微信公众账号,信息如下

账号名:查理歌词

微信号: chaligeci

项目地址: https://github.com/handalin/CharlieLrc
环境:linux系统

需要先安装的东西: svn ( ubuntu里 apt-get install subversion ) 这是新浪用来管理代码的工具

Flask (文档在此 https://flask-cn.readthedocs.org/en/latest/ ) 这是一个Python写的Web开发框架,轻巧灵活,很适合开发这种小应用。

一、去微信那里申请公号 ( http://mp.weixin.qq.com/

注册完,想好账号的名字(不可更改),填完资料来到一个页面,要求你填入你自己服务器的 url , 还有 token。

token就是令牌,微信平台通过token来验证彼此的身份(就别吐槽这个了。。。)

那么url,填入你的服务器地址。

服务器就采用新浪的Sina App Engine了。

二、到SAE新建一个项目

由于本文的主角是 微信平台, 新浪这边的事儿, 看这里吧 http://sae.sina.com.cn/?m=devcenter&catId=289 ,简洁明了。

三、微信公号和SAE应用的对接-验证

做法就是, 在SAE应用(下面简称应用)里写一个函数来处理Http请求, 微信平台这边会给我们的应用发送一个GET请求,带上4个参数。

我们要做的就是在应用里面处理这个请求,验证(其实可以不用)之后返回echostr参数即可。

上代码:

# -*- coding:utf8 -*-
import time
from flask import Flask,request, make_response
import hashlib

@app.route('/', methods = ['GET', 'POST'] )
def wechat_auth():
if request.method == 'GET':
token = 'xxxxxxxxxxx' # your token
query = request.args  # GET 方法附上的参数
signature = query.get('signature', '')
timestamp = query.get('timestamp', '')
nonce = query.get('nonce', '')
echostr = query.get('echostr', '')
s = [timestamp, nonce, token]
s.sort()
s = ''.join(s)
if ( hashlib.sha1(s).hexdigest() == signature ):
return make_response(echostr)


在微信平台输入你的url和token(要与上面代码里填的一致),点赞,不,点确定,即可完成验证。有问题的时候,记得加上末尾的 ‘/’ 试试 ( 如果你用Django,有ending slash 的问题 )。

四、完成初版- 将用户所发送的内容原样返回 (做完这个你就可以不用继续看了,去发挥你的想象力做出更有趣的东西来吧~)

首先要明白,微信平台提供给开发者的接口,其实是一堆xml格式的数据, 假设用户发了一个消息给公号,那么这个消息会以xml的格式被组织然后发送,那么我们在应用里收到此xml , 理所应当要解析出内容, 这里使用 xml.etree.ElementTree 来解析。 http://mp.weixin.qq.com/wiki/index.php?title=%E6%B6%88%E6%81%AF%E6%8E%A5%E5%8F%A3%E6%8C%87%E5%8D%97
这里可以看到它xml的格式,我们其实只需要解析出 发者,收者,还有内容即可。 ElementTree 可以很轻松地做到这点,代码如下:

# Get the infomations from the recv_xml.
xml_recv = ET.fromstring(request.data)
ToUserName = xml_recv.find("ToUserName").text
FromUserName = xml_recv.find("FromUserName").text
Content = xml_recv.find("Content").text


解析出这些内容之后,我们要按照微信接口的格式构造一个xml发回去, 这里只需把 收者 和 发者 互换位置,加上时间戳和内容, 即可达到效果。

reply = "<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[%s]]></Content><FuncFlag>0</FuncFlag></xml>"
response = make_response( reply % (FromUserName, ToUserName, str(int(time.time())), Content ) )
response.content_type = 'application/xml'
return response


svn commit -m 之后, 更新代码完成。

这里注意,要先去微信公众平台 mp.weixin.qq.com 的高级设置 那里面, 关闭编辑模式,打开开发者模式....

拿起你的手机去试试吧, 发什么回复什么。 你可以试试看骂它傻x,看会发生什么事。

五、查理歌词--一个查歌词的小爬虫

很明显,我们只需要对收到的Content作处理, 得到结果(歌词),返回去即可。

编写 shark.py 文件, shark是虾米的一个产品叫 虾歌, 我很喜欢虾米, 推荐一下吧。 不过虾米的搜索和排名真心是奇葩, 我表示受不了,但暂时先这样吧。

我把它写成了一个类 SharkSearcher, 实现了 feed 函数, 该函数接受关键词参数, 返回歌词结果。

# -*- coding:utf8 -*-
import urllib2, urllib
import sys
import re

class SharkSearcher():
def __init__(self):
self.error_msg = "查理没用...查不到...\nbtw,您听歌的品味真独特.\n您确认格式正确?(歌名 歌手名)"

def process_lrc(self, lrc):
return ''.join( lrc.split('<br />') )

def feed(self, song, artist=None):
if not artist: artist = ''
else: artist = '+' + artist
myurl = 'http://www.xiami.com/search?key=' + song + artist

# pretent to be IE. ^O^
user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
values = {'name':'67',
'location':'Northampton',
'language':'Python'}
headers = { 'User-Agent':user_agent}
data = urllib.urlencode(values)
req = urllib2.Request(myurl, data, headers)
try:
html = urllib2.urlopen(req).read()
except BaseException:
return self.error_msg
pattern = r'<td class="song_name"><a target="_blank" href="(.+?)" title="'
try:
song_url = re.findall(pattern, html)[0]
except BaseException:
return self.error_msg

pattern = r'<div class="lrc_main">([\s\S]+?)</div>'
req = urllib2.Request('http://www.xiami.com'+song_url, data, headers)
try:
html = urllib2.urlopen(req).read()
except BaseException:
return self.error_msg
lrc = re.findall(pattern, html)[0]

return self.process_lrc(lrc)


ss_lrc(lrc)
下面解释下代码:

我的做法很dirty,就是将用户给我的参数拆开,附到 HTTP 的GET请求里发给虾米。

去虾米 (xiami.com) 搜一下, 会发现 它的搜索结果 url 是这样的 http://www.xiami.com/search?key=xxx+yyy(xxx,yyy是搜索的关键词)
, 那么直接用python的urllib2包可以读到整个搜索结果, 然后看它源码, 这里用正则表达式直接抠出了我想要的部分( 第一个链接), 当然你可以用更碉堡的办法,但正则表达式无疑是最好写的。

接着拿到歌曲详情页,依然,用正则表达式抠出歌词,返回即可。

注意,虾米会判断你的身份,限制机器人的访问。 中间那段 # pretent to be IE 就是用来伪装的, 装成是浏览器, 然后虾米就乖乖地交出数据了。

所有代码已放上github。
https://github.com/handalin/CharlieLrc
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: