背景宿主有一块树莓派4B开发板(8G内存版),是目前的顶级机型。今年业余时间,除了写Java和架构方面的文章,还在树莓派上折腾了很多好玩的小项目。这里有新的树莓派实战系列文章,分享给广大爱好者和读者。什么是树莓派?RaspberryPi是一款信用卡大小的单板计算机,采用ARM架构CPU,低功耗。它可以7×24运行Linux服务器并连接到各种扩展硬件。所以你可以用你的想象力做很多有趣的事情。你有没有想过拥有一个微信机器人,可以自动回复、与AI聊天、定时发送天气预报、控制摄像头等等。使用树莓派+开源库itchat,可以实现以上需求。为什么强调使用RaspberryPi?因为它可以7×24在线,所以你可以把itchatclient当作一个不间断的服务器。特别提示:本文仅供学习使用,请勿用于任何商业或其他用途。itchat简介itchat是一个开源的微信个人账号界面。不到30行代码,就可以完成一个可以处理所有信息的微信机器人。github地址:https://github.com/littlecode...原理你一定很好奇。其实一句话可以概括:itchat本质上是一个微信网页版客户端,实现了微信网页版的协议/语义,通过http进行通信。具体源码可以在组件包中的文件中找到。下面几点介绍如何实现有趣的功能。功能实现1、自动回复首先要注册一个消息处理函数,即对不同类型的消息进行处理。微信消息分为文字、图片、语音、视频、好友请求等,可以使用itchat的Python语法糖注册不同类型消息的处理函数,有点类似于Java中的注解。如果是短信,可以识别其中的关键字,不同的关键字对应不同的逻辑处理。默认处理单聊消息,也可以处理群聊消息。运行程序后,会弹出一个二维码,扫码登录,然后itchat程序就会运行。另外需要注意的是,给自己发消息是没有用的。解决方法是给文件传输助手filehelper发消息,跟给自己发消息效果一样。下面给出了一个带有评论的演示。importitchat,timefromitchat.contentimport*#注册消息处理函数,回复文字,地图,名片,便签,分享消息类型@itchat.msg_register([TEXT,MAP,CARD,NOTE,SHARING])deftext_reply(msg):#回复以下消息:消息类型,消息内容textitchat.send('%s:%s'%(msg.type,msg.text))#根据不同的关键字回复不同的消息if'Hello'inmsg.text:itchat.send('Hello')elif'bye'inmsg.text:itchat.send('nextchat')#注册消息处理函数,当接收图片,语音,附件,视频时在下载时输入消息content@itchat.msg_register([PICTURE,RECORDING,ATTACHMENT,VIDEO])defdownload_files(msg):#下载文件msg.download(msg.fileName)typeSymbol={PICTURE:'img',VIDEO:'vid',}.get(msg.type,'fil')return'@%s@%s'%(typeSymbol,msg.fileName)#注册消息处理函数,处理好友请求消息@itchat.msg_register(FRIENDS)defadd_friend(msg):#自动地通过对方好友申请msg.user.verify()#然后发送问候msg.user.send('Nicetomeetyou!')#以上都是单聊,加上isGroupChat=True可以处理群聊消息@itchat.msg_register(TEXT,isGroupChat=True)deftext_reply(msg):#只有在群聊时才回复,通常加上这个条件,否则可能会回复群内的所有人Messageifmsg.isAt:#回复的时候,也在对应人的消息处msg.user.send(u'@%s\u2005Ireceived:%s'%(msg.actualNickName,msg.text))#会弹出二维码,扫码andYoucanloginitchat.auto_login(True)#runtheitchatclient,debug=True会打印logitchat.run(True)2.有了AI聊天第一步的基础,要实现AI聊天,需要引入另一个AI本地库,或者在线API,使用在线API更容易。您只需要控制参数传递和解析响应。文字指令的AI对话还是不错的。如果是自由对话,大概率会出现前言与后记不符的情况。#AI聊天调用接口,只有一个文本参数defai_chat(msg):url='http://api.qingyunke.com/api.php?key=free&appid=0&msg=%s'%msgresponse=requests.get(url)returnresponse.json()["content"].replace('{br}','\n')#响应中换行符为{br},替换为微信识别的\n换行符3、定时发送天气预报有步骤2的基础,要获取天气预报信息,只需要在AI聊天请求中发送某个地方的天气,比如:上海天气,北京天气。当然,你也可以通过爬升天气预报网页的字段来获取更详细的天气预报信息,这里不再赘述。要定期发布天气预报,必须解决两个关键问题。一是如何执行定时任务。此处使用Python库apscheduler。当然你也可以写一个Python脚本,然后通过操作系统的crontab在指定的时间执行这个脚本,不过还有一种更优雅的方式是在Python主程序中启动一个定时任务。可以使用Python库apscheduler来实现定时任务调度,类似于Java的ScheduledThreadPool。二是如何向指定的群组发送消息。itchat提供了一个方便的API,可以根据群组名称搜索特定的群组。fromapscheduler.schedulers.blockingimportBlockingScheduler#向群发送天气预报信息defweather_report():msg=ai_chat('上海天气')#获取所有群聊itchat.get_chatrooms(update=True)#根据群名,搜索特定群组chatrooms=itchat.search_chatrooms(name='<在此处更改为实际群组名称>')chatroom=itchat.update_chatroom(chatrooms[0]['UserName'])#向指定群组发送消息itchat.send_msg(msg=msg,toUserName=chatroom['UserName'])if__name__=='__main__':itchat.auto_login(hotReload=True)#itchat启动后是否被屏蔽,这里改成No(默认是yes),相当于itchat在一个新启动的线程中运行,不会阻塞主程序',day_of_week每天早上9点='*',hour=9,minute=0,second=0)scheduler.start()4.控制摄像头,拍照,看视频。家里的树莓派4B有2个USB3.0高速接口和2个USB2.0接口,只需要其中一个接USB摄像头,一般2.0接口就够了,3.0接口留给外接硬盘用磁盘。想要通过摄像头看到自己的家,关键要解决的问题是用什么摄像头软件?你用什么视频聊天软件?您可以使用fswebcam进行拍照,您可以指定或不指定图像分辨率。默认分辨率较低。安装:sudoaptinstallfswebcamimg_file='%d.jpg'%timestamp#调用fswebcam拍照os.system('fswebcam%s'%img_file)#将照片发送到自己的文件传输助手,因为一般发送给自己都会failitchat.send_image(img_file,toUserName='filehelper')发起视频楼主试了几个常见的免费视频聊天软件,都不支持。主要原因是树莓派基于ARMCPU架构,主流软件基本只能在amd64和x86CPU上使用。框架下发行。例如QQ、Skype、网页版的JitsiMeet等都无法发起视频聊天。最后楼主找到了一个完美的解决方案,就是使用linphone:启动视频:在树莓派上安装并打开linphone程序,在手机上安装并打开linphoneapp。这样树莓派上的linphone可以通过微信发起视频通话,手机可以接听电话。挂断视频:需要通过微信机器人主动退出树莓派上的linphone,否则无法继续发起视频。下载最新的linphone可能不起作用,必须使用sudoaptinstalllinphone来安装旧的稳定版本。#先退出linphone(如果当前正在运行),再启动linphoneos.system('linphonecshexit;linphonecshinit-V-c.linphonerc')time.sleep(1)#使用linphone命令行进行视频通话os.完整代码已经上传到github:https://github.com/topcoding/...除了上面提到的几个功能的实现外,还增加了健身签到和睡眠签到的功能。现在,微信机器人的功能已经越来越丰富。#-*-coding:utf-8-*-importitchatimportsqlite3importosimporttimeimportrequestsfromapscheduler.schedulers.blockingimportBlockingSchedulerPUNCH_TYPE_WORKOUT=1PUNCH_TYPE_SLEEP=2ai_chat_switch=TrueAI_CHATROOM_WHITELIST=['<替换成现实的]pudef_db,owner群名称>,timestamp=None):conn=sqlite3.connect('punch-card.db')cursor=conn.cursor()如果时间戳为None:punch_time=(int)(time.time())else:punch_time=timestampcursor.execute("插入punch_card(punch_type,owner,updated_at)values(%d,'%s',%d)"%(punch_type,owner,punch_time))conn.commit()conn.close()@itchat。msg_register(itchat.content.TEXT)deftext_reply(msg):print(msg)timestamp=(int)(time.time())globalai_chat_switchifmsg.text=='健身签到':save_db(PUNCH_TYPE_WORKOUT,msg.User.NickName,timestamp)itchat.send('%s,您好,您于%s健身签到成功'%(msg.User.NickName,time.strftime("%Y-%m-%d%H:%M:%S",time.localtime()),toUserName='filehelper')elifmsg.text=='睡眠签到':save_db(PUNCH_TYPE_SLEEP,msg.User.NickName,timestamp)itchat.send('%s,你好,你在%s登录成功'%(msg.User.NickName,time.strftime("%Y-%m-%d%H:%M:%S",time.localtime())),toUserName='filehelper')elifmsg.text=='拍照':img_file='%d.jpg'%timestampos.system('fswebcam%s'%img_file)itchat.send_image(img_file,toUserName='filehelper')elifmsg.text=='Lookathome':os.system('linphonecshexit;linphonecshinit-V-c.linphonerc')时间。sleep(1)os.system('linphonecshgeneric"call
