成为海王的日子——我做了一个微信自动聊天的工具
一直幻想着能够成为一个海王,于是做了一个微信自动聊天的工具。
测试微信版本:wechat 3.9.12.17
采用技术:
- Bmob后端云(AI对话和存储需要自动聊天的人和prompt)
- uiautomation
- pyautogui
开发语言:
- python,conda环境下运行
最终的效果大家可以看B站:http://www.bilibili.com/video/BV1yK…
一、获取微信对话内容
这里采用了网上的一些开源项目进行修改,写了一个自己的WeChat控制类,采用的是uiautomation和pyautogui组件进行UI的控制,模拟人的操作。
WeChat控制类的内容比较多,为了方便阅读,这里只呈现一部分,有需要的朋友可以联系我获取。
class WeChat:
def __init__(self, path, locale="zh-CN"):
# 微信打开路径
self.path = path
# 用于复制内容到剪切板
self.app = QApplication([])
self.lc = WeChatLocale(locale)
# 鼠标移动到控件上
def move(self,element):
x, y = element.GetPosition()
auto.SetCursorPos(x, y)
# 鼠标快速点击控件
def click(self,element):
x, y = element.GetPosition()
auto.Click(x, y)
# 鼠标右键点击控件
def right_click(self,element):
x, y = element.GetPosition()
auto.RightClick(x, y)
# 鼠标快速点击两下控件
def double_click(self,element):
x, y = element.GetPosition()
auto.SetCursorPos(x, y)
element.DoubleClick()
# 打开微信客户端
def open_wechat(self):
subprocess.Popen(self.path)
# 搜寻微信客户端控件
def get_wechat(self):
return auto.WindowControl(Depth=1, Name=self.lc.weixin)
# 防止微信长时间挂机导致掉线
def prevent_offline(self):
self.open_wechat()
self.get_wechat()
search_box = auto.EditControl(Depth=8, Name=self.lc.search)
self.click(search_box)
# 搜索指定用户
def get_contact(self, name):
self.open_wechat()
self.get_wechat()
search_box = auto.EditControl(Depth=8, Name=self.lc.search)
self.click(search_box)
pyperclip.copy(name)
auto.SendKeys("{Ctrl}v")
# 等待客户端搜索联系人
time.sleep(0.3)
search_box.SendKeys("{enter}")
# 鼠标移动到发送按钮处点击发送消息
def press_enter(self):
# 获取发送按钮
send_button = auto.ButtonControl(Depth=15, Name=self.lc.send)
self.click(send_button)
# 检测微信发新消息的用户
def check_new_user(self):
self.open_wechat()
self.get_wechat()
users = []
# 获取左侧聊天按钮
chat_btn = auto.ButtonControl(Name=self.lc.chats)
self.double_click(chat_btn)
# 持续点击聊天按钮,直到获取完全部新消息
item = auto.ListItemControl(Depth=10)
prev_name = item.ButtonControl().Name
while True:
# 判断该联系人是否有新消息
pane_control = item.PaneControl()
if len(pane_control.GetChildren()) == 3:
users.append(item.ButtonControl().Name)
self.click(item)
# 跳转到下一个新消息
self.double_click(chat_btn)
item = auto.ListItemControl(Depth=10)
# 已经完成遍历,退出循环
if prev_name == item.ButtonControl().Name:
break
prev_name = item.ButtonControl().Name
return users
二、获取需要自动聊天的人和对应的prompt
这部分信息我存储在Bmob后端云上面,对应的表结构(表名为:autochat
,创建的字段为:name
、prompt
)和测试的内容如下:
获取信息的时候,我采用了子线程
的方式,每隔300秒获取一次新的需要自动对话的微信和对应的prompt,代码如下:
# Bmob对象
bmob = Bmob(config['bmob_appid'], config['bmob_secret'])
# 存储从Bmob后端云获取到的自动对话的微信名和对应的prompt
name_prompts = {}
# 从Bmob后端云获取自动聊天的微信名和prompt
def get_user_prompt():
users = bmob.findObjects('autochat')
name_prompts.clear()
for user in users:
name_prompts[user.name] = user.prompt
# 每隔5分钟获取一次要自动聊天微信名称和对应的prompt
def run_with_interval():
while True:
get_user_prompt()
time.sleep(300)
if __name__ == "__main__":
t = threading.Thread(target=run_with_interval)
t.start()
三、组装对话上下文和自动对话
这里主要用到了WeChat
类的获取新对话人名字
、获取某个人历史聊天记录
的方法,和Bmob后端云的AI
功能,具体代码如下:
# 执行自动聊天功能
def main():
wechat = WeChat(path=config['wechat_path'])
# 创建一个锁
lock = threading.Lock()
while True:
try:
comtypes.CoInitialize()
# 确保微信操作的线程安全
with lock:
wechat.click(auto.ButtonControl(Name=wechat.lc.facorites))
users = wechat.check_new_user()
if len(users) <= 0:
time.sleep(5)
print("暂时没有新消息")
continue
for user in users:
if user not in name_prompts.keys():
time.sleep(5)
print(f"{user}不在需要自动问答的名单上")
continue
else:
# 获取聊天记录,30这个数字可以调整,越大的话,AI会越了解你,但消耗的token也越多
msgList = wechat.get_dialogs(user, 30)
if len(msgList) <= 0:
continue
# 组装上下文对话记录
ai = []
ai.append({"content": name_prompts[user], "role": "system"})
for msg in msgList:
chatmsg = msg[2].replace('[动画表情]','')
if chatmsg=='':
continue
if msg[1] == user:
ai.append({"content": chatmsg, "role": "user"})
else:
ai.append({"content": chatmsg, "role": "assistant"})
bmob.connectAI()
to = bmob.chat2(ai)
bmob.closeAI()
print('ai:'+to)
if to != "":
wechat.send_msg(user, to)
except Exception as e:
print(e)
作者:小小琪_Bmob后端云
来源:juejin.cn/post/7422401535215435788
来源:juejin.cn/post/7422401535215435788