跳至主要內容
全球國際徵信顧問
案件指揮艙全部本機工具
V236 / OPERATING GUIDE

先讀範圍,再看統計能說明什麼。

聊天紀錄統計分析器只在你的瀏覽器內處理匯出檔,不上傳、不使用瀏覽器儲存空間。本頁說明它做什麼、不做什麼、各項統計的算法、如何用 Python 自行重算,以及最常被誤解的地方。

READ FIRST

先說清楚這不是什麼

這個工具輸出的是「統計描述,不是對任何人的判斷」。
SOURCES

支援的來源與取得方式(一般而言)

下面「一般而言」的描述,是對各 App 常見做法的概述,不是逐版本確認過的操作畫面。App 會改版,選項的名稱與位置請以你手上的版本為準。

來源一般而言怎麼取得檔案長什麼樣子本工具的驗證程度
LINE 文字匯出(.txt)手機版與電腦版的聊天室選單裡,一般都有把聊天紀錄存成文字檔的功能,名稱可能是「傳送聊天記錄」或「儲存聊天」之類。開頭有 [LINE] 標題與儲存日期;之後每天一行日期標頭;訊息多為「時間、Tab、名稱、Tab、內容」,多行訊息常以雙引號包住。日期標頭、時間(24 小時或上午/下午)與各語系的寫法,是依記憶整理的多種變體,只用本站的合成資料驗證過,尚未用各版本的真實匯出檔逐一確認。
WhatsApp 文字匯出(.txt)聊天室選單裡一般有「匯出聊天」,可選擇是否附上媒體;選不含媒體會得到文字檔(有時包在 zip 內,請先解壓縮)。iPhone 常見為「[日期, 時間] 名稱: 內容」,Android 常見為「日期, 時間 - 名稱: 內容」;日期順序、12/24 小時制與標點依手機語系而不同。同上,只用合成資料驗證。「日/月/年」與「月/日/年」可能無法從檔案本身判斷,工具會明說,並提供一鍵改用另一種重新解析。
Telegram result.jsonTelegram 桌面版的資料匯出功能,一般可選擇 JSON 格式,得到 result.json;可匯出單一聊天室,也可匯出整個帳號(含多個聊天室,工具會請你選一個)。一個 JSON,內有 messages 陣列;每則有 date 與 date_unixtime、發送者、文字與媒體欄位。只用合成資料驗證。時區由檔案內 date 與 date_unixtime 的差推得。不讀 HTML 匯出。
Facebook Messenger JSONFacebook 的「下載你的資訊」一般可選 JSON 格式與「訊息」項目,解壓縮後常見 message_1.json、message_2.json 等檔案。JSON,內有 participants 與 messages;中文常被寫成「UTF-8 位元組當成 Latin-1」的亂碼,工具會偵測並還原。可一次選取多個 message_*.json 合併。只用合成資料驗證(含模擬的亂碼)。時間取 timestamp_ms,依你選的時區換成牆上時間。
CSV/TSV任何欄位式紀錄,例如自行整理的試算表,或本工具輸出的標準化 CSV。工具會猜哪一欄是時間、發送者、內容;支援 ISO 時間、epoch 秒或毫秒、日期與時間分欄;猜不出來時請你指定欄位。合成資料驗證。分隔字元可為逗號、分號、Tab。
不支援:zip 壓縮檔(請先在電腦上解壓縮,再選裡面的 .txt 或 .json)、HTML 匯出、Instagram、微信、Signal 等其他來源。這些沒有測試過,不承諾能讀。
PARSING RULES

解析規則與錯誤處理

格式偵測
檢查檔案開頭一段(至多約 1 MiB)的特徵並評分:LINE 看 [LINE] 標頭、「時間+Tab」的行與日期標頭;WhatsApp 看兩種日期時間格式;JSON 看 sender_name 加 timestamp_ms(Messenger),或 messages 加 date_unixtime 等欄位(Telegram);CSV 看分隔字元與欄位。結果附「信心:高、中、低」與依據。偵測不準時,可在「進階設定」手動選格式、編碼、日期順序與時區。
編碼
先看 BOM(UTF-8、UTF-16);沒有 BOM 時,依位元組分布判斷是否為 UTF-16,再嚴格檢查是不是有效的 UTF-8;都不是,就在 Big5、GB18030、Shift_JIS、EUC-KR 之中挑「無法解碼的字元最少」的一種,並在摘要註明是猜的。解不出來的位元組會顯示為「�」並提示數量;也可以手動指定編碼。
日期順序
像 03/05/2024 這種日期,可能是日/月/年,也可能是月/日/年。檔案中只要有任何一個日期的前兩個數字有一個大於 12(例如 25/03/2024),順序就能判定。全部都不大於 12 時無法判斷,工具會明說,先採一種預設解讀,並提供一鍵改用另一種重新解析;檔案內同時出現兩種順序的證據時,也會提示。
多行訊息與空行
LINE 以雙引號包住的多行訊息、WhatsApp 以「不是日期時間開頭的行」續接前一則;訊息中間的空行會保留。
訊息類型
依常見用語把每則分成文字、媒體(照片、貼圖、影片、語音、檔案、位置等)、通話、收回、系統。這是文字樣式比對:只認得它知道的寫法,沒認出的當作一般文字;也可能誤判,例如有人在聊天中真的打出「[照片]」這幾個字,工具無法與系統產生的提示區分。媒體本身(圖片、語音)不在文字匯出檔裡,工具只計次數。
同名發送者
名稱完全相同(去掉前後空白與方向標記後,區分大小寫)算同一位。兩個不同的人同名,會被合併;同一個人改過名字,會被算成兩位。工具無法分辨。
無法解析的行
日期無效、最早一則訊息之前的雜訊、不完整的 JSON 項目等,會列在問題清單,附行號與原因,不會悄悄略過。清單最多顯示前 200 筆,總數另外列出。
順序
統計用的順序就是檔案裡的順序。若某個來源整段幾乎都是由新到舊排列(例如部分 CSV),工具會反轉並在摘要提示;零星的時間倒退則照檔案順序保留,列在「時間順序異常」。
大小限制
單檔上限 256 MiB、合計 512 MiB、至多 200 個檔案、至多 400 萬則訊息,超過時會明確報錯,不會悄悄截斷。單行超過 1 MiB 的部分、以及多行訊息累積超過 10 萬字元的部分不保留文字,但字數仍計入全文。
TIME / TIME ZONE

時間與時區

牆上時間
LINE、WhatsApp 與沒有時區資訊的 CSV,只有「顯示的日期與時間」。工具照字面使用,不換算、不猜時區;輸出的 ISO 時間不附時區偏移(除非你在進階設定自行指定時區)。
時間戳記來源
Telegram 的 date_unixtime、Messenger 的 timestamp_ms、CSV 的 epoch 秒或毫秒,記的是不帶地區的時間戳記,必須依時區換成牆上時間才知道「幾點」。Telegram 用同一則訊息的 date(文字時間)與 date_unixtime 相減,取檔案前段最常出現的差作為偏移;其他來源預設取這台裝置目前的時區,可在進階設定改選。輸出的 ISO 時間會附上這個偏移。
固定偏移,不處理日光節約時間
換算只用單一固定偏移,不處理日光節約時間,也不處理時區的歷史變更。聊天若跨越日光節約時間的切換,換算出來的時間可能與當時手機上顯示的差一小時。
「哪一天、星期幾、幾點」
全部依顯示的牆上時間計算;跨過午夜的訊息,歸入各自的日期。週一排在一週的最前面。
時間精度
LINE 與 WhatsApp 常只到分鐘;有秒的檔案以秒計。分鐘精度下,同一分鐘的多則訊息時間差為 0,彼此的先後只能看檔案順序。
STATISTICS RULES

各項統計怎麼算

以下所有項目都可以用 Python 自行重算(見下一節)。「非系統訊息」指文字、媒體、通話、收回四種;系統訊息(加入群組、改名等)不計入任何統計。

1. 各發送者的訊息數、字數、平均長度
訊息數=該發送者的非系統訊息數。字數只計文字訊息,以 Unicode 碼位計(含空白與換行;一個 emoji 通常算 1 個碼位,但帶膚色、組合符號的 emoji 可能占多個碼位)。平均長度=字數 ÷ 文字訊息數。同時列出首則與末則的時間,以及有訊息的天數。
2. 每日訊息數(日曆熱度圖)與每月表
依顯示的牆上時間的日期,把每天的非系統訊息數加總。熱度圖的顏色依平方根分成五級,只是為了讓低量的日子看得見;精確的數字請看「文字版」表格與滑鼠或觸控時顯示的數字。
3. 星期 × 小時分佈
以星期(週一到週日)與整點小時(0 到 23)分成 168 格,計算非系統訊息數。
4. 最長的沉默間隔(前 10)
檔案順序中,相鄰兩則非系統訊息的時間差,由大到小列出前 10 名。時間倒退的相鄰對、以及時間差為 0 的相鄰對不列入;長度相同時,檔案中較前面的排前面。這只代表「兩則訊息之間沒有紀錄」,不代表當事人沒有聯絡:可能改用電話、當面或其他軟體,也可能是匯出不完整。
5. 回覆時間分佈(中位數、P90)
  • 只看相鄰兩則「文字、媒體、收回」訊息(有發送者的);通話與系統訊息不參與。
  • 前後兩則的發送者不同,且時間差大於或等於 0,後一則與前一則的時間差就算「後一位發送者」的一次回覆。同一個人連發多則,只有最後一則會成為下一位回覆時的起點。
  • 時間差超過上限(預設 24 小時,可調)者不計入分佈,另列「超過上限」次數。
  • 中位數用一般定義:個數為奇數取中間值,偶數取中間兩個的平均。P90 用最近排名法:由小到大排序後取第 ⌈0.9 × n⌉ 個。
  • 小例子:09:00 A 說話;09:02 B 回;09:03 B 又說一句;09:30 A 回。B 的回覆是 2 分鐘;A 的回覆從 B 的最後一則(09:03)算起,是 27 分鐘。n = 2,中位數 = (2 + 27) ÷ 2 = 14.5 分鐘,P90 = 第 ⌈1.8⌉ = 2 個 = 27 分鐘。
6. 沉默達門檻之後,由誰先開口
相鄰兩則非系統訊息的時間差大於或等於門檻(預設 6 小時,可調),就把「後一則」的發送者記為先開口一次。它只是「誰的訊息出現在沉默之後」,不代表誰主動、誰在意。
7. 深夜訊息比例
訊息顯示時間的「小時」落在設定時段內(預設 23:00 至 05:00)就算深夜;時段含起點、不含終點,可以跨午夜;起點等於終點代表空時段。比例=深夜訊息數 ÷ 全部非系統訊息數,全體與各發送者各算一次。
8. 時間順序異常
「時間倒退」=檔案中相鄰兩則非系統訊息,後者的時間早於前者。「同時間戳」=相鄰兩則時間完全相同,連續相同的算一組。分鐘精度的來源,同一分鐘有多則是正常現象。這些只是提醒檔案可能被重新排序、合併或編輯,並不能據此判斷原因。
9. 匯出完整性提示
「整天沒有訊息」=最早一天到最末一天之間,非系統訊息數為 0 的日子,並列出最長的幾段。「訊息量下降」=以最早一天起每 7 天為一週,某週起連續 4 週的每週平均不超過前 4 週平均的 10%,而且前 4 週平均至少 20 則。檔案若有 LINE 的「儲存日期」,也會列出它與最後一則訊息相差幾天。這些都只是「提醒你對照原 App」,工具分不出是真的沒聊、匯出時間範圍不含、被刪除,還是匯出不完整。
KEYWORDS / EXTRACT / MASK

關鍵字、萃取與遮蔽

關鍵字清單
  • 預設是六個中性的話題分類(金錢與轉帳、約定時間與地點、文件與附件、感謝與道歉、工作與會議、問候與日常)。它們只是方便你找訊息的歸類,不代表任何判斷;你可以改名、增刪字詞、新增分類。
  • 比對方式是「不分大小寫的子字串」,不做斷詞、同義詞或語意判斷。命中數=「含有其中任一字詞的訊息數」。通話、收回、系統訊息,以及「[照片]」「<attached: …>」這類占位文字不參與比對。
  • 清單可匯出成 JSON(格式 gib-chat-keywords-1),下次匯入;上限為 50 個分類、每類 500 個字詞、字詞至多 80 字、檔案 1 MiB。每個分類最多保留前 20,000 則命中供瀏覽,超過時會明說。
  • 命中的訊息以前後文片段呈現,按「到訊息」可跳到訊息檢視器的原位置。
萃取
  • 種類:電話、網址、Email、金額、內文提到的日期時間、長數字(連續 10 位以上,或三組以上數字以空格或連字號相連)、身分證字號格式(一個英文字母加 9 碼數字)。
  • 通話、收回、系統訊息與占位文字(例如「[照片]」)不參與萃取,所以通話時間「10:00」不會被當成日期時間。
  • 只依「格式」比對並標記;不查詢號碼屬於誰、不連線到網址、不展開短網址、不驗證證號或帳號。長數字不判斷是不是帳號或卡號,也可能比錯。
  • 金額不處理中文數字(例如「三千」);「內文提到的日期時間」是訊息內容裡的字樣,不是訊息本身的時間戳。
  • 每種最多列出 3,000 個不重複項目,超過的部分只計次數並明說。
遮蔽
  • 發送者改成 A、B、C…(依首次出現的順序);電話、長數字、身分證字號格式、Email 可分別勾選,數字類保留末 3 碼,其餘以 ● 蓋掉;網址可選擇保留或只留網域;你指定的字詞(姓名、地址、公司名等)換成 ■■■。
  • 發送者名稱出現在訊息內文時,也會換成對應代號(名稱至少 2 個字元)。
  • 限制:遮蔽只處理看得出格式的資料。內文中其他可辨識的資訊(沒有列入自訂字詞的姓名、地址、工作單位、事件細節)不會被遮蔽。遮蔽不是匿名化,對外提供前請自己再讀一遍。
OUTPUT / HANDOFF

輸出與送到線索推理艙

逐筆 CSV
欄位:seq、time_iso、sender、type、content、source_line、time_precision(合併多個檔案時另加 source_file)。UTF-8(含 BOM)、換行 CRLF。type 為 text、media、call、unsent、system 其中之一。內容以 = + - @ 開頭時,前面會加一個單引號,避免試算表把它當成公式執行,這會讓該格內容多一個字元;自行重算字數時請先去掉(見範例程式)。
逐筆 JSON
格式 gib-chat-1:內含說明、來源資訊(格式、編碼、時區、時間精度)與 messages 陣列。JSON 不加公式前綴。
範圍與遮蔽
可輸出「全部訊息」或「訊息檢視器目前篩選的結果」,也可選「原文(含真實名稱)」或「遮蔽版」。
報告與摘要
遮蔽報告(HTML,可在瀏覽器列印)、遮蔽統計摘要(TXT)、完整統計摘要(TXT,含真實名稱,請自己留用)。報告只含統計、你放進片段籃的片段,以及關鍵字與萃取的數量;萃取的內容不會寫進報告。
送到線索推理艙
只會送出「遮蔽版統計摘要」加上你放進片段籃的片段,不會送出完整對話。先按「更新預覽」看實際內容,勾選確認後才能送出。送出時會開啟同一網站的「AI 偵探實驗室」分頁,內容只在你的瀏覽器內從這個分頁傳到那個分頁,不經過任何伺服器;被瀏覽器擋住彈出視窗、或對方分頁沒有回應時,工具會提示改用「複製預覽文字」。
想證明這份檔案在某時點長這樣
請先用證據鏈帳本對「原始匯出檔」計算 SHA-256 並記錄加入時間,再來分析。工具讀取檔案時不會改動原檔;但輸出的 CSV、JSON、報告是新檔案,不能代替原始檔。
SELF-CHECK

如何自行驗證

方法一:用 Python 重算

在「輸出」分頁下載標準化 CSV(原文或遮蔽版都可以,遮蔽版的發送者會是 A、B…),然後執行下面的程式。它只讀取 CSV,不依賴本站任何程式,重算各發送者的訊息數與字數、回覆時間中位數與 P90、沉默後先開口、最長的三段沉默。把印出的數字與畫面上的統計比對;門檻若在畫面上改過,請用命令列參數帶入相同的值。

# 用法:python3 selfcheck.py chat.csv [沉默門檻小時=6] [回覆上限小時=24]
import csv, sys, math, collections, datetime as dt

path = sys.argv[1]
silence_h = float(sys.argv[2]) if len(sys.argv) > 2 else 6
cap_h = float(sys.argv[3]) if len(sys.argv) > 3 else 24

rows = list(csv.DictReader(open(path, encoding="utf-8-sig", newline="")))
for r in rows:
    # 牆上時間:ISO 字串若帶 +08:00 之類的偏移,只取日期時間本身(工具內部也是用顯示的牆上時間)
    r["t"] = dt.datetime.fromisoformat(r["time_iso"]).replace(tzinfo=None)
    c = r["content"]
    if c[:1] == "'" and c[1:2] in ("=", "+", "-", "@"):   # 還原 CSV 為防試算表公式而加的單引號
        r["content"] = c[1:]

counted = [r for r in rows if r["type"] != "system"]       # 系統訊息不計
secs = lambda a, b: (b["t"] - a["t"]).total_seconds()

# 1. 各發送者:訊息數、文字訊息的字數(Unicode 碼位,含空白與換行)
n = collections.Counter(r["sender"] for r in counted)
chars = collections.Counter()
for r in counted:
    if r["type"] == "text":
        chars[r["sender"]] += len(r["content"])

# 2. 回覆時間:相鄰的「文字、媒體、收回」訊息,發送者不同、時間差 >= 0 且不超過上限
conv = [r for r in counted if r["sender"] and r["type"] in ("text", "media", "unsent")]
rep = sorted(secs(a, b) for a, b in zip(conv, conv[1:])
             if a["sender"] != b["sender"] and 0 <= secs(a, b) <= cap_h * 3600)
median = (rep[(len(rep) - 1) // 2] + rep[len(rep) // 2]) / 2 if rep else None
p90 = rep[math.ceil(0.9 * len(rep) - 1e-9) - 1] if rep else None      # 最近排名法

# 3. 沉默達門檻之後,由誰先開口(相鄰兩則非系統訊息,時間差 >= 門檻,記後一則的發送者)
opens = collections.Counter(b["sender"] for a, b in zip(counted, counted[1:]) if secs(a, b) >= silence_h * 3600)

# 4. 最長的三段沉默(時間差 > 0;相同長度時檔案中較前面的排前面)
gaps = sorted(((secs(a, b), i) for i, (a, b) in enumerate(zip(counted, counted[1:])) if secs(a, b) > 0), key=lambda g: (-g[0], g[1]))[:3]

print("非系統訊息", len(counted), "則")
for s in n:
    print(" ", s or "(未標示)", "訊息", n[s], "文字字數", chars[s])
print("回覆", len(rep), "次;中位數", median, "秒;P90", p90, "秒")
print("沉默 >=", silence_h, "小時之後先開口:", dict(opens))
print("最長三段沉默(秒):", [g[0] for g in gaps])

用本站的合成對話小樣本(2,909 則)試過:畫面上的各項數字與這段程式印出的結果一致(本機沙箱小樣本,不代表所有檔案)。

方法二:用小例子手算

把下面四行存成 .csv 檔(UTF-8),丟進工具:

time,sender,text
2024-03-05 09:00,A,早
2024-03-05 09:02,B,早安
2024-03-05 09:03,B,吃飯了嗎
2024-03-05 09:30,A,還沒

依「回覆時間」一節的規則手算,應該是:非系統訊息 4 則(A 2 則、B 2 則);回覆 2 次(2 分鐘與 27 分鐘),中位數 14 分 30 秒,P90 為 27 分;最長的沉默是 09:03 到 09:30 的 27 分鐘。工具的畫面應與此相同。把例子擴充成你自己的幾十則對話,手算與工具比對,是最容易發現規則理解差異的做法。

方法三:對照原 App
在訊息檢視器按「到訊息」,會顯示原檔的行號(Telegram 與 Messenger 為第幾筆)。對照原始匯出檔與原 App 內的對話,確認工具沒有漏掉、切錯或拆錯訊息。
方法四:核對原始檔
用作業系統的 sha256sum(或 shasum -a 256、certutil -hashfile)對原始匯出檔計算,與你先前記錄的 SHA-256 比對,確認分析的是同一份檔案。
COMMON MISUNDERSTANDINGS

常見誤解

LIMITS

已知限制與尚未確認的地方

誠實說明:LINE 與 WhatsApp 的日期標頭、時間、語系、系統訊息與媒體用語的辨識規則,是依對各 App 匯出內容的記憶建立,用本站的合成資料測試過;沒有用各個 App 版本、各種手機語系的真實匯出檔逐一確認。遇到沒見過的寫法,會列入問題清單,或被當成一般文字。Telegram 與 Messenger 的 JSON 欄位,是依對公開格式的了解實作,不同版本可能有差異。

實測效能(本機沙箱小樣本)

以下數字來自 2 核心 CPU、沒有 GPU 的沙箱裡的 headless Chromium,只是「小樣本」,不代表你的裝置;手機、舊電腦或記憶體較少的環境會比較慢,也可能失敗。檔案是合成資料,不是真實對話。

3,353,385 則(本機沙箱小樣本)
項目實測說明
檔案119.2 MB(113.7 MiB),3,353,385 則合成的 LINE 文字匯出檔,兩位發送者,涵蓋約 10 年。
載入到出現統計結果5.7 秒讀檔、解析、計算統計全部在背景執行緒;期間畫面可操作「取消」。
按下「取消」到恢復可操作0.07 秒處理到一半取消,之後可立刻改載入別的檔案。
進度更新90 次通知、43 個不同的進度值解析階段的進度條只會前進;統計階段改為不確定進度。
改參數後重算統計0.58 秒沉默門檻、回覆上限、深夜時段改變後,在背景重算。
檢視器(3,353,385 列)開啟 0.13 秒;按 End 跳到最後一則 0.03 秒;類型篩選約 0.11 秒;全文搜尋 0.16 秒虛擬捲動,畫面上只有幾十列;篩選在背景執行緒進行。
匯出「目前篩選的結果」CSV0.30 秒以通話類型 67,454 列為例。
關鍵字掃描(預設 6 個分類)/萃取1.2 秒/0.80 秒全部 3,353,385 則;萃取只保留前 3,000 筆去重後的項目。
主執行緒長任務(超過 100 ms)0 個;最長 77 ms整段操作(載入、統計、檢視器、匯出、關鍵字、萃取)合計。
瀏覽器記憶體(所有 Chromium 行程的 RSS 峰值)約 1,469 MB包含背景執行緒中的 3,353,385 則訊息。記憶體少的手機處理這種大小的檔案可能失敗,建議依月份分段匯出。

另外用約 20 MB 的檔案、手機視窗(390×844),以開發者工具把 CPU 放慢為 4 倍,跑同一條流程。需要說明:這個節流只放慢頁面的主執行緒,背景執行緒的解析與統計不受影響,所以它主要反映畫面渲染與互動的變慢程度,不等於真實的低階手機。

CPU 節流 1× 與 4×(本機沙箱小樣本)
步驟1×4× 節流
載入到出現結果1.5 秒1.8 秒
改參數重算0.26 秒0.40 秒
關鍵字掃描0.41 秒0.59 秒
萃取0.30 秒0.32 秒
開啟檢視器0.07 秒0.12 秒
全文搜尋0.13 秒0.20 秒
End 鍵跳到最後0.01 秒0.02 秒
匯出全部 CSV(43 MB)1.7 秒1.9 秒
產生 HTML 報告0.05 秒0.13 秒
交接預覽0.08 秒0.13 秒
主執行緒長任務(>100 ms)0 個,最長 74 ms3 個,最長 239 ms

建議的使用流程

  1. 保留原始匯出檔,不要修改它。先用證據鏈帳本為原始檔計算 SHA-256 並記錄。
  2. 開啟聊天紀錄統計分析器,選取檔案,按「開始分析」。
  3. 先看「解析結果」:格式、編碼、日期順序、時區、筆數與問題清單。有疑問就到進階設定調整後重新解析。
  4. 看統計;需要時調整沉默門檻、回覆時間上限與深夜時段。
  5. 用關鍵字或萃取找出特定訊息,按「到訊息」對照原 App 內的紀錄。
  6. 把需要的片段加入片段籃,輸出遮蔽版報告或 CSV;對外提供之前,自己再讀一遍遮蔽後的內容。
  7. 要整理線索,可預覽後送到線索推理艙;是否可作為證據、怎麼提出,請諮詢律師。