作者:JiawuZhang
出品:JiawuLab(ID:jiawulab)实验记录系列是JiawuLab原创栏目,通过真实项目的操作,记录整个实验过程。
旨在通过一步步过程,无基础的朋友都能直接上手。
大家好,我是JiawuZhang,本次实验记录的项目是——微信公众号开发。
我的公众号开发的第四篇文章,如果您没看过前三篇文章,这里是传送门:
JiawuZhang:我的公众号开发(第一步)简单功能实现zhuanlan.zhihu.comJiawuZhang:我的公众号开发(第二步)智能AI对接zhuanlan.zhihu.comJiawuZhang:我的公众号开发(第三步)数据库实现关键字回复zhuanlan.zhihu.com
希望您多多关注。
上期回顾
首先对智能AI机器人进行优化,让机器人更聪明。
然后通过pymysql库,对MySQL数据库进行了基础操作学习。
最后通过改造代码,实现了关键字回复的功能并上线。
细心的你,可能会发现,粉丝每发一条信息,都会查询一次数据库,有些信息根本不需要查询,同时对数据库压力太大,
而且最后截图演示中,关键字回复的不只是文字,是像卡片一样的样式,
本期,我将进行代码再改造,让数据库轻松点,同时引入一个新的消息回复类型-图文回复。
本期知识点
1、图文消息回复
2、数据库轻松点
3、日志功能
关键字回复体验
上期我们使用数据库实现了关键字回复的功能,不知道你有没有试过,好不好用
反正我使用下来非常好用,可以在服务器不重新启动的情况下,增加多组新的关键字
比如原先我设置的关键字,只有下面两组,有朋友也测试过
然后我昨天将前三篇文章也加入进去,现在是这样的
只需要回复第一步、第二步、第三步,就能得到下面的回复
是不是很方便呢,一旦有新的关键字需要增加,都可以马上增加,你也可以上手试试看。
图文消息回复
大家从上面图片可看到,我用到的是一种卡片型的回复,不再是纯文字的
这就是本期将要学到的一种新的类型——图文消息回复
官方文档中也有提及这种类型,如下截图:
消息管理-被动回复用户消息-回复图文消息,有对该类型进行表述
从截图可以看到,图文消息体,我们单独拿出来研究一下
12345678
1
消息体分析:
MsgType的消息类型为news,一种新的类型,还记得前面我们分析消息回复原理讲到的吗?
上面表格中写明了,消息体的各项参数说明,我们从中可以得到如下结论
1、ArticleCount,我们是发送文本、图文,所以只能回复1条图文消息,所以我们只能设置为1
2、发送图文消息,我们需要有四条内容,分别是Title、Description、PicUrl、Url,对应着标题、描述、图片地址、链接
所以需要按照上期文章——数据库实现关键字回复——来改造数据库
综合上述,本期需要解决两个问题,才能实现图文消息回复,分别是新类型news和数据库改造,我们来实现吧
新回复类型news
当收到粉丝发来的一条文本关键字,服务器根据关键字返回类型为news的图文消息给粉丝
对于接收程序receive来说,还是文本消息,不用改造
我们需要改造的是回复程序reply,增加新类型news,如下
...
# 上面代码不变,只需新增下面代码
class NewsMsg(Msg):
def __init__(self, toUserName, fromUserName, content):
self.__dict = dict()
self.__dict['ToUserName'] = toUserName
self.__dict['FromUserName'] = fromUserName
self.__dict['CreateTime'] = int(time.time())
self.__dict['title'] = content[0]
self.__dict['description'] = content[1]
self.__dict['picurl'] = content[2]
self.__dict['url'] = content[3]
def send(self):
XmlForm = """
{CreateTime}
1
"""
return XmlForm.format(**self.__dict)
这里我说明一点:回复程序从Handle程序传递参数content,这是一个包含标题、描述、图片地址、链接的元组
所以需要在参数content的创建中,也按照这个顺序来,否则会出现错误
完成了回复程序reply的改造后,我们来对Handle程序中POST方法进行改造
...
if recMsg.MsgType == 'text':
key = recMsg.Content.decode('utf-8')
if mydb.mycontent(key):
content = mydb.mycontent(key) # 关键字回复
replyMsg = reply.NewsMsg(toUser, fromUser, content) #只改了这里
return replyMsg.send()
else:
content = robot(key) # 正常聊天
replyMsg = reply.TextMsg(toUser, fromUser, content)
return replyMsg.send()
...
本次更改很简单,只需要将备注点前面的TextMsg改为NewsMsg即可
这样就能调用图文消息回复,不过有个问题产生,mydb文件中mycontent()函数返回的并不是包含标题、描述、图片地址、链接的元组
所以我们需要对mydb中的mycontent()函数进行改造
数据库改造
改造mycontent()函数前,需要改造数据库,
原先我们创建的数据表中,只有keyword和reply两项内容
而图文回复需要五项内容,keyword、Title、Description、PicUrl、Url,所以我们需要重新创建一个数据表
创建数据表还记得吗,我这里将SQL语句给出来
# 创建新数据表newcontent,包含图文回复五项内容
sql = """
CREATE TABLE newcontent (
id INT auto_increment PRIMARY KEY ,
keyword VARCHAR(50) NOT NULL ,
title VARCHAR(100) NOT NULL ,
description VARCHAR(200) NOT NULL ,
picurl VARCHAR(200) NOT NULL ,
url VARCHAR(200) NOT NULL
)ENGINE=InnoDB DEFAULT CHARSET=utf8; #注意:charset='utf8' 不能写成utf-8
"""
后续操作按照上期文章介绍的执行即可,你可以动手试试
数据表有了,添加数据的两种方式,
一是代码添加,如下
# SQL插入语句
sql = 'insert into newcontent(keyword, title, description, picurl, url) values(%s, %s, %s, %s, %s);'
# 三组关键字回复
data = [
('关键字', '标题', '描述', '图片地址', '链接'),
('关键字2', '标题2', '描述2', '图片地址2', '链接2'),
('关键字3', '标题3', '描述3', '图片地址3', '链接3'),
]
# 拼接并执行sql语句
cursor.executemany(sql, data)
二是使用mySQL可视化软件直接添加,如下图:
两种方法各有优势,你可以选择自己合适的方式进行
关于图片地址,我的方法是,先将图片上传到素材中,再将图片地址复制出来
数据表有了,添加数据的方式也说了,我们进行代码改造mycontent()函数
def mycontent(key):
conn = pool.connection()
cursor = conn.cursor()
cursor.execute('select title,description,picurl,url from newcontent where keyword=%s', key)
data = cursor.fetchone() # 将数据库的数据(元组嵌套)赋值给datas
cursor.close()
conn.close()
return data
前面提到的,按照'标题'、'描述'、'图片地址'、'链接'的顺序返回data数据
保存文件后,重新启动服务器,就可以实现图文消息回复了,你也动手试试看,是不是很有成就感。
让数据库轻松点
上期结尾处,我们提到,粉丝每发一条消息,都要查询一次数据库,而且本期又改造成了图文回复
查询数据库的次数和耗时,都有所增加,那我们应该怎么减轻数据库的压力呢?
这里我的方法是,将数据表中关键字全部提出来,然后先用粉丝的消息与关键字列表做判断
如果在关键字列表中,再从数据库中将'标题'、'描述'、'图片地址'、'链接'等信息都取出来,发给粉丝
当然,如果你有更好的办法,自己进行实现,也可以分享在留言处,让大家都学习一下
这里按照我的方法进行,在mydb文件中新建一个mykeyword函数
def mykeyword():
conn = pool.connection()
cursor = conn.cursor()
# 提取所有keyword
cursor.execute('select keyword from newcontent')
data = cursor.fetchall()
cursor.close()
conn.close()
# data是元组嵌套,转换为列表
key = [j for i in data for j in i]
return key
然后将mykeyword函数加到Handle类中
...
if recMsg.MsgType == 'text':
key = recMsg.Content.decode('utf-8')
if key in mydb.mykeyword():
content = mydb.mycontent(key) # 关键字回复
replyMsg = reply.NewsMsg(toUser, fromUser, content)
return replyMsg.send()
else:
content = robot(key) # 正常聊天
replyMsg = reply.TextMsg(toUser, fromUser, content)
return replyMsg.send()
...
保存文件后,重启服务器就好了,这样数据库会轻松点,同时因为有数据池的存在,多人同时消息回复也能轻松解决。
日志功能
前面三期,我们每保存完改造后的代码,都是使用的python3 main.py 80进行服务器启动
这会造成一个问题,当退出后,服务就不再继续了,而且没有日志,不方便查看问题
所以本期,我们只用一条命令,就可以解决上述问题
我们在服务器命令行界面,先cd到main.py所在的文件夹
输入这条命令:
nohup python3 main.py 80 > wx.log 2>&1 &
服务就启动了,并且常驻在后台运行,我们退出服务器,程序也会一直运行
然后将服务器的日志保存在wx.log文件中
我们打开wx.log文件看看,命令是:
vi wx.log
就能查看到wx.log中的日志信息了
里面会根据你在程序中设置的print信息,以及各IP访问你的服务器的信息,你可以试试
现在日志功能有了,而且服务在后台静默运行,我们只要多增加相应的关键字回复就好。
如果你有不明白的,请关注公众号:JiawuLab,给我留言,我会一一解答。
下一步预告
本期我们新增图文消息回复,并且让数据库更轻松,最后也拥有了日志功能。
现在已经拥有了很完整的功能,只需要日后根据运营情况,进行完善相关功能就行。
那下一步做什么呢?还记得我们最开始选择的开发基础配置吗?
对了,明文模式,也就是说,所有粉丝发来的信息和我们回复的消息,都是明文的
如果有人进行数据包拦截,不用解密,就能全部看到,这样很危险。
所以下一步,我们将实现最重要,也是必须为安全着想的功能——消息加密。
本期记录到此结束,感谢您的阅读。如果您喜欢这期文章,请点赞,支持一下。
欢迎您关注公众号:JiawuLab,提前体验完整功能,或者给我留言,说说你遇到的问题,我们一起探讨。
文中资源:
推荐阅读