介绍:在系列的前两期中,我们分别实现了自动回复和热搜查询功能。由于它们是根据独立内容编写的,因此没有形成定制项目的结构。本期主要是优化项目结构,同时为我们的微信小助手增加短视频下载功能。这篇文章有点长,只关心新功能的同学可以直接拉到新功能介绍。项目结构微信小助手的目标是成为一个多功能的系统,功能要易于扩展。前面两篇文章都是作为独立的功能模块开发的。工程文件树如下:我们看到工程中除了2个功能模块代码和1个日志系统代码外,没有其他文件。目前设置的两个功能模块只能单独运行,并没有形成一个有机的整体,这也给开发新的功能模块带来了困难。因此,为了实现目标,对项目的结构进行优化是非常必要的。接下来我会根据信息的流向一一优化。命令解析器接收到微信信息后,程序首先要做的是分析是否是一条指令。如果是指令,则必须分析该指令将调用哪个功能模块和哪个操作。自动回复模块和热搜查询模块都有类似的操作。以下是截获的代码片段:#自动回复模块ifcmd=='开启自动回复':...elifcmd=='关闭自动回复':...elifcmd.startswith('Setup自动回复,'):...#热搜查询模块ifcmd=='开启热搜':...elifcmd=='关闭热搜':...elifcmd=='热搜':...elifcmd.startswith('热搜,'):...仔细观察,会发现自动回复模块的命令中都包含自动回复四个字。同样,热搜query模块的命令都包含热搜这个词。因此,只要接收到的微信信息中包含这些信息,就认为该信息可能是相应模块的指令,程序会将此信息发送给相应模块进行进一步分析。进一步观察发现,每个模块的指令有很大的相似性:每个模块都包含打开、关闭、设置等指令。不同之处在于查询类型的模块还可能包含默认查询和自定义查询。为了理解耦合性和代码可读性,结合上面的分析,需要创建一个命令解析器cmd_parser.py文件,负责解析信息。这个命令解析器会分析接收到的信息是不是指令,如果是指令,还会分析是什么指令属于哪个模块。代码大致如下:if'autoreply'inmsg:module='auto_reply'ifmsg.startswith('开启自动回复'):cmd='open'elifmsg.startswith('关闭自动回复'):cmd='close'elifmsg.startswith('设置自动回复,'):cmd='set'...elif'HotTopic'inmsg:module='hot_topic'ifmsg.startswith('OpenHotTopic'):cmd='open'elifmsg.startswith('关闭热点'):cmd='close'elifmsg.startswith('设置热点搜索,'):cmd='set'...elifmsg.startswith('热点Search,'):cmd='begin'...elifmsg=='热搜':cmd='default'else:print('notaninstruction!')为了代码的可读性,固定了几个指令为代码中open、close、set,查询指令固定为default和begin。以后只需要根据module和cmd的值,知道哪个模块执行哪个命令即可。命令解析器的另一个作用是解析出命令的参数,在确认是一条指令后传递给命令分发器。命令分发器目前没有特别需要命令分发器,直接在命令解析器中即可实现命令分发。但是长此以往,随着添加的模块越来越多,每次添加一个模块都需要修改很多代码,这无疑增加了维护的难度,也大大降低了代码的可读性。所以新建一个文件夹components,把所有模块的代码都搬到这里。同时添加一条命令distributordistributor.py,代码如下:#在distributor.pyfromcomponents.auto_replyimportauto_replyfromcomponents.hot_topicimporthot_topicdistributor={'auto_reply':auto_reply,'hot_topic':hot_topic,}#在cmd_parser.pyfromcmd_parserimportdistributor...distributor[module](sender,cmd,paras)...这样,添加命令分发器后,命令解析器就变成了一个通用的框架,所有新增的模块都要通过命令解析器首先向命令分发器进行分发。命令执行者一条命令被分发到各个模块,最终在模块内部执行,所以这里的命令执行者其实就是模块本身。由于之前已经对各种命令代码进行了规范,所以只需要按照模块内部对应的代码进行处理即可。开发新模块时也必须遵循此规则,例如:importitchatfromutils.loggerimportloggerdefauto_reply(sender,cmd,paras):logger.info('recieved:sender={},cmd={},paras={}'.format(sender,cmd,str(paras)))if'default'==cmd:...if'open'==cmd:...elif'close'==cmd:...elif'set'==cmd:...全局变量写入配置文件。上面根据信息处理的流程优化了项目结构,下面优化了项目配置。在上一篇文章中,所有需要自定义的内容都是通过全局变量实现的,如下:为了方便后期维护,现在全部改为配置文件。新建一个config.py文件,如下:switches={'auto_reply':False,'hot_topic':True,}settings={'auto_reply':'【自动回复】工作中,请留言!','hot_topic_platform':'','hot_topic_limit':0,}【本文来自微信小宇宙公众号Titus,ID为TitusCosmos,转载请注明!】【为了防止各种爬虫在网络上到处乱爬,故意删除原作者信息,所以在文章中间加上了作者信息,希望读者理解】这样,大家只需要介绍一下它在使用它的地方,它可以使用,例如:#-*-coding=utf8-*-fromconfigimportswitches,settingsimportitchatfromutils.loggerimportloggerdefauto_reply(sender,cmd,paras):logger.info('收到:发件人={},cmd={},paras={}'.format(sender,cmd,str(paras)))if'default'==cmdandswitches['auto_reply']:itchat.send_msg(settings['auto_reply'],sender)returnif'open'==cmd:switches['auto_reply']=Trueitchat.send_msg('自动回复开启!',sender)elif'close'==cmd:switches['auto_reply']=Falseitchat.send_msg('自动回复已关闭!',sender)elif'set'==cmd:settings['auto_reply']=paras[0]itchat.send_msg('自动回复内容有已设置!',发件人)优化结果继续之前的优化,现在将所有工具代码移动到新建的utils文件夹中。最终工程文件树如下:工程一期优化结束。短视频下载功能我们在使用皮皮虾或者抖音的时候,偶尔会遇到真的很想保存的短视频,却发现保存不了。这次会很伤心。为了让大家不再担心,微信小助手特地解决了这个问题。获取分享链接。无论是皮皮虾还是抖音中的短视频,都可以分享到微信,分享的文字中包含视频所在网页的地址。先通过正则表达式解析分享文本中的url:importrepattern=re.compile(r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+')url=re.findall(模式,string)上面的正则表达式专门用来匹配文本中的URL,因为默认分享的文本中只有一个URL,所以url[0]一定是我们要找的URL。获取视频地址,我们以皮皮虾的视频https://h5.pipix.com/s/7TC2Gk/为例,打开谷歌浏览器,打开开发者工具,回车。首先注意地址栏中的网址被重定向到https://h5.pipix.com/item/6809239849397131528?app_id=1319&app=super×tamp=1585401078&user_id=51901622841&carrier_region=cn®ion=cn&language=zh&utm_source=weixin:然后打开X的开发者工具在HR标签页发现一个请求https://h5.pipix.com/bds/webapi/item/detail/?item_id=6809239849397131528&source=share:它的返回值包含非常丰富的信息,视频的地址是在里面找到:我们打开看看这个地址是否真的可以播放视频:就是我们想要的。我们回头观察XHR请求中只有一个未知参数item_id,而这个参数在重定向的URL中已经出现了:这个问题就简单多了,代码如下:importrequestsr=requests.get('https://h5.pipix.com/s/7TC2Gk/')item_id=r.url.split('?')[0].split('/')[-1]r=requests.get('https://h5.pipix.com/bds/webapi/item/detail/?item_id={}&source=share'.format(item_id),headers=headers)pipixia=json.loads(r.text)video_url=pipixia['data']['item']['video']['video_download']['url_list'][0]['url']保存视频有了视频地址,就很容易保存视频了,就因为这是一个视频文件,所以不能像写文本那样使用二进制模式:video=requests.get(video_url).contentwithopen(save_path,'wb')asf:f.write(video)同时,它需要注意的是,微信对发送文件的视频有大小限制,所以需要判断下载的文件是否超过限制,没有的视频必须满足要求才能正常发送。这不是本文的主要内容,这里就不展开了。其他平台的视频下载原理类似。至此就实现了短视频下载功能,按照上半部分的设置即可轻松集成到项目中。后记至此,微信小助手有以下功能,有想法或者建议的同学可以在后台留言一起交流。想要体验的同学可以在后台留言体验,获取联系方式。不管写什么,都希望能和更多的人交流。如果您有任何问题或需求,欢迎随时交流。我所有的项目源码都会放在下面的github仓库,有需要的可以参考,有问题请指正,谢谢!https://github.com/TitusWongCN/【Python开发微信小助手】往期推荐:第一期:【Python开发微信小助手】01自动回复功能第二期:【Python开发微信小助手】02下面热搜查询功能是我的公众号,里面有一些资料,有兴趣可以扫一扫:
