Chengqi
Da ich zuvor einen WeChat-Roboter entworfen habe, um auf Benutzerartikel zu reagieren, ist diese App sehr einfach und erfordert kein besonders tiefgreifendes Design, und meine Idee ist: Wie auch immer, es gibt solche Bei vielen in Python geschriebenen Blog-Systemen muss ich nur den WeChat-Antwortteil implementieren, der darin besteht, die Artikeldaten aus der Datenbank abzurufen und dann den Artikeltitel, die URL, Bilder und andere Informationen in das XML-Format zu packen WeChat-Server, und der Server gibt es an den Benutzer zurück. Und ich fand, dass es viel besser wäre, ein Menü zu haben, etwa eine vollständige App, in der man direkt darauf klicken kann, um einen Artikel anzuzeigen, anstatt starr zu antworten. Ich habe ein von anderen geschriebenes Blog-System verwendet, um es umzuwandeln – saepy-log. Und dieses Blog-System basiert auf dem Tornado-Framework. Ich hatte ursprünglich nicht vor, mich auf Tornado einzulassen, aber ich musste in den sauren Apfel beißen und mich damit befassen . Ich bin auf viele Schwierigkeiten gestoßen und habe beim Schreiben von SQL-Anweisungen und beim Anzeigen von Dokumenten große Fortschritte gemacht.
Bereitstellung und Entwicklung
Bitte beachten Sie im Voraus, dass ich aufgrund aller möglichen Probleme möglicherweise nicht in der Lage bin, dies gemäß diesem Artikel zu tun. Nachdem Sie den Quellcode von Saepy-Log heruntergeladen und gemäß dem hier beschriebenen Vorgang hochgeladen haben, können Sie das Blog-System auf der Sae-Plattform installieren und dann den Code mit SVN mit dem lokalen Arbeitsverzeichnis synchronisieren, und schon ist alles fertig.
Was wir ändern möchten, ist, dass blog.py die Kernfunktion des Blogs und model.py der Schlüssel zum Datenmodell ist. Wir werden die Datenmodellfunktion erweitern, um unsere WeChat-Funktion zu vervollständigen .
Fügen Sie unsere WeChat-Funktionsklasse weixin.py in blog.py hinzu (da es das Tornado-Framework verwendet, unterscheidet sich die Methode geringfügig von der in Django):
Importieren Sie die erforderlichen Pakete
# weixin used package import xml.etree.ElementTree as ET import urllib,urllib2,time,hashlib import tornado.wsgi import tornado.escape
Hauptsächlich XML-Analyse und einige Pakete zur Verarbeitung von Zeichenfolgen. Als nächstes definieren wir den Hauptteil der Weixin-Klasse:
# 添加微信推送帐号 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
Es ist ersichtlich, dass die Schwierigkeit der App nicht groß ist. und es ist immer noch dasselbe wie Als ich die WeChat-API das letzte Mal verwendet habe, musste ich selbst mehrere globale Variablen definieren, z. B. Token, PIC_URL usw. Das Prinzip des Programms besteht darin, Benutzeranfragen zu analysieren. Wenn es mit h beginnt, stellt es ein Hilfemenü bereit. Wenn es mit einer Zahl beginnt, stellt es einen bestimmten Artikel usw. bereit und stellt dann entsprechende Funktionen zur Verarbeitung bereit. Die Erklärung hier ist komplizierter, also holen Sie sich einfach die Klassifizierung. Lassen Sie uns über den Artikel sprechen:
Sie müssen die Benutzeranforderungszeichenfolge analysieren:
# 分类 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)
Die Funktion von get_category_articles(category) benötigt muss hier bereitgestellt werden, daher müssen Sie eine solche Funktion in der Weixin-Klasse implementieren:
# 按照分类查找 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
Natürlich müssen wir uns mit dem Datenbankmodell Article befassen, um zu sehen, ob Article diese Funktion implementiert. Leider ist dies der Fall Nein, also müssen wir die Ärmel hochkrempeln und es selbst tun – Artikel erweitern, also wechseln wir zum Kämpfen. Gehen Sie zur Datei model.py und schreiben Sie den folgenden Code:
# 返回一个包含若干篇文章的数组 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
Hier eine Datenbankabfrage wird ausgeführt, der Kategorieparameter wird übergeben, 5 Artikel mit Kategorie als Parameter werden ausgewählt und das Paket wird zurückgegeben. post_detail_formate ist bereits im Blog-System geschrieben, wir müssen es nur verwenden. In Python müssen Sie beim Schreiben von SQL-Anweisungen sehr vorsichtig sein. Wenn Sie auf Parameter stoßen, die übergeben werden müssen, trennen Sie sie am besten durch Kommas, anstatt % zum Ausfüllen der Parameter zu verwenden. Besonders wenn wir like verwenden, müssen wir oft solche SQL-Anweisungen schreiben:
SELECT * FROM `sp_posts` WHERE `category` LIKE '%study%'
Aber in Python wird es %s verwendet wird als Parameterplatzhalter verwendet und führt daher zu vielen unnötigen Fehlern, wie zum Beispiel hier. Kurz gesagt, um sie sicher zu verwenden, ist es am besten, sie als Parameter zu übergeben. Python trennt sie von % usw. in der Originalzeichenfolge.
Das obige ist der detaillierte Inhalt vonDie öffentliche WeChat-Entwicklungsmethode nutzt den Nachrichtenempfang. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!