承啓
因爲之前設計了要實現一個微信機器人,以向用戶響應響應的文章,這個app十分地簡單,並不需要特別深入的設計,而且我的想法是:拿來主義, 反正github上面那麼多的用python寫的博客系統,我只需要實現微信響應的部分,也就是從數據庫中獲取文章的數據,然後將文章的標題,url,圖片等信息打包成xml格式返回給微信服務器,服務器再返回給用戶。而且我發現,有菜單的會好很多,就像一個完整的app,可以直接點擊察看某篇文章,而不是硬邦邦的回覆。我是用別人寫的一個博客系統進行改造——saepy-log.而這個博客系統又是基於tornado框架的,本來不打算染指tornado的,但是不得不硬着頭皮鑽研。其中遇到了很多困難,在sql語句的like寫法,察看文檔方面有了比較大的收穫。
部署與開發
事先說明,由於我是各種折騰,所以可能照本篇文章做是做不成的。下載了saepy-log的源碼後,按照這裏的操作進行上傳後,就可以將博客系統安裝在sae平臺上了,然後用svn把代碼同步下來到本地工作目錄,一切準備就緒。我們會看到我們的博客已經可以訪問了,而且我們本地還有博客的所有代碼:
我們要修改的是blog.py是博客的核心功能所在,還有modle.py是數據模型的關鍵所在,我們將要擴展數據模型功能,使之完成我們的微信功能。
在blog.py裏面添加我們的微信功能類 weixin.py(由於是用tornado框架,所以方法與在django裏面略有不同):
導入需要用到的包
# weixin used package
import xml.etree.ElementTree as ET
import urllib,urllib2,time,hashlib
import tornado.wsgi
import tornado.escape
主要是xml的解析和一些處理字符串的包,接下來我們定義weixin類的主體:
# 添加微信推送帳號
class WeiXinPoster(BaseHandler):
#-----------------------------------------------------------------------
# 處理get方法 對應check_signature
def get(self):
global TOKEN
signature = self.get_argument("signature")
timestamp = self.get_argument("timestamp")
nonce = self.get_argument("nonce")
echoStr = self.get_argument("echostr")
token = TOKEN
tmpList = [token,timestamp,nonce]
tmpList.sort()
tmpstr = "%s%s%s" % tuple(tmpList)
tmpstr = hashlib.sha1(tmpstr).hexdigest()
if tmpstr == signature:
self.write(echoStr)
#return echoStr
else:
self.write(None);
#return None
# 處理post方法,對應response_msg
def post(self):
global SORRY
# 從request中獲取請求文本
rawStr = self.request.body
# 將文本進行解析,得到請求的數據
msg = self.parse_request_xml(ET.fromstring(rawStr))
# 根據請求消息來處理內容返回
query_str = msg.get("Content")
query_str = tornado.escape.utf8(query_str)
# TODO 用戶發來的數據類型可能多樣,所以需要判別
response_msg = ""
return_data = ""
# 使用簡單的處理邏輯,有待擴展
if query_str[0] == "h": # send help menu to user
response_msg = self.get_help_menu() # 返回消息
# 包括post_msg,和對應的 response_msg
if response_msg:
return_data = self.pack_text_xml(msg, response_msg)
else:
response_msg = SORRY
return_data = self.pack_text_xml(msg, response_msg)
self.write(return_data)
# 分類
elif query_str[0] =="c":
category = query_str[1:]
response_msg = self.get_category_articles(category)
if response_msg:
return_data = self.pack_news_xml(msg, response_msg)
else:
response_msg = SORRY
return_data = self.pack_text_xml(msg, response_msg)
self.write(return_data)
# 列出文章列表
elif query_str[0] =="l":
response_msg = self.get_article_list()
if response_msg:
return_data = self.pack_text_xml(msg, response_msg)
else:
response_msg = SORRY
return_data = self.pack_text_xml(msg, response_msg)
self.write(return_data)
# 直接獲取某篇文章
elif query_str[0] == "a":
# 直接獲取文章的id,然後在數據庫中查詢
article_id = int(query_str[1:])
# 進行操作
response_msg = self.get_response_article_by_id(article_id)
if response_msg:
return_data = self.pack_news_xml(msg, response_msg)
else:
response_msg = SORRY
return_data = self.pack_text_xml(msg, response_msg)
self.write(return_data)
# 還要考慮其他
elif query_str[0] == "s":
keyword = str(query_str[1:])
# 搜索關鍵詞,返回相關文章
response_msg = self.get_response_article(keyword)
# 返回圖文信息
if response_msg:
return_data = self.pack_news_xml(msg, response_msg)
else:
response_msg = SORRY
return_data = self.pack_text_xml(msg, response_msg)
self.write(return_data)
elif query_str[0] == "n":
response_msg = self.get_latest_articles()
# 返回圖文信息
if response_msg:
return_data = self.pack_news_xml(msg, response_msg)
else:
response_msg = SORRY
return_data = self.pack_text_xml(msg, response_msg)
self.write(return_data)
# 如果找不到,返回幫助信息
else:
response_msg = get_help_menu()
if response_msg:
return_data = response_msg
else:
return_data = SORRY
self.write(return_data)
# n for 獲取最新的文章
def get_latest_articles(self):
global MAX_ARTICLE
global PIC_URL
article_list = Article.get_articles_by_latest()
article_list_length = len(article_list)
count = (article_list_length < MAX_ARTICLE) and article_list_length or MAX_ARTICLE
if article_list:
# 構造圖文消息
articles_msg = {'articles':[]}
for i in range(0,count):
article = {
'title': article_list[i].slug,
'description':article_list[i].description,
'picUrl':PIC_URL,
'url':article_list[i].absolute_url
}
# 插入文章
articles_msg['articles'].append(article)
article = {}
# 返回文章
return articles_msg
#-----------------------------------------------------------------------
# 解析請求,拆解到一個字典裏
def parse_request_xml(self,root_elem):
msg = {}
if root_elem.tag == 'xml':
for child in root_elem:
msg[child.tag] = child.text # 獲得內容
return msg
#-----------------------------------------------------------------------
def get_help_menu(self):
menu_msg = '''歡迎關注南苑隨筆,在這裏你能獲得關於校園的資訊和故事。回覆如下按鍵則可以完成得到相應的迴應
h :幫助(help)
l :文章列表(article list)
f : 獲得分類列表
n : 獲取最新文章
a + 數字 :察看某篇文章 a2 察看第2篇文章
s + 關鍵字 : 搜索相關文章 s科研 察看科研相關
c + 分類名 : 獲取分類文章 c校園生活 察看校園生活分類
其他 : 功能有待豐富'''
return menu_msg
#-----------------------------------------------------------------------
# 獲取文章列表
def get_article_list(self):
# 查詢數據庫獲取文章列表
article_list = Article.get_all_article_list()
article_list_str = "最新文章列表供您點閱,回覆a+數字即可閱讀: \n"
for i in range(len(article_list)):
art_id = str(article_list[i].id)
art_id = tornado.escape.native_str(art_id)
art_title = article_list[i].title
art_title = tornado.escape.native_str(art_title)
art_category = article_list[i].category
art_category = tornado.escape.native_str(art_category)
article_list_str += art_id + ' ' + art_title + ' ' + art_category + '\n'
return article_list_str
# 按照分類查找
def get_category_articles(self, category):
global MAX_ARTICLE
global PIC_URL
article_list = Article.get_articles_by_category(category)
article_list_length = len(article_list)
count = (article_list_length < MAX_ARTICLE) and article_list_length or MAX_ARTICLE
if article_list:
# 構造圖文消息
articles_msg = {'articles':[]}
for i in range(0,count):
article = {
'title': article_list[i].slug,
'description':article_list[i].description,
'picUrl':PIC_URL,
'url':article_list[i].absolute_url
}
# 插入文章
articles_msg['articles'].append(article)
article = {}
# 返回文章
return articles_msg
#-----------------------------------------------------------------------
# 獲取用於返回的msg
def get_response_article(self, keyword):
global PIC_URL
keyword = str(keyword)
# 從數據庫查詢得到若干文章
article = Article.get_article_by_keyword(keyword)
# 這裏先用測試數據
if article:
title = article.slug
description = article.description
picUrl = PIC_URL
url = article.absolute_url
count = 1
# 也有可能是若干篇
# 這裏實現相關邏輯,從數據庫中獲取內容
# 構造圖文消息
articles_msg = {'articles':[]}
for i in range(0,count):
article = {
'title':title,
'description':description,
'picUrl':picUrl,
'url':url
}
# 插入文章
articles_msg['articles'].append(article)
article = {}
# 返回文章
return articles_msg
else:
return
def get_response_article_by_id(self, post_id):
global PIC_URL
# 從數據庫查詢得到若干文章
article = Article.get_article_by_id_detail(post_id)
# postId爲文章id
if article:
title = article.slug
description = article.description
picUrl = PIC_URL
url = article.absolute_url
count = 1
# 這裏實現相關邏輯,從數據庫中獲取內容
# 構造圖文消息
articles_msg = {'articles':[]}
for i in range(0,count):
article = {
'title':title,
'description':description,
'picUrl':picUrl,
'url':url
}
# 插入文章
articles_msg['articles'].append(article)
article = {}
# 返回文章
return articles_msg
else:
return
可見app的難度並不大,還是和上次使用微信API裏面的和接近,需要用到的幾個全局變量,需要自己定義,如token,如PIC_URL等。程序原理其實就是解析用戶請求,h開頭,則提供幫助菜單,a開頭加數字的,就提供某篇文章,等等,然後提供相應的函數進行處理,這裏面說明起來比較複雜,就以獲取分類文章來講吧:
需要用到分析用戶請求字符串:
# 分類
elif query_str[0] =="c":
category = query_str[1:]
response_msg = self.get_category_articles(category)
if response_msg:
return_data = self.pack_news_xml(msg, response_msg)
else:
response_msg = SORRY
return_data = self.pack_text_xml(msg, response_msg)
self.write(return_data)
這裏要提供get_category_articles(category)的功能,所以需要在weixin類裏面實現一個這樣的函數:
# 按照分類查找
def get_category_articles(self, category):
global MAX_ARTICLE
global PIC_URL
article_list = Article.get_articles_by_category(category)
article_list_length = len(article_list)
count = (article_list_length < MAX_ARTICLE) and article_list_length or MAX_ARTICLE
if article_list:
# 構造圖文消息
articles_msg = {'articles':[]}
for i in range(0,count):
article = {
'title': article_list[i].slug,
'description':article_list[i].description,
'picUrl':PIC_URL,
'url':article_list[i].absolute_url
}
# 插入文章
articles_msg['articles'].append(article)
article = {}
# 返回文章
return articles_msg
很顯然,這裏需要和數據庫模型Article打交道,看看Article是否實現了該功能,很遺憾沒有,那麼我們只好捲起袖子自己幹——擴展Article,所以我們轉戰到modle.py文件裏面了,寫下了如下的代碼:
# 返回一個包含若干篇文章的數組 limit 5
def get_articles_by_category(self, category):
sdb._ensure_connected()
article_list = sdb.query('SELECT * FROM `sp_posts` WHERE `category` = %s LIMIT 5', str(category))
for i in range(len(article_list)):
article_list[i] = post_detail_formate(article_list[i])
return article_list
這裏進行了數據庫查詢,將category參數傳遞進去,選擇category爲參數的5篇文章,打包返回。post_detail_formate是博客系統已經寫好的,我們只要拿來用就行了。在python裏面,寫sql語句要很小心,遇到要傳入參數的,最好是用逗號分割開,而不是使用%來填充參數。特別是使用like的時候,我們往往需要寫這樣的sql語句:
SELECT * FROM `sp_posts` WHERE `category` LIKE '%study%'
但是python裏面又是用%s做參數佔位符的,故而會引起很多不必要的錯誤,比如這裏。總之要安全使用,最好是作爲參數傳遞,python會爲他們與原字符串裏的%等分開。
上傳發布
完成功能後就可以發佈了,雖然還有很多不足的地方,但是測試發現,還是可以使用的。本項目將開源到github中,歡迎使用(需要修改部分的參數,例如博客名稱等),或者交流研究源代碼。實現後的功能是這樣字的:
比如回覆一個a9,將返回第9篇文章;回覆l,列出所有文章。吐槽一下我們宿舍的網絡,差到離譜,我是獲取信息之後才截屏的。
該篇並不是要將實現的所有細節披露出來,披露細節最好的方法就是公開源代碼,接下來會發布到github上面去,只需稍微配置,你就可以擁有一個可以推送到微信的博客了(我不會告訴你wordpress早就出微信插件了)。經過這一番折騰,可以得出一個微信第三方開發的經驗,那就是初步制定好自己的app需要提供什麼功能,然後接着設計一個類,處理各種的請求,將各種處理部分封裝起來,例如按照分類獲取文章,或者獲取文章列表等,然後在這裏面調用數據庫模型裏面的功能來實現。這是MVC的一種便利之處。此外,還要勇於閱讀源代碼和英文文檔,我之前google了很多字符串轉換編碼的方法,沒有成功,但是閱讀了tornado的文檔之後,我恍然大悟。例如之前在django裏面寫這個應用的時候,我們獲取的還是request.raw_post_data,現在改成了self.request.body,不看文檔,想破頭也想不出來。功能實現雖然告一段落,但是這個項目還有很多需要重寫一次,使得它的表現更好,安全性更高。這裏不得不提一下,服務器中採用tornado真的不是一般快~
END
by bibodeng 2013-05-08
承啓
因爲之前設計了要實現一個微信機器人,以向用戶響應響應的文章,這個app十分地簡單,並不需要特別深入的設計,而且我的想法是:拿來主義, 反正github上面那麼多的用python寫的博客系統,我只需要實現微信響應的部分,也就是從數據庫中獲取文章的數據,然後將文章的標題,url,圖片等信息打包成xml格式返回給微信服務器,服務器再返回給用戶。而且我發現,有菜單的會好很多,就像一個完整的app,可以直接點擊察看某篇文章,而不是硬邦邦的回覆。我是用別人寫的一個博客系統進行改造——saepy-log.而這個博客系統又是基於tornado框架的,本來不打算染指tornado的,但是不得不硬着頭皮鑽研。其中遇到了很多困難,在sql語句的like寫法,察看文檔方面有了比較大的收穫。
部署與開發
事先說明,由於我是各種折騰,所以可能照本篇文章做是做不成的。下載了saepy-log的源碼後,按照這裏的操作進行上傳後,就可以將博客系統安裝在sae平臺上了,然後用svn把代碼同步下來到本地工作目錄,一切準備就緒。我們會看到我們的博客已經可以訪問了,而且我們本地還有博客的所有代碼:
我們要修改的是blog.py是博客的核心功能所在,還有modle.py是數據模型的關鍵所在,我們將要擴展數據模型功能,使之完成我們的微信功能。
在blog.py裏面添加我們的微信功能類 weixin.py(由於是用tornado框架,所以方法與在django裏面略有不同):
導入需要用到的包
# weixin used package import xml.etree.ElementTree as ET import urllib,urllib2,time,hashlib import tornado.wsgi import tornado.escape
主要是xml的解析和一些處理字符串的包,接下來我們定義weixin類的主體:
# 添加微信推送帳號 class WeiXinPoster(BaseHandler): #----------------------------------------------------------------------- # 處理get方法 對應check_signature def get(self): global TOKEN signature = self.get_argument("signature") timestamp = self.get_argument("timestamp") nonce = self.get_argument("nonce") echoStr = self.get_argument("echostr") token = TOKEN tmpList = [token,timestamp,nonce] tmpList.sort() tmpstr = "%s%s%s" % tuple(tmpList) tmpstr = hashlib.sha1(tmpstr).hexdigest() if tmpstr == signature: self.write(echoStr) #return echoStr else: self.write(None); #return None # 處理post方法,對應response_msg def post(self): global SORRY # 從request中獲取請求文本 rawStr = self.request.body # 將文本進行解析,得到請求的數據 msg = self.parse_request_xml(ET.fromstring(rawStr)) # 根據請求消息來處理內容返回 query_str = msg.get("Content") query_str = tornado.escape.utf8(query_str) # TODO 用戶發來的數據類型可能多樣,所以需要判別 response_msg = "" return_data = "" # 使用簡單的處理邏輯,有待擴展 if query_str[0] == "h": # send help menu to user response_msg = self.get_help_menu() # 返回消息 # 包括post_msg,和對應的 response_msg if response_msg: return_data = self.pack_text_xml(msg, response_msg) else: response_msg = SORRY return_data = self.pack_text_xml(msg, response_msg) self.write(return_data) # 分類 elif query_str[0] =="c": category = query_str[1:] response_msg = self.get_category_articles(category) if response_msg: return_data = self.pack_news_xml(msg, response_msg) else: response_msg = SORRY return_data = self.pack_text_xml(msg, response_msg) self.write(return_data) # 列出文章列表 elif query_str[0] =="l": response_msg = self.get_article_list() if response_msg: return_data = self.pack_text_xml(msg, response_msg) else: response_msg = SORRY return_data = self.pack_text_xml(msg, response_msg) self.write(return_data) # 直接獲取某篇文章 elif query_str[0] == "a": # 直接獲取文章的id,然後在數據庫中查詢 article_id = int(query_str[1:]) # 進行操作 response_msg = self.get_response_article_by_id(article_id) if response_msg: return_data = self.pack_news_xml(msg, response_msg) else: response_msg = SORRY return_data = self.pack_text_xml(msg, response_msg) self.write(return_data) # 還要考慮其他 elif query_str[0] == "s": keyword = str(query_str[1:]) # 搜索關鍵詞,返回相關文章 response_msg = self.get_response_article(keyword) # 返回圖文信息 if response_msg: return_data = self.pack_news_xml(msg, response_msg) else: response_msg = SORRY return_data = self.pack_text_xml(msg, response_msg) self.write(return_data) elif query_str[0] == "n": response_msg = self.get_latest_articles() # 返回圖文信息 if response_msg: return_data = self.pack_news_xml(msg, response_msg) else: response_msg = SORRY return_data = self.pack_text_xml(msg, response_msg) self.write(return_data) # 如果找不到,返回幫助信息 else: response_msg = get_help_menu() if response_msg: return_data = response_msg else: return_data = SORRY self.write(return_data) # n for 獲取最新的文章 def get_latest_articles(self): global MAX_ARTICLE global PIC_URL article_list = Article.get_articles_by_latest() article_list_length = len(article_list) count = (article_list_length < MAX_ARTICLE) and article_list_length or MAX_ARTICLE if article_list: # 構造圖文消息 articles_msg = {'articles':[]} for i in range(0,count): article = { 'title': article_list[i].slug, 'description':article_list[i].description, 'picUrl':PIC_URL, 'url':article_list[i].absolute_url } # 插入文章 articles_msg['articles'].append(article) article = {} # 返回文章 return articles_msg #----------------------------------------------------------------------- # 解析請求,拆解到一個字典裏 def parse_request_xml(self,root_elem): msg = {} if root_elem.tag == 'xml': for child in root_elem: msg[child.tag] = child.text # 獲得內容 return msg #----------------------------------------------------------------------- def get_help_menu(self): menu_msg = '''歡迎關注南苑隨筆,在這裏你能獲得關於校園的資訊和故事。回覆如下按鍵則可以完成得到相應的迴應 h :幫助(help) l :文章列表(article list) f : 獲得分類列表 n : 獲取最新文章 a + 數字 :察看某篇文章 a2 察看第2篇文章 s + 關鍵字 : 搜索相關文章 s科研 察看科研相關 c + 分類名 : 獲取分類文章 c校園生活 察看校園生活分類 其他 : 功能有待豐富''' return menu_msg #----------------------------------------------------------------------- # 獲取文章列表 def get_article_list(self): # 查詢數據庫獲取文章列表 article_list = Article.get_all_article_list() article_list_str = "最新文章列表供您點閱,回覆a+數字即可閱讀: \n" for i in range(len(article_list)): art_id = str(article_list[i].id) art_id = tornado.escape.native_str(art_id) art_title = article_list[i].title art_title = tornado.escape.native_str(art_title) art_category = article_list[i].category art_category = tornado.escape.native_str(art_category) article_list_str += art_id + ' ' + art_title + ' ' + art_category + '\n' return article_list_str # 按照分類查找 def get_category_articles(self, category): global MAX_ARTICLE global PIC_URL article_list = Article.get_articles_by_category(category) article_list_length = len(article_list) count = (article_list_length < MAX_ARTICLE) and article_list_length or MAX_ARTICLE if article_list: # 構造圖文消息 articles_msg = {'articles':[]} for i in range(0,count): article = { 'title': article_list[i].slug, 'description':article_list[i].description, 'picUrl':PIC_URL, 'url':article_list[i].absolute_url } # 插入文章 articles_msg['articles'].append(article) article = {} # 返回文章 return articles_msg #----------------------------------------------------------------------- # 獲取用於返回的msg def get_response_article(self, keyword): global PIC_URL keyword = str(keyword) # 從數據庫查詢得到若干文章 article = Article.get_article_by_keyword(keyword) # 這裏先用測試數據 if article: title = article.slug description = article.description picUrl = PIC_URL url = article.absolute_url count = 1 # 也有可能是若干篇 # 這裏實現相關邏輯,從數據庫中獲取內容 # 構造圖文消息 articles_msg = {'articles':[]} for i in range(0,count): article = { 'title':title, 'description':description, 'picUrl':picUrl, 'url':url } # 插入文章 articles_msg['articles'].append(article) article = {} # 返回文章 return articles_msg else: return def get_response_article_by_id(self, post_id): global PIC_URL # 從數據庫查詢得到若干文章 article = Article.get_article_by_id_detail(post_id) # postId爲文章id if article: title = article.slug description = article.description picUrl = PIC_URL url = article.absolute_url count = 1 # 這裏實現相關邏輯,從數據庫中獲取內容 # 構造圖文消息 articles_msg = {'articles':[]} for i in range(0,count): article = { 'title':title, 'description':description, 'picUrl':picUrl, 'url':url } # 插入文章 articles_msg['articles'].append(article) article = {} # 返回文章 return articles_msg else: return
可見app的難度並不大,還是和上次使用微信API裏面的和接近,需要用到的幾個全局變量,需要自己定義,如token,如PIC_URL等。程序原理其實就是解析用戶請求,h開頭,則提供幫助菜單,a開頭加數字的,就提供某篇文章,等等,然後提供相應的函數進行處理,這裏面說明起來比較複雜,就以獲取分類文章來講吧:
需要用到分析用戶請求字符串:
# 分類 elif query_str[0] =="c": category = query_str[1:] response_msg = self.get_category_articles(category) if response_msg: return_data = self.pack_news_xml(msg, response_msg) else: response_msg = SORRY return_data = self.pack_text_xml(msg, response_msg) self.write(return_data)
這裏要提供get_category_articles(category)的功能,所以需要在weixin類裏面實現一個這樣的函數:
# 按照分類查找 def get_category_articles(self, category): global MAX_ARTICLE global PIC_URL article_list = Article.get_articles_by_category(category) article_list_length = len(article_list) count = (article_list_length < MAX_ARTICLE) and article_list_length or MAX_ARTICLE if article_list: # 構造圖文消息 articles_msg = {'articles':[]} for i in range(0,count): article = { 'title': article_list[i].slug, 'description':article_list[i].description, 'picUrl':PIC_URL, 'url':article_list[i].absolute_url } # 插入文章 articles_msg['articles'].append(article) article = {} # 返回文章 return articles_msg
很顯然,這裏需要和數據庫模型Article打交道,看看Article是否實現了該功能,很遺憾沒有,那麼我們只好捲起袖子自己幹——擴展Article,所以我們轉戰到modle.py文件裏面了,寫下了如下的代碼:
# 返回一個包含若干篇文章的數組 limit 5 def get_articles_by_category(self, category): sdb._ensure_connected() article_list = sdb.query('SELECT * FROM `sp_posts` WHERE `category` = %s LIMIT 5', str(category)) for i in range(len(article_list)): article_list[i] = post_detail_formate(article_list[i]) return article_list
這裏進行了數據庫查詢,將category參數傳遞進去,選擇category爲參數的5篇文章,打包返回。post_detail_formate是博客系統已經寫好的,我們只要拿來用就行了。在python裏面,寫sql語句要很小心,遇到要傳入參數的,最好是用逗號分割開,而不是使用%來填充參數。特別是使用like的時候,我們往往需要寫這樣的sql語句:
SELECT * FROM `sp_posts` WHERE `category` LIKE '%study%'
但是python裏面又是用%s做參數佔位符的,故而會引起很多不必要的錯誤,比如這裏。總之要安全使用,最好是作爲參數傳遞,python會爲他們與原字符串裏的%等分開。
上傳發布
完成功能後就可以發佈了,雖然還有很多不足的地方,但是測試發現,還是可以使用的。本項目將開源到github中,歡迎使用(需要修改部分的參數,例如博客名稱等),或者交流研究源代碼。實現後的功能是這樣字的:
比如回覆一個a9,將返回第9篇文章;回覆l,列出所有文章。吐槽一下我們宿舍的網絡,差到離譜,我是獲取信息之後才截屏的。
該篇並不是要將實現的所有細節披露出來,披露細節最好的方法就是公開源代碼,接下來會發布到github上面去,只需稍微配置,你就可以擁有一個可以推送到微信的博客了(我不會告訴你wordpress早就出微信插件了)。經過這一番折騰,可以得出一個微信第三方開發的經驗,那就是初步制定好自己的app需要提供什麼功能,然後接着設計一個類,處理各種的請求,將各種處理部分封裝起來,例如按照分類獲取文章,或者獲取文章列表等,然後在這裏面調用數據庫模型裏面的功能來實現。這是MVC的一種便利之處。此外,還要勇於閱讀源代碼和英文文檔,我之前google了很多字符串轉換編碼的方法,沒有成功,但是閱讀了tornado的文檔之後,我恍然大悟。例如之前在django裏面寫這個應用的時候,我們獲取的還是request.raw_post_data,現在改成了self.request.body,不看文檔,想破頭也想不出來。功能實現雖然告一段落,但是這個項目還有很多需要重寫一次,使得它的表現更好,安全性更高。這裏不得不提一下,服務器中採用tornado真的不是一般快~
END
by bibodeng 2013-05-08