之前我们讲了如何利用python自动获取微信聊天记录,感兴趣的小伙伴可查看我之前的文章。不过,之前的方法都只获取了微信的聊天内容,有些场景或项目中可能需要我们记录各条消息的发送时间。这一节我们来看一下如何获取微信聊天消息的发送时间。
1. 微信PC客户端
(注:这里最好把微信客户端升级至较新版本)
2. python3.x
3. wxauto
pip install wxauto -i https://pypi.tuna.tsinghua.edu.cn/simple
在wxauto.py中,有这么一段代码,用于解析微信聊天窗口中的一些系统消息,如:消息发送时间、撤回信息、“某某邀请某某入群”等等。
def SplitMessage(MsgItem):
uia.SetGlobalSearchTimeout(0)
MsgItemName = MsgItem.Name
if MsgItem.BoundingRectangle.height() == WxParam.SYS_TEXT_HEIGHT:
Msg = ('SYS', MsgItemName, ''.join([str(i) for i in MsgItem.GetRuntimeId()]))
elif MsgItem.BoundingRectangle.height() == WxParam.TIME_TEXT_HEIGHT:
Msg = ('Time', MsgItemName, ''.join([str(i) for i in MsgItem.GetRuntimeId()]))
elif MsgItem.BoundingRectangle.height() == WxParam.RECALL_TEXT_HEIGHT:
if '撤回' in MsgItemName:
Msg = ('Recall', MsgItemName, ''.join([str(i) for i in MsgItem.GetRuntimeId()]))
else:
Msg = ('SYS', MsgItemName, ''.join([str(i) for i in MsgItem.GetRuntimeId()]))
else:
Index = 1
User = MsgItem.ButtonControl(foundIndex=Index)
try:
while True:
if User.Name == '':
Index += 1
User = MsgItem.ButtonControl(foundIndex=Index)
else:
break
Msg = (User.Name, MsgItemName, ''.join([str(i) for i in MsgItem.GetRuntimeId()]))
except:
Msg = ('SYS', MsgItemName, ''.join([str(i) for i in MsgItem.GetRuntimeId()]))
uia.SetGlobalSearchTimeout(10.0)
return Msg
不过这里的方法只是将这些消息提取出来,没有对时间做进一步解析。我以这个方法为基础,加入了时间转换等代码,使其能够更好地解析时间,满足我们的需求:
def SplitMessageWithTime(MsgItem, step):
uia.SetGlobalSearchTimeout(0)
MessageInfos = WxUtils.GetMessageInfos(MsgItem)
MsgItemName = MsgItem.Name
time_pattern1 = r'([01]?[0-9]|2[0-3]):[0-5][0-9]'
time_pattern2 = r'新消息' # 用于后面的正则表达式匹配时间
"""
这是我自己设计的一个逻辑。因为不同的电脑分辨率不同,我们不能以一个固定的像素值来判断获取到的消息是系统消息、还是聊天正文消息。因此我以第一次
获取的系统消息为基准,按比例来区分系统消息和聊天正文。一般来说,聊天正文的控件高度要略大于系统消息的控件高度。(这里可能设计得不太好,大家有
更好的方法可以指出)
"""
# 以第一条内容的尺寸为标准,设定其他控件的尺寸
if step == 0:
WxParam.SYS_TEXT_HEIGHT = MsgItem.BoundingRectangle.height()
WxParam.TIME_TEXT_HEIGHT = MsgItem.BoundingRectangle.height() * 1.2
WxParam.CHAT_TEXT_HEIGHT = MsgItem.BoundingRectangle.height() * 1.4
Msg = None
# 记录'查看更多消息'的标签宽度
if re.search('查看更多消息', MsgItemName):
Msg = ('SYS', MsgItemName, MessageInfos)
# 获取时间
elif MsgItem.BoundingRectangle.height() <= WxParam.TIME_TEXT_HEIGHT and re.search(time_pattern1, MsgItemName):
WxUtils.publish_time = MsgItemName
Msg = ('Time', MsgItemName, MessageInfos)
# 获取特殊时间
elif MsgItem.BoundingRectangle.height() <= WxParam.TIME_TEXT_HEIGHT and re.search(time_pattern2, MsgItemName):
WxUtils.publish_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M')
Msg = ('Time', WxUtils.publish_time, [WxUtils.publish_time])
# 聊天消息
elif MsgItem.BoundingRectangle.height() >= WxParam.CHAT_TEXT_HEIGHT:
Index = 1
User = MsgItem.ButtonControl(foundIndex=Index)
try:
while True:
if User.Name == '':
Index += 1
User = MsgItem.ButtonControl(foundIndex=Index)
else:
break
if WxUtils.publish_time != '':
Msg = (User.Name, MsgItemName, MessageInfos, WxUtils.publish_time) # 已经有时间则为消息设置时间
else:
Msg = (User.Name, MsgItemName, MessageInfos, '') # 没有时间则先设置为'',后续会继续向前滚动鼠标
except:
Msg = ('SYS', MsgItemName, MessageInfos)
# 系统标签
elif MsgItem.BoundingRectangle.height() == WxParam.SYS_TEXT_HEIGHT:
Msg = ('SYS', MsgItemName, MessageInfos)
else:
Msg = ('Other', MsgItemName, MessageInfos)
uia.SetGlobalSearchTimeout(10.0)
return Msg
原理就是分别读取微信聊天窗口的时间和聊天内容,并将聊天内容和对应的时间放到同一个元组中。由于微信的消息发送时间可能会含有“昨天 14:00”、“星期一 14:00”等这种时间格式,这显然是不可用的。因此我们在解析这些元组时,转换里面的时间YYYY-MM-DD HH:MM的格式。
可能有人会问,你怎么知道哪条消息对应哪个时间?大家可在debug模式下查看获取的所有消息,这里的消息获取是从上往下,时间自然也是从早期到现在。我在代码里面设置了一个变量记录最新时间,如果获取的时间晚于变量,则将变量的值更新为更晚的时间。每次的聊天消息的时间都用这个最晚时间。