cluic / wxauto

Windows版本微信客户端(非网页版)自动化,可实现简单的发送、接收微信消息,简单微信机器人
MIT License
2.88k stars 465 forks source link

GetListenMessage的Bug-有时候会把以前的message也收进来 #255

Open zzstarfish opened 3 months ago

zzstarfish commented 3 months ago

微信版本:3.9.11.19 代码就是类似简单机器人中的监听某个群的消息,打印出来。有的时候运行正常,拿到的信息就是群里新出现的消息。有的时候拿到的信息,一上来会出现昨天和前天发的消息。具体测试发现(测过好几次,测试结果可重复):如果在程序启动之前,手动打开了监听的群的聊天窗口,那么拿到的消息就是新出现的消息(运行正确)。如果程序启动之前,监听的群的聊天窗口没有打开,而是程序运行时通过程序自己打开的,那么拿到的消息就是包括昨天和前天发送的消息。 代码和打印出来的信息如下。 具体的代码:

listen_list = [
    '我有一个家'
]

for i in listen_list:
    wx.AddListenChat(who=i)
wait = 15
while True:
    msgs = wx.GetListenMessage()
    for chat in msgs:
        one_msgs = msgs.get(chat)  # 获取消息内容

        for msg in one_msgs:
            if msg.type == 'sys':
                print(f'【系统消息】{msg.content}')

            elif msg.type == 'friend':

                sender = msg.sender  # 这里可以将msg.sender改为msg.sender_remark,获取备注名
                print(f'{sender.rjust(20)}:{msg.content}')

            elif msg.type == 'self':
                print(f'{msg.sender.ljust(20)}:{msg.content}')

            elif msg.type == 'time':
                print(f'\n【时间消息】{msg.time}')

            elif msg.type == 'recall':
                print(f'【撤回消息】{msg.content}')
    time.sleep(wait)

运行异常时控制台打印出来的信息,当前时间是2024-7-18。可以看到7-16日的信息都被打印出来了。

D:\AIdemo\WeChatRPA\venv\Scripts\python.exe D:\AIdemo\WeChatRPA\demo.py 初始化成功,获取到已登录窗口:{我的微信昵称}

【时间消息】2024-07-16 19:21 老猫:夏天太热,多喝水 Self :OK 老猫:你这回复还挺快

【时间消息】2024-07-16 20:54 老爸:[强][强] 老爸:档次最高的小范

【时间消息】2024-07-16 23:34 老猫:[视频号]

【时间消息】2024-07-16 23:58 老猫:[视频号] 老猫:[视频号]

【时间消息】2024-07-17 6:57 老猫:[视频号]

【时间消息】2024-07-17 9:22 老猫:[图片] 老猫:[图片]

【时间消息】2024-07-17 10:15 老猫:[视频号]

2413567 commented 3 months ago

我也遇到了同样的问题

zzstarfish commented 3 months ago

一步一步debug(测试条件是在程序运行之前不打开监听的群窗口),有时候会出错,有时候运行正常。也不是每一次都出错。 目前发现一些端倪。 下面这句 msg = chat.GetNewMessage(savepic=chat.savepic, savefile=chat.savefile, savevoice=chat.savevoice) 进入chat.GetNewMessage一步一步调式结果都是对的,只拿了最新的消息(大概1-2条消息),然后返回结果之后 msg的值突然就不对了,结果是一个38条消息的列表,细看这里面包含了过去的消息。 我现在怀疑是变量污染?有其他的变量叫做msg导致的? 我对python没那么熟悉,不了解变量污染是个什么概念。有python熟悉的告诉我一下。 现象倒是符合,bug出现不那么稳定,有一定随机性。

` def GetListenMessage(self, who=None): """获取监听对象的新消息

    Args:
        who (str, optional): 要获取消息的聊天对象名,如果为None,则获取所有监听对象的消息

    Returns:
        str|dict: 如果
    """
    if who and who in self.listen:
        chat = self.listen[who]
        msg = chat.GetNewMessage(savepic=chat.savepic, savefile=chat.savefile, savevoice=chat.savevoice)
        return msg
    msgs = {}
    for who in self.listen:
        chat = self.listen[who]
        msg = chat.GetNewMessage(savepic=chat.savepic, savefile=chat.savefile, savevoice=chat.savevoice)
        if msg:
            msgs[chat] = msg
    return msgs`
zzstarfish commented 2 months ago

上面的答案误导大家了,刚才把这个问题搞清楚,解决了。 先说结果: 如果程序启动之前,监听的群的聊天窗口没有打开,而是程序运行时通过程序自己打开的,这样监听消息时就会出现前面的历史消息,原因在于,刚刚打开这个窗口,窗口还没有展示完全,self.C_MsgList.GetChildren得到的元素列表的长度不稳定,有时是5,有时是10,有时是11(理论上我那个聊天窗口应该得到的长度是43),这样存入的self.usedmsgid就会比预期少很多。如此一来,再拿到消息比对usedmsgid时就会把历史消息误判为新消息。 解决方法: 在首次的 msgs = wx.GetListenMessage()之前暂停几秒,等窗口加载完全就可以了。 完整代码

在listen_list = [
    '我有一个家'
]

for i in listen_list:
    wx.AddListenChat(who=i)
wait = 15

time.sleep(20) #就是这里,等一会,大家自己试一下,估计再少一些也没问题

while True:
    msgs = wx.GetListenMessage()
    for chat in msgs:
        one_msgs = msgs.get(chat)  # 获取消息内容

        for msg in one_msgs:
            if msg.type == 'sys':
                print(f'【系统消息】{msg.content}')

            elif msg.type == 'friend':

                sender = msg.sender  # 这里可以将msg.sender改为msg.sender_remark,获取备注名
                print(f'{sender.rjust(20)}:{msg.content}')

            elif msg.type == 'self':
                print(f'{msg.sender.ljust(20)}:{msg.content}')

            elif msg.type == 'time':
                print(f'\n【时间消息】{msg.time}')

            elif msg.type == 'recall':
                print(f'【撤回消息】{msg.content}')
    time.sleep(wait)

加了一些print语句追踪,可以看一下效果,注意_self.CMsgList.GetChildren的长度 D:\AIdemo\WeChatRPA\venv\Scripts\python.exe D:\AIdemo\WeChatRPA\demo.py 初始化成功,获取到已登录窗口:{微信昵称} 将要执行ChatWind的init构造函数中的self.GetAllMessage()语句 进入ChatWnd类GetAllMessage函数 chatWnd类GetAllMessage函数的MsgItems-即 self.C_MsgList.GetChildren的长度是12 chatWnd类GetAllMessage函数的msgs的长度是12 刚刚执行过ChatWind的init构造函数中的self.GetAllMessage()语句 等20秒,窗口加载完全 进入WeChat类的GetListenMessage函数 进入ChatWnd类的GetNewMessage函数 ChatWnd类的GetNewMessage函数中self.usedmsgid为空 进入ChatWnd类GetAllMessage函数 chatWnd类GetAllMessage函数的MsgItems-即self.C_MsgList.GetChildren的长度是43 chatWnd类GetAllMessage函数的msgs的长度是42 ChatWnd类的GetNewMessage函数中self.usedmsgid初始化完毕,长度为42,即将退出该函数 WeChat类中的GetListenMessage函数中的the_new_msgs的长度是0

lkeai2007 commented 1 month ago

上面的答案误导大家了,刚才把这个问题搞清楚,解决了。 先说结果: 如果程序启动之前,监听的群的聊天窗口没有打开,而是程序运行时通过程序自己打开的,这样监听消息时就会出现前面的历史消息,原因在于,刚刚打开这个窗口,窗口还没有展示完全,self.C_MsgList.GetChildren得到的元素列表的长度不稳定,有时是5,有时是10,有时是11(理论上我那个聊天窗口应该得到的长度是43),这样存入的self.usedmsgid就会比预期少很多。如此一来,再拿到消息比对usedmsgid时就会把历史消息误判为新消息。 解决方法: 在首次的 msgs = wx.GetListenMessage()之前暂停几秒,等窗口加载完全就可以了。 完整代码

在listen_list = [
    '我有一个家'
]

for i in listen_list:
    wx.AddListenChat(who=i)
wait = 15

time.sleep(20) #就是这里,等一会,大家自己试一下,估计再少一些也没问题

while True:
    msgs = wx.GetListenMessage()
    for chat in msgs:
        one_msgs = msgs.get(chat)  # 获取消息内容

        for msg in one_msgs:
            if msg.type == 'sys':
                print(f'【系统消息】{msg.content}')

            elif msg.type == 'friend':

                sender = msg.sender  # 这里可以将msg.sender改为msg.sender_remark,获取备注名
                print(f'{sender.rjust(20)}:{msg.content}')

            elif msg.type == 'self':
                print(f'{msg.sender.ljust(20)}:{msg.content}')

            elif msg.type == 'time':
                print(f'\n【时间消息】{msg.time}')

            elif msg.type == 'recall':
                print(f'【撤回消息】{msg.content}')
    time.sleep(wait)

加了一些print语句追踪,可以看一下效果,注意_self.CMsgList.GetChildren的长度 D:\AIdemo\WeChatRPA\venv\Scripts\python.exe D:\AIdemo\WeChatRPA\demo.py 初始化成功,获取到已登录窗口:{微信昵称} 将要执行ChatWind的init构造函数中的self.GetAllMessage()语句 进入ChatWnd类GetAllMessage函数 chatWnd类GetAllMessage函数的MsgItems-即 self.C_MsgList.GetChildren的长度是12 chatWnd类GetAllMessage函数的msgs的长度是12 刚刚执行过ChatWind的init构造函数中的self.GetAllMessage()语句 等20秒,窗口加载完全 进入WeChat类的GetListenMessage函数 进入ChatWnd类的GetNewMessage函数 ChatWnd类的GetNewMessage函数中self.usedmsgid为空 进入ChatWnd类GetAllMessage函数 chatWnd类GetAllMessage函数的MsgItems-即self.C_MsgList.GetChildren的长度是43 chatWnd类GetAllMessage函数的msgs的长度是42 ChatWnd类的GetNewMessage函数中self.usedmsgid初始化完毕,长度为42,即将退出该函数 WeChat类中的GetListenMessage函数中的the_new_msgs的长度是0

还有个问题不知道你发现没,长时间运行的时候会出现旧的消息被重复监听到,比如我今天11.45突然又收到一个9.40多的消息,不知道是不是旧消息的runtimeid变更了,导致被当作新的消息重新监听到

zzstarfish commented 1 month ago

我还没注意到这个现象,你连续运行了多久?中间没有中断过?

---- 回复的原邮件 ---- | 发件人 | @.> | | 日期 | 2024年08月22日 16:03 | | 收件人 | @.> | | 抄送至 | @.>@.> | | 主题 | Re: [cluic/wxauto] GetListenMessage的Bug-有时候会把以前的message也收进来 (Issue #255) |

上面的答案误导大家了,刚才把这个问题搞清楚,解决了。 先说结果: 如果程序启动之前,监听的群的聊天窗口没有打开,而是程序运行时通过程序自己打开的,这样监听消息时就会出现前面的历史消息,原因在于,刚刚打开这个窗口,窗口还没有展示完全,self.C_MsgList.GetChildren得到的元素列表的长度不稳定,有时是5,有时是10,有时是11(理论上我那个聊天窗口应该得到的长度是43),这样存入的self.usedmsgid就会比预期少很多。如此一来,再拿到消息比对usedmsgid时就会把历史消息误判为新消息。 解决方法: 在首次的 msgs = wx.GetListenMessage()之前暂停几秒,等窗口加载完全就可以了。 完整代码

在listen_list = [ '我有一个家' ]

for i in listen_list: wx.AddListenChat(who=i) wait = 15

time.sleep(20) #就是这里,等一会,大家自己试一下,估计再少一些也没问题

while True: msgs = wx.GetListenMessage() for chat in msgs: one_msgs = msgs.get(chat) # 获取消息内容

    for msg in one_msgs:
        if msg.type == 'sys':
            print(f'【系统消息】{msg.content}')

        elif msg.type == 'friend':

            sender = msg.sender  # 这里可以将msg.sender改为msg.sender_remark,获取备注名
            print(f'{sender.rjust(20)}:{msg.content}')

        elif msg.type == 'self':
            print(f'{msg.sender.ljust(20)}:{msg.content}')

        elif msg.type == 'time':
            print(f'\n【时间消息】{msg.time}')

        elif msg.type == 'recall':
            print(f'【撤回消息】{msg.content}')
time.sleep(wait)

加了一些print语句追踪,可以看一下效果,注意_self.CMsgList.GetChildren的长度 D:\AIdemo\WeChatRPA\venv\Scripts\python.exe D:\AIdemo\WeChatRPA\demo.py 初始化成功,获取到已登录窗口:{微信昵称} 将要执行ChatWind的init构造函数中的self.GetAllMessage()语句 进入ChatWnd类GetAllMessage函数 chatWnd类GetAllMessage函数的MsgItems-即 self.C_MsgList.GetChildren的长度是12 chatWnd类GetAllMessage函数的msgs的长度是12 刚刚执行过ChatWind的init构造函数中的self.GetAllMessage()语句 等20秒,窗口加载完全 进入WeChat类的GetListenMessage函数 进入ChatWnd类的GetNewMessage函数 ChatWnd类的GetNewMessage函数中self.usedmsgid为空 进入ChatWnd类GetAllMessage函数 chatWnd类GetAllMessage函数的MsgItems-即self.C_MsgList.GetChildren的长度是43 chatWnd类GetAllMessage函数的msgs的长度是42 ChatWnd类的GetNewMessage函数中self.usedmsgid初始化完毕,长度为42,即将退出该函数 WeChat类中的GetListenMessage函数中的the_new_msgs的长度是0

还有个问题不知道你发现没,长时间运行的时候会出现旧的消息被重复监听到,比如我今天11.45突然又收到一个9.40多的消息,不知道是不是旧消息的runtimeid变更了,导致被当作新的消息重新监听到

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you are subscribed to this thread.Message ID: @.***>

lkeai2007 commented 1 month ago

一个多星期,很多人都有这个情况,不知道是不是我设置的监听1s一个循环太快了

发自我的iPhone

------------------ 原始邮件 ------------------ 发件人: zzstarfish @.> 发送时间: 2024年8月22日 20:06 收件人: cluic/wxauto @.> 抄送: Mr.Cat @.>, Comment @.> 主题: Re: [cluic/wxauto] GetListenMessage的Bug-有时候会把以前的message也收进来 (Issue #255)

我还没注意到这个现象,你连续运行了多久?中间没有中断过?

---- 回复的原邮件 ---- | 发件人 | @.> | | 日期 | 2024年08月22日 16:03 | | 收件人 | @.> | | 抄送至 | @.>@.> | | 主题 | Re: [cluic/wxauto] GetListenMessage的Bug-有时候会把以前的message也收进来 (Issue #255) |

上面的答案误导大家了,刚才把这个问题搞清楚,解决了。 先说结果: 如果程序启动之前,监听的群的聊天窗口没有打开,而是程序运行时通过程序自己打开的,这样监听消息时就会出现前面的历史消息,原因在于,刚刚打开这个窗口,窗口还没有展示完全,self.C_MsgList.GetChildren得到的元素列表的长度不稳定,有时是5,有时是10,有时是11(理论上我那个聊天窗口应该得到的长度是43),这样存入的self.usedmsgid就会比预期少很多。如此一来,再拿到消息比对usedmsgid时就会把历史消息误判为新消息。 解决方法: 在首次的 msgs = wx.GetListenMessage()之前暂停几秒,等窗口加载完全就可以了。 完整代码

在listen_list = [ '我有一个家' ]

for i in listen_list: wx.AddListenChat(who=i) wait = 15

time.sleep(20) #就是这里,等一会,大家自己试一下,估计再少一些也没问题

while True: msgs = wx.GetListenMessage() for chat in msgs: one_msgs = msgs.get(chat) # 获取消息内容

     for msg in one_msgs:
         if msg.type == 'sys':
             print(f'【系统消息】{msg.content}')

         elif msg.type == 'friend':

             sender = msg.sender  # 这里可以将msg.sender改为msg.sender_remark,获取备注名
             print(f'{sender.rjust(20)}:{msg.content}')

         elif msg.type == 'self':
             print(f'{msg.sender.ljust(20)}:{msg.content}')

         elif msg.type == 'time':
             print(f'\n【时间消息】{msg.time}')

         elif msg.type == 'recall':
             print(f'【撤回消息】{msg.content}')
 time.sleep(wait)

加了一些print语句追踪,可以看一下效果,注意_self.CMsgList.GetChildren的长度 D:\AIdemo\WeChatRPA\venv\Scripts\python.exe D:\AIdemo\WeChatRPA\demo.py 初始化成功,获取到已登录窗口:{微信昵称} 将要执行ChatWind的init构造函数中的self.GetAllMessage()语句 进入ChatWnd类GetAllMessage函数 chatWnd类GetAllMessage函数的MsgItems-即 self.C_MsgList.GetChildren的长度是12 chatWnd类GetAllMessage函数的msgs的长度是12 刚刚执行过ChatWind的init构造函数中的self.GetAllMessage()语句 等20秒,窗口加载完全 进入WeChat类的GetListenMessage函数 进入ChatWnd类的GetNewMessage函数 ChatWnd类的GetNewMessage函数中self.usedmsgid为空 进入ChatWnd类GetAllMessage函数 chatWnd类GetAllMessage函数的MsgItems-即self.C_MsgList.GetChildren的长度是43 chatWnd类GetAllMessage函数的msgs的长度是42 ChatWnd类的GetNewMessage函数中self.usedmsgid初始化完毕,长度为42,即将退出该函数 WeChat类中的GetListenMessage函数中的the_new_msgs的长度是0

还有个问题不知道你发现没,长时间运行的时候会出现旧的消息被重复监听到,比如我今天11.45突然又收到一个9.40多的消息,不知道是不是旧消息的runtimeid变更了,导致被当作新的消息重新监听到

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you are subscribed to this thread.Message ID: @.> — Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you commented.Message ID: @.>

zzstarfish commented 1 month ago

哎,我确实不知道唉,没有跑过这么久,我最长也就跑过几个小时…我一般是大概15秒监听一次

---- 回复的原邮件 ---- | 发件人 | @.> | | 日期 | 2024年08月22日 20:11 | | 收件人 | @.> | | 抄送至 | @.>@.> | | 主题 | Re: [cluic/wxauto] GetListenMessage的Bug-有时候会把以前的message也收进来 (Issue #255) |

一个多星期,很多人都有这个情况,不知道是不是我设置的监听1s一个循环太快了

发自我的iPhone

------------------ 原始邮件 ------------------ 发件人: zzstarfish @.> 发送时间: 2024年8月22日 20:06 收件人: cluic/wxauto @.> 抄送: Mr.Cat @.>, Comment @.> 主题: Re: [cluic/wxauto] GetListenMessage的Bug-有时候会把以前的message也收进来 (Issue #255)

我还没注意到这个现象,你连续运行了多久?中间没有中断过?

---- 回复的原邮件 ---- | 发件人 | @.> | | 日期 | 2024年08月22日 16:03 | | 收件人 | @.> | | 抄送至 | @.>@.> | | 主题 | Re: [cluic/wxauto] GetListenMessage的Bug-有时候会把以前的message也收进来 (Issue #255) |

上面的答案误导大家了,刚才把这个问题搞清楚,解决了。 先说结果: 如果程序启动之前,监听的群的聊天窗口没有打开,而是程序运行时通过程序自己打开的,这样监听消息时就会出现前面的历史消息,原因在于,刚刚打开这个窗口,窗口还没有展示完全,self.C_MsgList.GetChildren得到的元素列表的长度不稳定,有时是5,有时是10,有时是11(理论上我那个聊天窗口应该得到的长度是43),这样存入的self.usedmsgid就会比预期少很多。如此一来,再拿到消息比对usedmsgid时就会把历史消息误判为新消息。 解决方法: 在首次的 msgs = wx.GetListenMessage()之前暂停几秒,等窗口加载完全就可以了。 完整代码

在listen_list = [ '我有一个家' ]

for i in listen_list: wx.AddListenChat(who=i) wait = 15

time.sleep(20) #就是这里,等一会,大家自己试一下,估计再少一些也没问题

while True: msgs = wx.GetListenMessage() for chat in msgs: one_msgs = msgs.get(chat) # 获取消息内容

for msg in one_msgs: if msg.type == 'sys': print(f'【系统消息】{msg.content}')

elif msg.type == 'friend':

sender = msg.sender # 这里可以将msg.sender改为msg.sender_remark,获取备注名 print(f'{sender.rjust(20)}:{msg.content}')

elif msg.type == 'self': print(f'{msg.sender.ljust(20)}:{msg.content}')

elif msg.type == 'time': print(f'\n【时间消息】{msg.time}')

elif msg.type == 'recall': print(f'【撤回消息】{msg.content}') time.sleep(wait)

加了一些print语句追踪,可以看一下效果,注意_self.CMsgList.GetChildren的长度 D:\AIdemo\WeChatRPA\venv\Scripts\python.exe D:\AIdemo\WeChatRPA\demo.py 初始化成功,获取到已登录窗口:{微信昵称} 将要执行ChatWind的init构造函数中的self.GetAllMessage()语句 进入ChatWnd类GetAllMessage函数 chatWnd类GetAllMessage函数的MsgItems-即 self.C_MsgList.GetChildren的长度是12 chatWnd类GetAllMessage函数的msgs的长度是12 刚刚执行过ChatWind的init构造函数中的self.GetAllMessage()语句 等20秒,窗口加载完全 进入WeChat类的GetListenMessage函数 进入ChatWnd类的GetNewMessage函数 ChatWnd类的GetNewMessage函数中self.usedmsgid为空 进入ChatWnd类GetAllMessage函数 chatWnd类GetAllMessage函数的MsgItems-即self.C_MsgList.GetChildren的长度是43 chatWnd类GetAllMessage函数的msgs的长度是42 ChatWnd类的GetNewMessage函数中self.usedmsgid初始化完毕,长度为42,即将退出该函数 WeChat类中的GetListenMessage函数中的the_new_msgs的长度是0

还有个问题不知道你发现没,长时间运行的时候会出现旧的消息被重复监听到,比如我今天11.45突然又收到一个9.40多的消息,不知道是不是旧消息的runtimeid变更了,导致被当作新的消息重新监听到

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you are subscribed to this thread.Message ID: @.> — Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you commented.Message ID: @.>

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you are subscribed to this thread.Message ID: @.***>

lkeai2007 commented 1 month ago

15s,那不是消息发多了就收不全了

发自我的iPhone

------------------ 原始邮件 ------------------ 发件人: zzstarfish @.> 发送时间: 2024年8月22日 22:38 收件人: cluic/wxauto @.> 抄送: Mr.Cat @.>, Comment @.> 主题: Re: [cluic/wxauto] GetListenMessage的Bug-有时候会把以前的message也收进来 (Issue #255)

哎,我确实不知道唉,没有跑过这么久,我最长也就跑过几个小时…我一般是大概15秒监听一次

---- 回复的原邮件 ---- | 发件人 | @.> | | 日期 | 2024年08月22日 20:11 | | 收件人 | @.> | | 抄送至 | @.>@.> | | 主题 | Re: [cluic/wxauto] GetListenMessage的Bug-有时候会把以前的message也收进来 (Issue #255) |

一个多星期,很多人都有这个情况,不知道是不是我设置的监听1s一个循环太快了

发自我的iPhone

------------------ 原始邮件 ------------------ 发件人: zzstarfish @.> 发送时间: 2024年8月22日 20:06 收件人: cluic/wxauto @.> 抄送: Mr.Cat @.>, Comment @.> 主题: Re: [cluic/wxauto] GetListenMessage的Bug-有时候会把以前的message也收进来 (Issue #255)

我还没注意到这个现象,你连续运行了多久?中间没有中断过?

---- 回复的原邮件 ---- | 发件人 | @.> | | 日期 | 2024年08月22日 16:03 | | 收件人 | @.> | | 抄送至 | @.>@.> | | 主题 | Re: [cluic/wxauto] GetListenMessage的Bug-有时候会把以前的message也收进来 (Issue #255) |

上面的答案误导大家了,刚才把这个问题搞清楚,解决了。 先说结果: 如果程序启动之前,监听的群的聊天窗口没有打开,而是程序运行时通过程序自己打开的,这样监听消息时就会出现前面的历史消息,原因在于,刚刚打开这个窗口,窗口还没有展示完全,self.C_MsgList.GetChildren得到的元素列表的长度不稳定,有时是5,有时是10,有时是11(理论上我那个聊天窗口应该得到的长度是43),这样存入的self.usedmsgid就会比预期少很多。如此一来,再拿到消息比对usedmsgid时就会把历史消息误判为新消息。 解决方法: 在首次的 msgs = wx.GetListenMessage()之前暂停几秒,等窗口加载完全就可以了。 完整代码

在listen_list = [ '我有一个家' ]

for i in listen_list: wx.AddListenChat(who=i) wait = 15

time.sleep(20) #就是这里,等一会,大家自己试一下,估计再少一些也没问题

while True: msgs = wx.GetListenMessage() for chat in msgs: one_msgs = msgs.get(chat) # 获取消息内容

for msg in one_msgs: if msg.type == 'sys': print(f'【系统消息】{msg.content}')

elif msg.type == 'friend':

sender = msg.sender # 这里可以将msg.sender改为msg.sender_remark,获取备注名 print(f'{sender.rjust(20)}:{msg.content}')

elif msg.type == 'self': print(f'{msg.sender.ljust(20)}:{msg.content}')

elif msg.type == 'time': print(f'\n【时间消息】{msg.time}')

elif msg.type == 'recall': print(f'【撤回消息】{msg.content}') time.sleep(wait)

加了一些print语句追踪,可以看一下效果,注意_self.CMsgList.GetChildren的长度 D:\AIdemo\WeChatRPA\venv\Scripts\python.exe D:\AIdemo\WeChatRPA\demo.py 初始化成功,获取到已登录窗口:{微信昵称} 将要执行ChatWind的init构造函数中的self.GetAllMessage()语句 进入ChatWnd类GetAllMessage函数 chatWnd类GetAllMessage函数的MsgItems-即 self.C_MsgList.GetChildren的长度是12 chatWnd类GetAllMessage函数的msgs的长度是12 刚刚执行过ChatWind的init构造函数中的self.GetAllMessage()语句 等20秒,窗口加载完全 进入WeChat类的GetListenMessage函数 进入ChatWnd类的GetNewMessage函数 ChatWnd类的GetNewMessage函数中self.usedmsgid为空 进入ChatWnd类GetAllMessage函数 chatWnd类GetAllMessage函数的MsgItems-即self.C_MsgList.GetChildren的长度是43 chatWnd类GetAllMessage函数的msgs的长度是42 ChatWnd类的GetNewMessage函数中self.usedmsgid初始化完毕,长度为42,即将退出该函数 WeChat类中的GetListenMessage函数中的the_new_msgs的长度是0

还有个问题不知道你发现没,长时间运行的时候会出现旧的消息被重复监听到,比如我今天11.45突然又收到一个9.40多的消息,不知道是不是旧消息的runtimeid变更了,导致被当作新的消息重新监听到

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you are subscribed to this thread.Message ID: @.> — Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you commented.Message ID: @.>

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you are subscribed to this thread.Message ID: @.> — Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you commented.Message ID: @.>

zzstarfish commented 1 month ago

会吗?就是每15秒收一下,一下子收好多条…不过我那个也确实消息发得很少

---- 回复的原邮件 ---- | 发件人 | @.> | | 日期 | 2024年08月22日 23:54 | | 收件人 | @.> | | 抄送至 | @.>@.> | | 主题 | Re: [cluic/wxauto] GetListenMessage的Bug-有时候会把以前的message也收进来 (Issue #255) |

15s,那不是消息发多了就收不全了

发自我的iPhone

------------------ 原始邮件 ------------------ 发件人: zzstarfish @.> 发送时间: 2024年8月22日 22:38 收件人: cluic/wxauto @.> 抄送: Mr.Cat @.>, Comment @.> 主题: Re: [cluic/wxauto] GetListenMessage的Bug-有时候会把以前的message也收进来 (Issue #255)

哎,我确实不知道唉,没有跑过这么久,我最长也就跑过几个小时…我一般是大概15秒监听一次

---- 回复的原邮件 ---- | 发件人 | @.> | | 日期 | 2024年08月22日 20:11 | | 收件人 | @.> | | 抄送至 | @.>@.> | | 主题 | Re: [cluic/wxauto] GetListenMessage的Bug-有时候会把以前的message也收进来 (Issue #255) |

一个多星期,很多人都有这个情况,不知道是不是我设置的监听1s一个循环太快了

发自我的iPhone

------------------ 原始邮件 ------------------ 发件人: zzstarfish @.> 发送时间: 2024年8月22日 20:06 收件人: cluic/wxauto @.> 抄送: Mr.Cat @.>, Comment @.> 主题: Re: [cluic/wxauto] GetListenMessage的Bug-有时候会把以前的message也收进来 (Issue #255)

我还没注意到这个现象,你连续运行了多久?中间没有中断过?

---- 回复的原邮件 ---- | 发件人 | @.> | | 日期 | 2024年08月22日 16:03 | | 收件人 | @.> | | 抄送至 | @.>@.> | | 主题 | Re: [cluic/wxauto] GetListenMessage的Bug-有时候会把以前的message也收进来 (Issue #255) |

上面的答案误导大家了,刚才把这个问题搞清楚,解决了。 先说结果: 如果程序启动之前,监听的群的聊天窗口没有打开,而是程序运行时通过程序自己打开的,这样监听消息时就会出现前面的历史消息,原因在于,刚刚打开这个窗口,窗口还没有展示完全,self.C_MsgList.GetChildren得到的元素列表的长度不稳定,有时是5,有时是10,有时是11(理论上我那个聊天窗口应该得到的长度是43),这样存入的self.usedmsgid就会比预期少很多。如此一来,再拿到消息比对usedmsgid时就会把历史消息误判为新消息。 解决方法: 在首次的 msgs = wx.GetListenMessage()之前暂停几秒,等窗口加载完全就可以了。 完整代码

在listen_list = [ '我有一个家' ]

for i in listen_list: wx.AddListenChat(who=i) wait = 15

time.sleep(20) #就是这里,等一会,大家自己试一下,估计再少一些也没问题

while True: msgs = wx.GetListenMessage() for chat in msgs: one_msgs = msgs.get(chat) # 获取消息内容

for msg in one_msgs: if msg.type == 'sys': print(f'【系统消息】{msg.content}')

elif msg.type == 'friend':

sender = msg.sender # 这里可以将msg.sender改为msg.sender_remark,获取备注名 print(f'{sender.rjust(20)}:{msg.content}')

elif msg.type == 'self': print(f'{msg.sender.ljust(20)}:{msg.content}')

elif msg.type == 'time': print(f'\n【时间消息】{msg.time}')

elif msg.type == 'recall': print(f'【撤回消息】{msg.content}') time.sleep(wait)

加了一些print语句追踪,可以看一下效果,注意_self.CMsgList.GetChildren的长度 D:\AIdemo\WeChatRPA\venv\Scripts\python.exe D:\AIdemo\WeChatRPA\demo.py 初始化成功,获取到已登录窗口:{微信昵称} 将要执行ChatWind的init构造函数中的self.GetAllMessage()语句 进入ChatWnd类GetAllMessage函数 chatWnd类GetAllMessage函数的MsgItems-即 self.C_MsgList.GetChildren的长度是12 chatWnd类GetAllMessage函数的msgs的长度是12 刚刚执行过ChatWind的init构造函数中的self.GetAllMessage()语句 等20秒,窗口加载完全 进入WeChat类的GetListenMessage函数 进入ChatWnd类的GetNewMessage函数 ChatWnd类的GetNewMessage函数中self.usedmsgid为空 进入ChatWnd类GetAllMessage函数 chatWnd类GetAllMessage函数的MsgItems-即self.C_MsgList.GetChildren的长度是43 chatWnd类GetAllMessage函数的msgs的长度是42 ChatWnd类的GetNewMessage函数中self.usedmsgid初始化完毕,长度为42,即将退出该函数 WeChat类中的GetListenMessage函数中的the_new_msgs的长度是0

还有个问题不知道你发现没,长时间运行的时候会出现旧的消息被重复监听到,比如我今天11.45突然又收到一个9.40多的消息,不知道是不是旧消息的runtimeid变更了,导致被当作新的消息重新监听到

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you are subscribed to this thread.Message ID: @.> — Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you commented.Message ID: @.>

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you are subscribed to this thread.Message ID: @.> — Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you commented.Message ID: @.>

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you are subscribed to this thread.Message ID: @.***>