新建Python文件:wx_file.py,代码如下

# -*- coding: utf-8 -*-
# @Author : CxiuM
# @Time   : 2023-07-06 10:12
# @Name   : wx_operation.py"""微信群发消息"""import os
import time
import subprocessimport requests
import uiautomation as auto
from copy import deepcopy
from typing import Iterableclass WxOperation:"""微信群发消息的类。...Attributes:----------wx_window: auto.WindowControl微信控制窗口input_edit: wx_window.EditControl聊天界面输入框编辑控制窗口search_edit: wx_window.EditControl搜索输入框编辑控制窗口Methods:-------__goto_chat_box(name):跳转到 指定好友窗口__send_text(*msgs):发送文本。__send_file(*filepath):发送文件get_friend_list(tag, num):可指定tag,获取好友num页的好友数量send_msg(*names, msgs, file_paths)单个或批量发送文本和文件"""def __init__(self):auto.SendKeys(text='{Alt}{Ctrl}z')  # 快捷键唤醒微信self.wx_window = auto.WindowControl(Name='微信', ClassName='WeChatMainWndForPC')assert self.wx_window.Exists(), "窗口不存在"self.input_edit = self.wx_window.EditControl(Name='输入')self.search_edit = self.wx_window.EditControl(Name='搜索')def __goto_chat_box(self, name: str) -> None:"""跳转到指定 name好友的聊天窗口。Args:name(str): 必选参数,好友名称Returns:None"""assert name, "无法跳转到名字为空的聊天窗口"self.wx_window.SendKeys(text='{Ctrl}f', waitTime=0.2)self.wx_window.SendKeys(text='{Ctrl}a', waitTime=0.1)self.wx_window.SendKey(key=auto.SpecialKeyNames['DELETE'])auto.SetClipboardText(text=name)self.wx_window.SendKeys(text='{Ctrl}v', waitTime=0.1)self.wx_window.SendKey(key=auto.SpecialKeyNames['ENTER'], waitTime=0.2)def __send_text(self, *msgs) -> None:"""发送文本.Args:*msgs(Iterable or str): 必选参数,为发送的文本Returns:None"""for msg in msgs:assert msg, "发送的文本内容为空"self.input_edit.SendKeys(text='{Ctrl}a', waitTime=0.1)self.input_edit.SendKey(key=auto.SpecialKeyNames['DELETE'])# self.input_edit.SendKeys(text=msg, waitTime=0.1) # 一个个字符插入,不建议使用该方法# 设置到剪切板再黏贴到输入框auto.SetClipboardText(text=msg)self.input_edit.SendKeys(text='{Ctrl}v', waitTime=0.1)self.wx_window.SendKey(key=auto.SpecialKeyNames['ENTER'], waitTime=0.2)def __send_file(self, *file_paths) -> None:"""发送文件.Args:*file_paths(Iterable or str): 必选参数,为文件的路径Returns:None"""all_path = str()for path in file_paths:full_path = os.path.abspath(path=path)assert os.path.exists(full_path), f"{full_path} 文件路径有误"all_path += "'" + full_path + "',"args = ['powershell', f'Get-Item {all_path[:-1]} | Set-Clipboard']# 去除console 弹窗startupinfo = subprocess.STARTUPINFO()startupinfo.dwFlags = subprocess.CREATE_NEW_CONSOLE | subprocess.STARTF_USESHOWWINDOWstartupinfo.wShowWindow = subprocess.SW_HIDEsubprocess.Popen(args=args, startupinfo=startupinfo)time.sleep(0.5)self.input_edit.SendKeys(text='{Ctrl}v', waitTime=0.2)self.wx_window.SendKey(key=auto.SpecialKeyNames['ENTER'], waitTime=0.2)def get_friend_list(self, tag: str = None, num: int = 10) -> list:"""获取微信好友名称.Args:tag(str): 可选参数,如不指定,则获取所有好友num(int): 可选参数,如不指定,只获取10页好友Returns:list"""def click_tag():"""点击标签"""contacts_management_window.ButtonControl(Name="标签").Click()# 点击 通讯录管理self.wx_window.ButtonControl(Name="通讯录").Click()self.wx_window.ListControl(Name="联系人").ButtonControl(Name="通讯录管理").Click()contacts_management_window = auto.GetForegroundControl()  # 切换到通讯录管理,相当于切换到弹出来的页面# contacts_management_window.ButtonControl(Name='最大化').Click()if tag:click_tag()  # 点击标签contacts_management_window.PaneControl(Name=tag).Click()time.sleep(0.3)click_tag()  # 关闭标签# 获取滑动模式scroll = contacts_management_window.ListControl().GetScrollPattern()# assert scroll, "没有可滑动对象"name_list = list()if not scroll:for name_node in contacts_management_window.ListControl().GetChildren():  # 获取当前页面的 列表 -> 子节点nick_name = name_node.TextControl().Name  # 用户名remark_name = name_node.ButtonControl(foundIndex=2).Name  # 用户备注名,索引1会错位,索引2是备注名,索引3是标签名name_list.append(remark_name if remark_name else nick_name)else:rate: int = int(float(102000 / num))  # 根据输入的num计算滑动的步长for pct in range(0, 102000, rate):  # range不支持float,不导入numpy库,采取迂回这的方式# 每次滑动一点点,-1代表不用滑动scroll.SetScrollPercent(horizontalPercent=-1, verticalPercent=pct / 100000)for name_node in contacts_management_window.ListControl().GetChildren():  # 获取当前页面的 列表 -> 子节点nick_name = name_node.TextControl().Name  # 用户名remark_name = name_node.ButtonControl(foundIndex=2).Name  # 用户备注名,索引1会错位,索引2是备注名,索引3是标签名name_list.append(remark_name if remark_name else nick_name)contacts_management_window.SendKey(auto.SpecialKeyNames['ESC'])  # 结束时候关闭 "通讯录管理" 窗口return list(set(name_list))  # 简单去重,但是存在误判(如果存在同名的好友def get_group_chat_list(self) -> list:"""获取群聊通讯录中的用户名称"""name_list = list()auto.ButtonControl(Name='聊天信息').Click()time.sleep(0.5)chat_members_win = self.wx_window.ListControl(Name='聊天成员')if not chat_members_win.Exists():return list()self.wx_window.ButtonControl(Name='查看更多').Click()for item in chat_members_win.GetChildren():name_list.append(item.ButtonControl().Name)return name_listdef get_chat_records(self, page: int = 1) -> list:"""获取聊天列表的聊天记录.Args:page(int): 可选参数,如不指定,只获取1页聊天记录Returns:list"""chat_records = list()def extract_msg() -> None:all_msgs = self.wx_window.ListControl(Name="消息").GetChildren()for msg_node in all_msgs:msg = msg_node.Nameif not msg:continueif msg_node.PaneControl().Name:chat_records.append({'type': 'Time', 'name': 'System', 'msg': msg_node.PaneControl().Name})continueif msg in ['以下为新消息', '查看更多消息', '该类型文件可能存在安全风险,建议先检查文件安全性后再打开。', '已撤回']:chat_records.append({'type': 'System', 'name': 'System', 'msg': msg})continueif '撤回了一条消息' in msg or '尝试撤回上一条消息' in msg:chat_records.append({'type': 'Other', 'name': ''.join(msg.split(' ')[:-1]), 'msg': msg.split(' ')[-1]})continueif msg in ['发出红包,请在手机上查看', '收到红包,请在手机上查看', '你发送了一次转账收款提醒,请在手机上查看', '你收到了一次转账收款提醒,请在手机上查看']:chat_records.append({'type': 'RedEnvelope', 'name': 'System', 'msg': msg})continueif '领取了你的红包' in msg:_ = msg.split('领取了你的红包')chat_records.append({'type': 'RedEnvelope', 'name': _[0], 'msg': _[1]})continuename = msg_node.ButtonControl(foundIndex=1).Nameif msg == '[文件]':file_name = msg_node.PaneControl().TextControl(foundIndex=1).Namesize = msg_node.PaneControl().TextControl(foundIndex=2).Namechat_records.append({'type': 'File', 'name': name, 'msg': f'size: {size}  ---  file_name: {file_name}'})continueif msg == '微信转账':operation = msg_node.PaneControl().TextControl(foundIndex=2).Nameamount = msg_node.PaneControl().TextControl(foundIndex=3).Namechat_records.append({'type': 'RedEnvelope', 'name': name, 'msg': msg + f'    {operation}    ' + amount})continueif '引用' in msg and '的消息' in msg:chat_records.append({'type': 'Cited', 'name': name, 'msg': msg})continueif msg == '[聊天记录]':if not name:name = msg_node.ButtonControl(foundIndex=2).Namechat_records.append({'type': 'Content', 'name': name, 'msg': msg})for _ in range(page):self.wx_window.WheelUp(wheelTimes=15)extract_msg()return chat_recordsdef send_msg(self, *names, msgs, file_paths, add_remark_name=False) -> None:"""发送消息,可同时发送文本和文件(至少选一项Args:*names (str or Iterable):必选参数,接收消息的好友名称,可以群发,也可以单发msgs (list): 可选参数,发送的文本消息file_paths (Iterable):可选参数,发送的文件路径add_remark_name(bool): 可选参数,是否添加备注名称发送Returns:None"""assert names, "用户名列表为空"assert any([msgs, file_paths]), "没有发送任何消息"assert not isinstance(msgs, str), "文本必须为可迭代且非字符串类型"assert not isinstance(file_paths, str), "文件路径必须为可迭代且非字符串类型"for name in names:self.__goto_chat_box(name=name)if msgs:if add_remark_name:new_msgs = deepcopy(msgs)new_msgs.insert(0, name)self.__send_text(*new_msgs)else:self.__send_text(*msgs)if file_paths:self.__send_file(*file_paths)

再建一个Python文件为:mytest.py,代码如下:

from wx_file import WxOperationwx = WxOperation()
# 发送文本和文件
wx.send_msg('文件传输助手', msgs=["Hello"], file_paths=["F:\Test.txt"])
wx.send_msg('文件传输助手', msgs=["world"], file_paths=["F:\Test.txt"])

但是有时第一次发送不成功,第二次成功。

注意:微信最新版本3.9.5以上代码会发送文件不成功,原因是找不到控件。把电脑版本微信降到上一个版本3.9.2发送成功。

仅用于学习交流。

Python实现微信发送文件实例相关推荐

  1. 使用Python实现微信发送文本消息、图片以及附件

    使用Python实现微信发送文本消息.图片以及附件 因为目前很多微信账号已经不支持网页版的操作了,因此无法使用之前的itchat这一类对微信进行操作. 为此,选择对微信PC端进行开发. 选择的方式比较 ...

  2. UI自动化控制微信发送文件【解决了一个无人回答的难题,Pywin32设置文件到剪切板】

    大家好,我是小小明.前面我在<UI自动化控制PC版微信>该系列文中更新了控制微信发送图片的方法.根据部分群友实际工作的需要,本文将分享如何控制微信发送文件. 专栏链接:https://bl ...

  3. 模拟微信发送文件给好友/群

    JAVA模拟微信发送文件给好友/群 通过google开发者模式抓取https://file2.wx.qq.com/cgi-bin/mmwebwx-bin/webwxuploadmedia?f=json ...

  4. 微信怎么和计算机发送文件格式,用微信怎么发送文件 手机微信发送文件、视频方法图文详解...

    微信火爆程度已经明显超过qq了,那么你知道微信除了飞好友发送图片.视频外还能发送文件,今天小编就为大家分享手机微信发送文件方法图文详解,如何用微信将电脑.手机上的文件发送给好友. 微信怎么添加自定义表 ...

  5. 电脑微信发送文件总显示“文件被占用,无法发送,请重新选择。”

    奇怪的问题 在微信发送文件多次提醒时,查看了文件被占用情况,发现并未被占用, 为了解决疑惑,尝试多方发送 同一个文件,发送钉钉就完全没有问题,发送微信却总提示"文件占用,无法发送" ...

  6. kettle实现企业微信发送文件

    kettle实现企业微信发送文件 用途 通过kettle中嵌入java代码,实现企业微信发送文件. 实现效果 脚本总览 转换属性: 生成记录 用于模拟待上传的文件 Java代码 java代码参考:ht ...

  7. 【银河麒麟桌面操作系统微信发送文件失败-问题分析及解决方案】

    银河麒麟桌面操作系统微信发送文件失败-问题分析及解决方案 1.问题描述 银河麒麟桌面操作系统微信发送文件失败,提示文件为空文件,检查发现文件并非空文件. 2.问题分析排查 2.1微信版本信息:已是最新 ...

  8. 企业微信机器人发送文件实例

    生成 media_id import os from copy import copy import requests from urllib3 import encode_multipart_for ...

  9. PC微信逆向:分析微信发送文件call

    文章目录 发送文件call的结构体参数分析 组合数据call的分析 定位发送文件的call 接上一篇文章,PCXX逆向:发送与接收消息的分析与代码实现:https://blog.csdn.net/qq ...

最新文章

  1. 万字深度好文!视觉-语言(VL)智能:任务、表征学习和大型模型
  2. VC使用CRT调试功能来检测内存泄漏
  3. 在一台服务器绑定多个IP
  4. c++标准库中,含有链表的类list
  5. 【Elasticsearch】Elasticsearch 热点线程 hot_threads
  6. linux mysql 每天备份_Linux下Mysql每天自动备份
  7. paip.python错误解决15
  8. 数据结构实验5-递归
  9. AE遮罩路径扭曲插件BOA Boa for Macv1.3.1破解版
  10. 总结了一份嵌入式相关开源项目、库、资料
  11. 微软小娜关闭服务器,图文详解彻底关闭windows10系统里的小娜(Cortana)语音服务-系统操作与应用 -亦是美网络...
  12. 慢就是快的人生哲理_快和慢人生感悟
  13. 朋友在B站魔力赏抽到的动漫周边,把我看馋了
  14. html竖版古诗,古诗竖版手抄报版面设计图
  15. 计算机学院的入场词,大学校运会入场词
  16. 天琊 V1.0(测试 1125版)
  17. 接口管理平台 - APIPOST和APIfox使用 - PUSDN
  18. 雷电网络(一):厘清雷电网络的原理
  19. 阶跃型多模光纤与渐变型多模光纤有何区别?
  20. elementUI合并单元格

热门文章

  1. Win10和他的老兄弟们
  2. 梆定变量的长度不一致也可能会造成硬解析
  3. 蛮易信你们懂的,不过我最爱武器大师
  4. [转]Nvidia 的Shadow 文章收集
  5. java修饰符总结,关于Java中修饰符的总结(fina除外)
  6. 对于小游戏2048代码具体讲解
  7. 23日广铁加开列车159列 深圳至潮汕方向有少量余票
  8. Python中的 // 和 / 和 % 的用法区别
  9. oracle创建表,序列,触发器,自动生成唯一主键
  10. MASA MAUI Plugin (五)Android 指纹识别