feat(t73): Excel/CSV 抽取器——企業用很多(leo)

leo 兩句定調:
①「要思考 Excel 和 csv 的問題,因為企業用很多」
②「企業的 excel 通常不會是 1 萬行,人工做不出這麼多,但你可以轉結構資料丟進去」
→ 修正我先前「CSV 會變數字牆、先不加」的判斷——那是拿機器產生的百萬列當前提。
   實測 60列x6欄 ≈ 2,200 token,對 LLM 完全不是問題。

統一中間格式=Markdown(leo 提 n8n 對照後定調):
n8n 一切轉 JSON 是對的,因為它下游是程式(.欄位 取值);
我們下游是 LLM ⇒ Markdown 表格更好。實測同一份表格
JSON 6,872 字元 vs Markdown 3,341=JSON 多花 2.1 倍 token(每列重複寫欄位名)。

測試 8/8,用 openpyxl 產的真 Excel 檔(非自捏 XML):
   測試抓到兩個真 bug(讀原始碼看不出來):
     ① rels 的 Target 是絕對路徑 /xl/... 我卻又補 xl/ 前綴 → 變 xl/xl/...
     ② r:id 帶 namespace,寫 xml:"id,attr" 抓不到,要用完整 namespace URI
     修好後分頁名從 ## sheet1 變成 ## 維修紀錄(企業分頁名本身就是語意)
  CSV:去 BOM(Excel 另存必帶)/引號內逗號不拆欄/| 跳脫/欄數不齊不整份失敗
  XLSX:多工作表全讀(只取第一頁會漏)/sharedStrings 索引/壞檔報錯

防呆:超過 500 列截斷並明說截斷了(不靜默丟資料);單格超 500 字截斷。
This commit is contained in:
2026-07-27 20:50:45 +08:00
parent 09bf454402
commit 12c8098b5f
4 changed files with 467 additions and 2 deletions
+14 -1
View File
@@ -42,10 +42,23 @@ type extractor func(data []byte) (string, error)
// extractors=格式→師傅的對照表。加新格式只要在這裡註冊一行。
//
// .md/.markdown/.txt 不在此表:它們本來就是純文字,走 passthrough(見 ConvertToText)。
// **統一中間格式=Markdown**2026-07-27leo 提 n8n 對照後定調)。
//
// leo:「其實 n8n 把一切 extract 都轉成 json,因為**它內部跑 json**」——這個觀察是對的,
// 而且點出「**統一中間格式**」本身就是價值。差別在下游是誰:
//
// n8n 的下游是**程式**(節點之間要 `$json.欄位` 取值)→ JSON 可定址,正確。
// 我們的下游是 **LLM**(讀完寫知識卡)→ Markdown 表格更好。
//
// 實測(60 列 × 6 欄的維修紀錄表):JSON 6,872 字元 vs Markdown 3,341 字元,
// **JSON 多花 2.1 倍 token**——因為每一列都要重複寫一次欄位名。
// 且 Markdown 與卡片格式同語言,萃出來的卡自然帶得走表格。
var extractors = map[string]extractor{
".docx": extractDocx,
".csv": extractCSV,
".xlsx": extractXLSX,
// .pdf → PDFium-via-wazero(下一步接;體積 +10.43MB,實測 15頁/2.2MB=134ms
// .pptx/.xlsx → 同 docx 的 ZIP+XML 路數,數十行,體積幾乎不變POC 實測 +0.31MB
// .pptx → 同 docx 的 ZIP+XML 路數,數十行,體積幾乎不變
}
// IsPlainText 回報這個副檔名是否本來就是純文字(不需要轉檔)。