You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS版24小时制WhatsApp聊天文本日期匹配与split报错问题

iOS WhatsApp聊天文本转DataFrame的正则匹配问题解决方案

问题原因分析

  • 正则匹配失败:原有正则中秒数匹配规则为([0-9])?,仅支持0或1位数字,而WhatsApp导出的秒数固定为2位,因此无法匹配到合法的日期前缀。
  • split解包报错:原有正则中添加了大量不必要的捕获组(即没有实际提取需求却加了()包裹规则),使用re.split()时会自动把所有捕获组的内容返回为分割结果的一部分,导致分割后的元素数量远多于预期的2-3个,触发解包报错。

修复方案

1. 修正日期匹配函数

去掉所有不必要的捕获组,将不需要单独提取的规则改为非捕获组(括号前加?:),同时适配2位秒数的匹配规则:

import re
import pandas as pd

def dateTimeios(s):
    # 适配24小时制iOS WhatsApp日期前缀,非捕获组避免split返回多余内容
    pattern = r'^\[(?:\d{1,2})\/(?:\d{1,2})\/(?:\d{4}), (?:\d{1,2}):(?:\d{1,2}):(?:\d{2})\] '
    return bool(re.match(pattern, s))

2. 优化消息拆分逻辑

不使用split()做拆分,直接通过正则分组一次性提取日期、发件人、消息内容三个字段,避免解包错误,同时支持处理换行的长消息:

def parse_chat_line(line):
    match_res = re.match(r'^\[(\d{1,2}\/\d{1,2}\/\d{4}, \d{1,2}:\d{1,2}:\d{2})\] (.*?): (.*)', line)
    if match_res:
        return {
            "datetime": match_res.group(1),
            "sender": match_res.group(2),
            "content": match_res.group(3)
        }
    return None

# 完整的聊天文件转DataFrame逻辑
def chat_to_df(file_path):
    chat_list = []
    current_msg = None
    with open(file_path, 'r', encoding='utf-8') as f:
        for line in f:
            line = line.strip()
            if not line:
                continue
            # 匹配到新的消息头
            if dateTimeios(line):
                if current_msg:
                    chat_list.append(current_msg)
                current_msg = parse_chat_line(line)
            # 是上一条消息的换行内容
            else:
                if current_msg:
                    current_msg["content"] += f"\n{line}"
    # 追加最后一条消息
    if current_msg:
        chat_list.append(current_msg)
    df = pd.DataFrame(chat_list)
    # 转换时间格式,注意如果你的日期是月/日格式,把format改成'%m/%d/%Y, %H:%M:%S'
    df["datetime"] = pd.to_datetime(df["datetime"], format='%d/%m/%Y, %H:%M:%S')
    return df

# 调用示例
# df = chat_to_df("你的聊天文件路径.txt")

可选说明

如果确实需要用re.split()实现拆分,只需要把正则里所有非必要的捕获组都改成非捕获组,分割后就只会返回[前缀前内容, 前缀后内容]两个部分,不会出现多余元素:

# 用于split的非捕获组正则
split_pattern = r'^\[(?:\d{1,2})\/(?:\d{1,2})\/(?:\d{4}), (?:\d{1,2}):(?:\d{1,2}):(?:\d{2})\] '
# 分割后得到两个元素:空串(因为前缀在开头)和后面的发件人+内容
parts = re.split(split_pattern, line)

内容的提问来源于stack exchange,提问作者mickeywise

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 00:36:03