Spaces:
Sleeping
Sleeping
data clean and combine dataset
Browse files
app.py
CHANGED
|
@@ -10,6 +10,7 @@ import urllib.request
|
|
| 10 |
import matplotlib.pyplot as plt
|
| 11 |
import seaborn as sns
|
| 12 |
import matplotlib.font_manager as fm
|
|
|
|
| 13 |
|
| 14 |
# --- 🌟 解決 Matplotlib 中文顯示問題 ---
|
| 15 |
font_path = 'SimHei.ttf'
|
|
@@ -57,19 +58,30 @@ try:
|
|
| 57 |
le_action = joblib.load('le_action.pkl')
|
| 58 |
le_ip = joblib.load('le_ip.pkl')
|
| 59 |
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 63 |
base_df = pd.read_csv('baseline_logs (1).csv')
|
| 64 |
else:
|
| 65 |
-
print("⚠️ 找不到
|
| 66 |
base_df = pd.DataFrame(columns=["timestamp", "ip_address", "cookie_id", "account", "role", "action", "status"])
|
| 67 |
|
| 68 |
# ☁️ 步驟 B:同步雲端動態歷史資料庫
|
| 69 |
print("🔄 正在從 Hugging Face 雲端同步最新動態歷史資料...")
|
| 70 |
dynamic_df = logger_service.sync_from_hf()
|
| 71 |
|
| 72 |
-
# 🤝 步驟 C:將靜態訓練資料與動態資料合併
|
| 73 |
if not dynamic_df.empty:
|
| 74 |
baseline_df = pd.concat([base_df, dynamic_df], ignore_index=True)
|
| 75 |
else:
|
|
@@ -78,21 +90,20 @@ try:
|
|
| 78 |
# 確保時間格式正確
|
| 79 |
baseline_df['timestamp'] = pd.to_datetime(baseline_df['timestamp'])
|
| 80 |
|
| 81 |
-
# 🧹 步驟 D:資料清洗 (強制切除 IP 後面的中文字串,保護 AI 模型)
|
| 82 |
baseline_df['clean_ip'] = baseline_df['ip_address'].astype(str).apply(lambda x: x.split(" ")[0])
|
| 83 |
|
| 84 |
-
# 📊
|
| 85 |
global_stats["total_count"] = len(baseline_df)
|
| 86 |
global_stats["abnormal_count"] = baseline_df[baseline_df['status'].str.contains("異常", na=False)].shape[0]
|
| 87 |
print(f"📊 統計初始化:總監測量 {global_stats['total_count']}, 異常數 {global_stats['abnormal_count']}")
|
| 88 |
|
| 89 |
-
# 📜
|
| 90 |
display_df = baseline_df.sort_values(by='timestamp', ascending=False).head(20).copy()
|
| 91 |
display_df['timestamp'] = display_df['timestamp'].dt.strftime('%Y-%m-%d %H:%M:%S')
|
| 92 |
-
# 這裡丟給介面的還是原本帶有中文說明的原始 IP 欄位
|
| 93 |
log_history = display_df[['timestamp', 'ip_address', 'cookie_id', 'account', 'role', 'action', 'status']].to_dict('records')
|
| 94 |
|
| 95 |
-
# 🚨
|
| 96 |
abnormal_mask = baseline_df['status'].astype(str).str.contains("異常", na=False)
|
| 97 |
if abnormal_mask.any():
|
| 98 |
abn_df_temp = baseline_df[abnormal_mask].sort_values(by='timestamp', ascending=False).copy()
|
|
@@ -186,7 +197,7 @@ def get_plot_data(selected_key):
|
|
| 186 |
action_code = ACTION_MAP.get(selected_key)
|
| 187 |
try:
|
| 188 |
plt.close('all')
|
| 189 |
-
# 📊
|
| 190 |
df_hist = baseline_df[baseline_df['action'] == action_code].copy()
|
| 191 |
|
| 192 |
# 加上啟動後即時產生的新資料
|
|
|
|
| 10 |
import matplotlib.pyplot as plt
|
| 11 |
import seaborn as sns
|
| 12 |
import matplotlib.font_manager as fm
|
| 13 |
+
import shutil
|
| 14 |
|
| 15 |
# --- 🌟 解決 Matplotlib 中文顯示問題 ---
|
| 16 |
font_path = 'SimHei.ttf'
|
|
|
|
| 58 |
le_action = joblib.load('le_action.pkl')
|
| 59 |
le_ip = joblib.load('le_ip.pkl')
|
| 60 |
|
| 61 |
+
print("📂 正在處理靜態訓練基底資料...")
|
| 62 |
+
static_file = 'static_train_data.csv'
|
| 63 |
+
|
| 64 |
+
# 🛡️【自動隔離防護盾】避免 5 萬筆資料被 logger_service 覆蓋
|
| 65 |
+
# 如果 baseline_logs.csv 存在且超過 500KB (大機率是 5 萬筆資料檔)
|
| 66 |
+
if os.path.exists('baseline_logs.csv') and os.path.getsize('baseline_logs.csv') > 500000:
|
| 67 |
+
if not os.path.exists(static_file):
|
| 68 |
+
shutil.copy('baseline_logs.csv', static_file)
|
| 69 |
+
print(f"🛡️ 系統防護:已自動將 5 萬筆訓練資料備份為 '{static_file}' 避免被雲端同步洗掉!")
|
| 70 |
+
|
| 71 |
+
# 📁 步驟 A:優先讀取被保護的靜態資料 (或原本的舊檔名)
|
| 72 |
+
if os.path.exists(static_file):
|
| 73 |
+
base_df = pd.read_csv(static_file)
|
| 74 |
+
elif os.path.exists('baseline_logs (1).csv'):
|
| 75 |
base_df = pd.read_csv('baseline_logs (1).csv')
|
| 76 |
else:
|
| 77 |
+
print("⚠️ 找不到靜態訓練資料,建立空資料表")
|
| 78 |
base_df = pd.DataFrame(columns=["timestamp", "ip_address", "cookie_id", "account", "role", "action", "status"])
|
| 79 |
|
| 80 |
# ☁️ 步驟 B:同步雲端動態歷史資料庫
|
| 81 |
print("🔄 正在從 Hugging Face 雲端同步最新動態歷史資料...")
|
| 82 |
dynamic_df = logger_service.sync_from_hf()
|
| 83 |
|
| 84 |
+
# 🤝 步驟 C:將靜態訓練資料與動態資料無縫合併
|
| 85 |
if not dynamic_df.empty:
|
| 86 |
baseline_df = pd.concat([base_df, dynamic_df], ignore_index=True)
|
| 87 |
else:
|
|
|
|
| 90 |
# 確保時間格式正確
|
| 91 |
baseline_df['timestamp'] = pd.to_datetime(baseline_df['timestamp'])
|
| 92 |
|
| 93 |
+
# 🧹 步驟 D:資料統一清洗 (強制切除 IP 後面的中文字串,保護 AI 模型)
|
| 94 |
baseline_df['clean_ip'] = baseline_df['ip_address'].astype(str).apply(lambda x: x.split(" ")[0])
|
| 95 |
|
| 96 |
+
# 📊 【功能 1】:統計資料整合 (包含 5萬筆 + 動態新增)
|
| 97 |
global_stats["total_count"] = len(baseline_df)
|
| 98 |
global_stats["abnormal_count"] = baseline_df[baseline_df['status'].str.contains("異常", na=False)].shape[0]
|
| 99 |
print(f"📊 統計初始化:總監測量 {global_stats['total_count']}, 異常數 {global_stats['abnormal_count']}")
|
| 100 |
|
| 101 |
+
# 📜 【功能 4】:即時 Log 顯示最新動態資料
|
| 102 |
display_df = baseline_df.sort_values(by='timestamp', ascending=False).head(20).copy()
|
| 103 |
display_df['timestamp'] = display_df['timestamp'].dt.strftime('%Y-%m-%d %H:%M:%S')
|
|
|
|
| 104 |
log_history = display_df[['timestamp', 'ip_address', 'cookie_id', 'account', 'role', 'action', 'status']].to_dict('records')
|
| 105 |
|
| 106 |
+
# 🚨 【功能 3】:異常 Log 分析區預先載入歷史異常 (涵蓋動靜態庫)
|
| 107 |
abnormal_mask = baseline_df['status'].astype(str).str.contains("異常", na=False)
|
| 108 |
if abnormal_mask.any():
|
| 109 |
abn_df_temp = baseline_df[abnormal_mask].sort_values(by='timestamp', ascending=False).copy()
|
|
|
|
| 197 |
action_code = ACTION_MAP.get(selected_key)
|
| 198 |
try:
|
| 199 |
plt.close('all')
|
| 200 |
+
# 📊 【功能 2】:圖表整合所有基準資料 (baseline_df 已包含靜態+動態)
|
| 201 |
df_hist = baseline_df[baseline_df['action'] == action_code].copy()
|
| 202 |
|
| 203 |
# 加上啟動後即時產生的新資料
|