持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第3天,点击查看活动详情
简介
当你只想敲代码时,女朋友总是发消息怎么办,那当然是使用一个机器人啦。一个基于python和api的自动敷衍机器人就诞生了。本来微信有很多可以用的库,例如:itchat,但是由于微信的限制,网页微信基本不可以使用了,不过泻玉不行我们还有沁芳,不给我直接用库,我就模拟操作。
开发流程
一、问题分析
当前面临的问题其实很明显,我们需要获取聊天时对方发来的消息,并把消息post给机器人API并得到回复,再将回复消息粘贴到聊天框,并发送。 由此,我们分析出需求为这些:剪贴板,模拟按键,post请求 所以我们使用以下包
import win32gui
import win32con
import win32clipboard as w
import time
import win32api
import requests
二、代码实现
1.得到对方发送来的消息
这一步中我们需要拿到对方发来的消息。
为了提高适应性,我们需要排除聊天框在不同位置的情况。所有默认操作为,win32库操作窗口全屏。
通过测试我们可以确定新消息的位置,我们就将鼠标移上去。
此时我们已经可以确定将鼠标移动到的位置
下一步将确定如何选中文本
微信只需要右键就会选中全部文本,这为我们实现需求提供了便捷。
为了提高准确率,我们不采用点击复制的方式,而是关闭菜单,模拟按键。
选择再左键点击下关闭菜单,然后使用模拟Ctrl+C的快捷键复制
win32api.SetCursorPos([90,680])#移动鼠标位置
#执行右单键击
win32api.mouse_event(win32con.MOUSEEVENTF_RIGHTUP | win32con.MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0)
time.sleep(2)#延时
#执行左单键击
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP | win32con.MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0)
time.sleep(2)
# 以下为“CTRL+C”组合键,回车发送,(方法一)
win32api.keybd_event(17, 0, 0, 0) # ctrl键位码是17
win32api.keybd_event(67, 0, 0, 0) # v键位码是67
win32api.keybd_event(67, 0, win32con.KEYEVENTF_KEYUP, 0) # 释放按键
win32api.keybd_event(17, 0, win32con.KEYEVENTF_KEYUP, 0)
通过以上操作,已经成功获得了发送的文字
2.从剪贴板获取信息并发送
这一步很简单,直接使用代码表示
w.OpenClipboard() #打开剪贴板
msg = w.GetClipboardData()#获取信息
#关闭剪贴板
w.CloseClipboard()
url = 'http://api.tianapi.com/txapi/robot/index?key=xxxxx&question={}'.format(msg) #机器人API地址
html = requests.get(url)
returnmsg = html.json()["newslist"][0]['reply']
#打开剪贴板
w.OpenClipboard()
#清空剪贴板
w.EmptyClipboard()
#设置剪贴板内容
w.SetClipboardData(win32con.CF_UNICODETEXT, returnmsg)
#获取剪贴板内容
data = w.GetClipboardData()
#关闭剪贴板
w.CloseClipboard()
这一部同时发送了消息给api,从api获取机器人的回复,并将机器人的回复放到剪贴板中
3.发送消息
经过测试,微信的信息框在获取信息结束后是失焦状态,所以我们需要移动鼠标并点击信息框,才可以输入信息。
在输入状态下,使用模拟Ctrl+V的按键操作,粘贴机器人的回复 并使用模拟回车,发送消息。
win32api.SetCursorPos([100,780]) #移动鼠标
#执行左单键击,若需要双击则延时几毫秒再点击一次即可
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP | win32con.MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0)
# 以下为“CTRL+V”组合键,回车发送,(方法一)
win32api.keybd_event(17, 0, 0, 0) # ctrl键位码是17
win32api.keybd_event(86, 0, 0, 0) # v键位码是86
win32api.keybd_event(86, 0, win32con.KEYEVENTF_KEYUP, 0) # 释放按键
win32api.keybd_event(17, 0, win32con.KEYEVENTF_KEYUP, 0)
time.sleep(1) # 缓冲时间
win32api.keybd_event(13, 0, 0, 0) # Rutrn键位码是13,按下
win32api.keybd_event(13, 0, win32con.KEYEVENTF_KEYUP, 0) # 释放按键
4.补充
程序获取窗口句柄的代码
name = 'XXX'#聊天窗口的名字
handle = win32gui.FindWindow(None, name)
总结
总体来说,该项目是一个简单的功能实现,为了规避限制采取了模拟的方式,当然这样并不靠谱,会占用电脑以及充满不确定性,但是解决问题的过程还是非常不错的,本文撰写时间较早,目前可能有新方法了,所以还是需要结合前沿技术解决才是最好的。
本文首发于隔壁平台,重新撰写后发布。