HOWTO · Python

在 Python 中解析日誌檔案

瞭解如何在 Python 中解析日誌檔案

本頁內容

日誌檔案會記錄應用程式或系統發生的事件,例如請求和錯誤。若要在 Python 中分析以直線符號分隔的檔案,可以逐行讀取,將每筆記錄拆分成欄位,再將欄位對應到名稱。以下範例使用四個欄位:時間戳記、URL、訊息類型和訊息。

了解日誌格式

此範例預期每行有一筆記錄,格式如下:timestamp | URL | type | message。直線符號(|)用來分隔欄位,每個值前後的空白也會移除。時間戳記會保留為文字;若之後需要進行時間順序相關的計算,可以再將它轉換成日期時間物件。URL 和訊息類型也都是字串,解析後可以用來篩選或轉換資料。

範例記錄如下:2021-10-26 10:26:44 | https://website.com/home | SUCCESS | Message。解析器假設前三個直線符號依序分隔時間戳記、URL 和類型。後續的直線符號都會留在訊息欄位中,因此訊息即使含有 |,也不會讓前面的欄位錯位。

將每一行解析成字典

字典會為每個值提供固定名稱,之後篩選時比依賴數字位置更清楚。下方的指令碼會建立暫存檔案 log.txt,使用內容管理器讀取檔案,並解析每一行非空白記錄。split("|", 3) 將拆分次數限制為三次欄位分隔,因此該行其餘內容會留在訊息欄位中。若記錄的欄位數不是四個,指令碼會回報問題,而不是默默捨棄無法對應的值。

執行以下範例:

本節中的程式碼以及顯示的標籤或輸出仍為英文。

import json
from pathlib import Path
from tempfile import TemporaryDirectory

sample = """2021-10-26 10:26:44 | https://website.com/home | SUCCESS | Home loaded
2021-10-26 10:26:54 | https://website.com/about | SUCCESS | About page loaded
2021-10-27 10:27:01 | https://website.com/page | ERROR | Page unavailable
"""
fields = ("date", "url", "type", "message")

with TemporaryDirectory() as folder:
    log_path = Path(folder) / "log.txt"
    log_path.write_text(sample, encoding="utf-8")
    records = []

    with log_path.open(encoding="utf-8") as log_file:
        for line_number, line in enumerate(log_file, start=1):
            if not line.strip():
                continue
            values = [value.strip() for value in line.split("|", 3)]
            if len(values) != len(fields):
                print(f"Line {line_number}: expected 4 fields, got {len(values)}")
                continue
            records.append(dict(zip(fields, values)))

for record in records:
    print(json.dumps(record, ensure_ascii=False))
{"date": "2021-10-26 10:26:44", "url": "https://website.com/home", "type": "SUCCESS", "message": "Home loaded"}
{"date": "2021-10-26 10:26:54", "url": "https://website.com/about", "type": "SUCCESS", "message": "About page loaded"}
{"date": "2021-10-27 10:27:01", "url": "https://website.com/page", "type": "ERROR", "message": "Page unavailable"}

提供的執行結果會為每筆範例記錄列印一個字典。每個字典都包含 date、url、type 和 message 這些鍵,各值前後的空白則已移除。

執行解析器並檢查輸出

將指令碼存成 Python 檔案,然後在已安裝 Python 的終端機中執行。範例資料會由指令碼寫入暫存檔案 log.txt,因此不需要另外準備輸入檔案。請確認每個列印出的 JSON 物件都對應一行範例資料、日期與輸入資料相符,而且訊息文字保留在 message 鍵下。JSON 輸出便於檢視;若想保留解析後的記錄,也可以將輸出重新導向至檔案。

處理格式錯誤或格式不同的日誌行

解析器會先檢查欄位數,再建立字典。若某行的分隔符號不足,欄位數就會少於四個;指令碼會回報該行的行號,然後繼續處理。由於 split("|", 3) 在前三個分隔符號處停止拆分,後續的直線符號會留在第四個欄位,成為訊息的一部分。解析器無法判斷多出的分隔符號是意外出現,還是原本就屬於訊息。空白行會略過。若你的格式允許訊息以外的欄位包含直線符號,單純依分隔符號拆分就會產生歧義。請改用含有引號規則的格式,例如設定分隔符號的 CSV,或調整資料產生端,讓它一致地跳脫分隔符號。

若記錄可能以分隔符號結尾,或包含選填欄位,請明確定義格式,並調整驗證規則以符合該格式。若資料品質很重要,應保留格式錯誤的行以供調查;不要直接對長度不相等的清單使用 zip,因為它會截斷較長的清單,可能讓遺漏的值被掩蓋。

分析解析後的記錄

當 records 中已包含字典時,可以使用清單推導式選出錯誤記錄,例如 [record for record in records if record["type"] == "ERROR"]。你可以依類型彙總數量、將記錄存入資料庫,或把選定欄位傳給繪圖函式庫。解析只會整理文字,無法判定事件是否可疑,也不能證明發生了資安事件。要得出這類結論,還需要背景脈絡、合適的偵測規則和進一步調查。