在前面《UI自動化輕松解決微信手工群發訊息的煩惱》一文中,我演示了如何使用uiautomation控制微信發送文本訊息,
前幾天又有群友詢問:

雖然之前覺得太簡單懶得做,但今天又想起這個問題,考慮到很多網友不知道如何實作,所以今天再簡單演示一下,
uiautomation控制微信發送圖片
其實原理非常簡單,之前無非是將需要發送的文本復制到剪切板再粘貼,那么其實對于圖片也一樣,我們只需要將需要發送的圖片放入剪切板即可,其他地方邏輯都一樣,
那么如何將圖片放入剪切板呢?
uiautomation已經提供了SetClipboardBitmap方法,實作代碼如下:
from uiautomation.uiautomation import Bitmap
auto.SetClipboardBitmap(Bitmap.FromFile(path))
之前我們發送圖片訊息的完整代碼為:
import time
import uiautomation as auto
wechatWindow = auto.WindowControl(
searchDepth=1, Name="微信", ClassName='WeChatMainWndForPC')
wechatWindow.SetActive()
search = wechatWindow.EditControl(Name='搜索')
edit = wechatWindow.EditControl(Name='輸入')
messages = wechatWindow.ListControl(Name='訊息')
sendButton = wechatWindow.ButtonControl(Name='發送(S)')
def send2name(name, txt, wait_time=0.1):
search.Click()
auto.SetClipboardText(name)
edit.SendKeys('{Ctrl}v')
# 等待微信索引搜索跟上
time.sleep(wait_time)
search.SendKeys("{Enter}")
auto.SetClipboardText(txt)
edit.SendKeys('{Ctrl}v')
sendButton.Click()
name = "小小明"
txt = "小小明你好,收到這條訊息說明你的程式已經成功---來自自動化測驗程式"
send2name(name, txt)
下面我們改造到支持圖片發送:
import time
import uiautomation as auto
from uiautomation.uiautomation import Bitmap
wechatWindow = auto.WindowControl(
searchDepth=1, Name="微信", ClassName='WeChatMainWndForPC')
wechatWindow.SetActive()
search = wechatWindow.EditControl(Name='搜索')
edit = wechatWindow.EditControl(Name='輸入')
messages = wechatWindow.ListControl(Name='訊息')
sendButton = wechatWindow.ButtonControl(Name='發送(S)')
def selectSessionFromName(name, wait_time=0.1):
search.Click()
auto.SetClipboardText(name)
edit.SendKeys('{Ctrl}v')
# 等待微信索引搜索跟上
time.sleep(wait_time)
search.SendKeys("{Enter}")
def send_msg(content, msg_type=1):
if msg_type:
auto.SetClipboardText(content)
else:
auto.SetClipboardBitmap(Bitmap.FromFile(content))
edit.SendKeys('{Ctrl}v')
sendButton.Click()
測驗一下切換并發送文本訊息和圖片訊息:
name = "小小明"
selectSessionFromName(name)
content = "小小明你好,收到這條訊息說明你的程式已經成功---來自自動化測驗程式"
send_msg(content)
content = r"C:\Users\ASUS\Pictures\avatar.png"
send_msg(content, msg_type=0)

這樣,我們就完成了圖片訊息的發送,
圖片訊息的轉發
上文中,已經實作了轉發當前最后一條文本訊息的功能,但是假如最后一條訊息是圖片時,之前的方法就會報錯退出,這到底是什么情況呢?我們看看圖片與文本訊息節點的異同:

為了使代碼更加通用,我們必須分析出更通用的規律,發下圖可以發現規律:

每一條訊息由一個面板的三個子節點組成,首尾兩個節點的內容互斥,首節點有按鈕表示非本人發送的訊息,尾節點有按鈕表示自己發送的訊息,中間節點是一個包括了訊息內容的面板,
那么可以將之前的代碼由message.EditControl().RightClick()修改為message.GetFirstChildControl().GetChildren()[1].RightClick()
另外之前的代碼可以排除最后一條訊息為拍一拍的情況,但實際上最后一潭訓有可能是撤回,也需要排除,在向前尋找節點時可能碰到時間,也需要排除掉,
對于轉發訊息,我們基本只需要轉發自己發送的訊息,下面的代碼將再當前視窗中找到,自己發送的最后一條訊息,當然需要保證自己最后發送的訊息在可視范圍內,只要是向檔案傳輸助手發送的訊息都不會存在這個問題,
改造之前的訊息發送代碼,最終如下:
def relay2users(users, max_n=9, wait_time=0.1):
message = messages.GetLastChildControl()
while True:
nodes = message.GetFirstChildControl().GetChildren()
if nodes and nodes[2].ControlTypeName == "ButtonControl":
break
message = message.GetPreviousSiblingControl()
nodes[1].RightClick()
menu = wechatWindow.MenuControl()
menu_items = menu.GetLastChildControl().GetFirstChildControl().GetChildren()
for menu_item in menu_items:
if menu_item.ControlTypeName != "MenuItemControl":
continue
if menu_item.Name == "轉發":
menu_item.Click()
break
send2ps = wechatWindow.WindowControl(Name="轉發給", ClassName='SelectContactWnd')
receiver = send2ps.EditControl(Name="搜索")
sendB2 = send2ps.ButtonControl(Name='發送')
items = send2ps.ListControl()
for i in range(0, len(users), max_n):
users_split = users[i:i+max_n]
for user in users_split:
receiver.Click()
auto.SetClipboardText(user)
receiver.SendKeys('{Ctrl}v')
# 等待UI組件的渲染變化
time.sleep(wait_time)
items.ButtonControl().Click()
receiver.GetParentControl().GetNextSiblingControl().Click()
sendB2.Click()
下面測驗一下轉發這條圖片訊息到指定會話名稱:

users = ["檔案傳輸助手", "小小明", "Playmarker",
"資料分析與商業化設計", "道財Gdc", "云朵君MrCloudData"]
relay2users(users)

可以看到這樣就實作了圖片訊息的轉發,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/301287.html
標籤:python
