解析WhatsApp聊天记录
我正在尝试为WhatsApp的聊天记录写一个解析器。下面是一个简单的聊天记录文件。
在这个记录中,有两种类型的消息,第一种是普通消息,格式是
date time: Name: Message
你可以看到,Message
可以换行,而名字中可以包含:
。
第二种消息是“事件”消息,可能有以下几种类型:
date time: Name joined
date time: Name left
date time: Name was removed
date time: Name changed the subject to “GroupName”
date time: Name changed the group icon
我尝试写了一些正则表达式,但遇到了一些困难:如何处理多行消息,如何解析Name
字段(因为用:
分割不太好用),如何构建一个正则表达式来识别当前在群组中的发送者的消息,最后如何解析特殊消息(比如,寻找“joined”作为最后一个词并不是个好主意)。
我该如何解析这样的日志文件,并把所有内容放到一个字典里呢?
更具体地说,针对评论中的问题,我想要的输出是一个嵌套字典:第一层的键是每个发送者,第二层区分“事件”(比如加入、离开等)和“消息”,并把所有内容放成一个元组的列表。
>>>datab[Sender1]['Events']
>>>[('Joined',data1,time1),('Left',data2,time2]
>>>datab[Sender2]['Messages']
>>>[(data1,time1,Message1),(data2,time2,Message2)]
不过如果你能想到更聪明的格式,那就试试吧!
29/03/14 15:48:05: John Smith changed the subject to “Test”
29/03/14 16:10:39: John Smith joined
29/03/14 16:10:40: Person:2 joined
29/03/14 16:10:40: John Smith: Hello!
29/03/14 16:11:40: Person:2: some random words,
29/03/14 16:12:40: Person3 joined
29/03/14 16:13:40: John Smith: Hello!Test message with newline
Another line of the same message
Another line.
29/03/14 16:14:43: Person:2: Test message using as last word joined
29/03/14 16:15:57: Person3 left
29/03/14 16:17:16: Person3 joined
29/03/14 16:18:21: Person:2 changed the group icon
29/03/14 16:19:16: Person3 was removed
29/03/14 16:20:43: Person:2: Test message using as last word left
2 个回答
1
迟来的补充。
@Casimir的回答是2014年的内容。现在WhatsApp消息的格式有了一些变化。下面是更新后的正则表达式,但我没有涵盖特殊消息的部分(比如加入、离开、改变主题等)。
(?<datetime>\d{1,2}\/\d{1,2}\/\d{1,4}, \d{1,2}:\d{1,2}( (?i)[ap]m)*) - (?<name>.*(?::\s*\w+)*|[\w\s]+?)(?:\s+(?<action>joined|left|was removed|changed the (?:subject to "\w+"|group's icon))|:\s(?<message>(?:.+|\n(?!\d{1,2}\/\d{1,2}\/\d{1,4}, \d{1,2}:\d{1,2}( (?i)[ap]m)*))+))
4
你可以使用这个模式:
(?P<datetime>\d{2}\/\d{2}\/\d{2} \d{2}:\d{2}:\d{2}): (?P<name>\w+(?::\s*\w+)*|[\w\s]+?)(?:\s+(?P<action>joined|left|was removed|changed the (?:subject to “\w+”|group icon))|:\s(?P<message>(?:.+|\n(?!\n))+))
为了处理多行信息,我使用了一个负向前瞻来禁止连续的换行符。不过,你可以通过在\n
后面添加下一个块的开始或字符串的结束来让这个模式更宽容。