本程序能做什么:
在PC版的微信界面,模拟鼠标键盘动作,随机对好友列表里的某些好友发送文本消息和图片
(因为本人以前没有WINDOW UI的编程经验,所以这几天对WIN32UI接口基本是边学边搜边用,导致程序里面导入的UI包资源有功能上的冗余,比如WIN32API和pyautogui代码都有混合重叠,目的只是实现自己需要的功能,也就不要太计较了)
# 第一步需要手动登录PC版微信
# 因为显示器分辨率的不同,程序文件的各个常量需要手工设置一下,否则鼠标可能无法准确点击微信功能界面
# 开始运行本Python程序,会自动把微信最大化并最靠前,然后依次对好友列表内的好友发送预置的文本信息和图片
#在INI文件里可以设置需要发送的好友列表的页数,需要发送的文本信息,以及图片所在文件夹的路径(图片文件夹下面的所有图片随机发送)
INI文件内容:
[DataLoading]
friendListPages = 1
imageDir =
sendMsg = 您好,请关注一下!
import win32gui, win32api, win32con
import win32clipboard as clipboard
import pyperclip
import pyautogui
import time
import random
import configparser
from PIL import Image
from io import BytesIO
import os
# 要定位的窗口信息常量
WINDOW_NAME = '微信'
WINDOW_CLASS = 'WeChatMainWndForPC'
# 联系人按钮入口鼠标位置
FRIENDS_IN_XPOS = 30
FREENDS_IN_YPOS = 140
# 联系人详细列表鼠标X坐标位置
PEOPLE_XPOS = 200
# 好友详细列表居中X坐标位置
PEOPLE_LIST_MID_XPOS = 180
# 联系人详细列表鼠标Y坐标起始位置
PEOPLE_LIST_START_YPOS = 70
# 每个联系人列表的高度
PEOPLE_ONE_HEIGHT = 60
# 微信在屏幕中最低位置标记
SCREEN_LOWEST_POS = 730
# 右键向上弹出菜单的最低屏幕位置
RMENU_UPDOWN_POS= 653
# 点击好友详细列表右侧滚动条向下的位置
FRIENDS_LIST_SCROLL_XPOS = 308
FRIENDS_LIST_SCROLL_YPOS = SCREEN_LOWEST_POS - 2
# 点击当前的位置
current_friend_y_pos = 0
# 好友列表页面计数
FRIEND_LIST_MAXPAGES = 70
friend_list_pageCount = 1
# 发送好友消息计数
friend_sendMsgCount = 0
# 图片目录
IMAGE_DIR = 'D:\\PythonProjects\\Hello\\GoodsPics\\'
# 自定图片目录下的所有图片的名称列表
ALL_IMAGES_LIST = []
# 发送给好友的文本信息
SEND_MSG = ''
# 每次发送给好友的图片数量
SEND_IMAGE_TIMES = 1
# 发送文本消息的分隔符
MSG_SPLIT_FLAG = '%%'
send_msg_list = []
def _ini():
global FRIEND_LIST_MAXPAGES
global IMAGE_DIR
global ALL_IMAGES_LIST
global SEND_MSG
global SEND_IMAGE_TIMES
global MSG_SPLIT_FLAG
global send_msg_list
# 从配置文件里读取初始值
configure = configparser.ConfigParser()
configure.read('configure.ini')
section = configure['DataLoading']
if int(section['friendListPages']) > 0:FRIEND_LIST_MAXPAGES = int(section['friendListPages'])
if len(section['imageDir']) > 0:IMAGE_DIR = section['imageDir']
if len(section['sendMsg']) > 0:SEND_MSG = section['sendMsg']
if int(section['sendImageTimes']) > 0:SEND_IMAGE_TIMES = int(section['sendImageTimes'])
if len(section['msgSplitFlag']) > 0:MSG_SPLIT_FLAG = section['msgSplitFlag']
# 将要发送的文本消息列表,随机挑选消息
send_msg_list = SEND_MSG.split(MSG_SPLIT_FLAG)
ALL_IMAGES_LIST = _getAllImagesPathList()
#
def getLocalImageData(path):
img = Image.open(path)
output = BytesIO() # BytesIO实现了在内存中读写bytes
# output = StringIO() # StringsIO实现了在内存中读写bytes
img.convert("RGB").save(output, "BMP") #以RGB模式保存图像
data = output.getvalue()[14:]
output.close()
img.close()
return data
# 把图片数据内容塞入剪贴板
def setImageDataToClipboard(data):
clipboard.OpenClipboard()
clipboard.EmptyClipboard()
clipboard.SetClipboardData(win32con.CF_DIB, data)
clipboard.CloseClipboard()
# 清空剪贴板
def clearClipboard():
clipboard.OpenClipboard()
clipboard.EmptyClipboard()
clipboard.CloseClipboard()
# 按照提供的图片路径装载图片到剪切板
def loadImageToclipboard(path):
setImageDataToClipboard(getLocalImageData(path))
# 复制文字到剪贴板
def _loadTextToClipboard():
pyperclip.copy(send_msg_list[random.randint(0, len(send_msg_list) - 1)])
# 得到指定图片目录下面的所有图片列表
def _getAllImagesPathList():
return os.listdir(IMAGE_DIR)
def _loadSendMsg():
# 首先清空剪贴板
clearClipboard()
# 装载将要发送的文本信息到剪贴板
_loadTextToClipboard()
_clipboardSendMsg()
for i in range(1, SEND_IMAGE_TIMES + 1):
# 随机装载图片到剪贴板
loadImageToclipboard(IMAGE_DIR +
ALL_IMAGES_LIST[random.randint(0, len(ALL_IMAGES_LIST) - 1)])
_clipboardSendMsg()
_sleepLongTime()
i += 1
# 把粘贴板里的内容,粘帖到微信里,然后发送出去
def _clipboardSendMsg():
# 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)
# 粘帖到微信
pyautogui.hotkey('ctrl', 'v')
_sleepLongTime()
# 发送消息动作
def _sendMsgAction():
win32api.keybd_event(13, 0, 0, 0) # Enter的键位码是13
win32api.keybd_event(13, 0, win32con.KEYEVENTF_KEYUP, 0)
_sleepLongTime()
# 为了给界面切换足够的时间,需要适当的间隔时间
def _sleepShortTime():
time.sleep(0.5)
def _sleepLongTime():
time.sleep(1)
# 找到窗口,让窗口位置靠最前,并最大化
def _controlWindow():
# 获取窗口句柄
hw = win32gui.FindWindow(None, WINDOW_NAME)
hw = win32gui.FindWindow(WINDOW_CLASS, None)
if hw <= 0:return -1
# 让窗口在最前面
win32gui.SetForegroundWindow(hw)
# 让窗口最大化
win32gui.ShowWindow(hw, win32con.SW_MAXIMIZE)
return 1
# 点击联系人按钮
def _clickFriendsList():
# 将鼠标移动到坐标处
pyautogui.moveTo(FRIENDS_IN_XPOS, FREENDS_IN_YPOS, duration = 0)
# 左点击,准备进入联系人列表界面
pyautogui.click()
_sleepLongTime()
# 在好友列表滚动鼠标,换下一批好友
def _scrollNextFriendList():
# 将鼠标移动到坐标处
pyautogui.moveTo(PEOPLE_LIST_MID_XPOS, PEOPLE_LIST_START_YPOS, duration = 0)
# 鼠标滚轮滚动好友列表
pyautogui.scroll(-2200)
_sleepLongTime()
return 1
# 右键点击联系人,然后发送粘贴板里的消息
def _rbClickSendMessage(xPos, yPos):
global friend_sendMsgCount
# 将鼠标移动到坐标处
pyautogui.moveTo(xPos, yPos, duration = 0)
_sleepShortTime()
# 右键点击出弹出菜单,点击发消息选项
pyautogui.rightClick()
_sleepShortTime()
if yPos <= RMENU_UPDOWN_POS:
pyautogui.moveTo(xPos + 15, yPos + 15, duration = 0)
_sleepShortTime()
# 左键点击菜单,准备进入联系人列表界面
pyautogui.click()
else:
pyautogui.moveTo(xPos + 15, yPos - 100, duration = 0)
_sleepShortTime()
# 左键点击菜单,准备进入联系人列表界面
pyautogui.click()
_sleepShortTime()
# 装载要发送的消息到剪切板,然后复制到微信里
_loadSendMsg()
friend_sendMsgCount += 1
# 发送消息出去
_sendMsgAction()
def _random_friend_yPos():
return random.randint(1,
int((SCREEN_LOWEST_POS - PEOPLE_LIST_START_YPOS) / PEOPLE_ONE_HEIGHT)) * PEOPLE_ONE_HEIGHT
# 判断是不是好友列表是不是最后一页,为程序结束最准备
def _isLastPage():
return False
if __name__ =='__main__':
# 首先找到窗口
if _controlWindow() == -1:exit()
_sleepLongTime()
# 初始化
_ini()
while 1:
# 点击联系人按钮,准备进入联系人列表
_clickFriendsList()
# 判断当前点击位置如果不在有效范围内,设置初始值。
if current_friend_y_pos == 0:
current_friend_y_pos = PEOPLE_LIST_START_YPOS - PEOPLE_ONE_HEIGHT
current_friend_y_pos += _random_friend_yPos()
if current_friend_y_pos > SCREEN_LOWEST_POS:
current_friend_y_pos = 0
# 在好友列表滚动鼠标,换下一批好友
_scrollNextFriendList()
print('已完成' + str(friend_list_pageCount) + '页')
# 如果是最后一页,结束程序
if _isLastPage():exit()
friend_list_pageCount += 1
if friend_list_pageCount > FRIEND_LIST_MAXPAGES:
print('共发送给' + str(friend_sendMsgCount) + '个好友')
print('执行完毕!')
exit()
continue
# 右键点击好友,然后发送粘贴板里的消息
_rbClickSendMessage(PEOPLE_XPOS, current_friend_y_pos)