Agentic Research
首頁/學習/機器怎麼讀懂財報:從 PDF 到結構化數據

機器怎麼讀懂財報:從 PDF 到結構化數據

2026/09/3010 分鐘君澤智庫最後更新 2026/09/30
這篇屬於學習主題財報解析OCRAI Agent港股

要做「AI 讀財報」,第一步不是挑模型,而是搞清楚一件事:你手上的 PDF,機器到底讀不進去。 很多人把年報丟給 AI 之後對結果失望,問題往往不在 AI 不夠聰明,而在文件根本沒有以機器可讀的形式進入模型。這篇把「從 PDF 到結構化數據」的路徑完整拆開:三種讀取方式、財報表格為什麼特別難、OCR 之後為什麼必須人工校對,以及最後應該輸出成什麼格式。

三種路徑:先判斷你的 PDF 是哪一種

先建立一個基本觀念:PDF 是「版面描述格式」,不是「數據格式」。 它記錄的是「在這一頁的這個座標畫哪個字」,而不是「這個數字是營業收入」。機器要讀懂財報,得先把版面還原成有意義的結構。

按這個標準,年報 PDF 分成三種,處理路徑完全不同:

PDF 類型特徵讀取路徑難度
文字層 PDF(數位原生)游標可以直接選取文字,複製出來是正確字元直接抽取文字層,不需要 OCR低
掃描檔 PDF(圖像)游標選不到文字,每一頁本質上是一張圖片必須先 OCR:從圖像辨識出文字高
混合型部分頁面可選取、部分不可逐頁判斷,分別走兩條路徑中

判斷方法很簡單:打開 PDF,試著用游標選取一段文字。選得到、複製出來正確,就是有文字層;選不到,是掃描檔;選得到但複製出來是亂碼,代表內嵌字體缺少正確的編碼對應表,實務上也要當掃描檔處理(轉圖像後 OCR)。港股年報三種都有:近年的報告多數是文字層,年代較久的報告掃描檔比例明顯更高,所以做歷史數據時更要逐份檢查。

三個技術名詞,一次講清楚:

名詞回答的問題說明
文字層抽取「這頁有哪些字?」直接讀 PDF 內嵌的文字資訊,速度快、準確率高,但只給你字,不給你結構
OCR(光學字元辨識)「這張圖片上有哪些字?」從圖像辨識文字,會輸出每個字的內容與信心度;辨識錯誤無法完全避免
版面分析「這些字是什麼關係?」判斷一塊文字是標題、內文還是表格儲存格,屬於表格的哪一列哪一欄。財報以表格為主,缺了版面分析,抽出來的數字就是一堆散沙

為什麼財報表格特別難

文字抽取只是入門。真正的難點在於,財報表格幾乎集中了所有讓機器頭痛的版面問題:

難點具體形態機器處理不好時的後果
跨頁表格附註裡的長表被切成兩頁,第二頁表頭可能只剩「(續)」兩個字第二頁的數字失去行標籤與列標籤,張冠李戴
合併儲存格「其中:」下面的子項共用一個大類標籤機器把子項當獨立行,數字層級錯亂
附註編號報表本體寫「見附註 18」,真正的數字在幾十頁之後只抽報表頁拿不到完整資訊,抽錯附註更危險
單位與幣別表頭寫著「人民幣千元」「港幣百萬元」漏讀這一行,所有數字錯幾個數量級
負數表示財務報表慣例用括號表示負數,不用減號括號被丟掉,方向整個相反
多年度欄位本期與上期欄位並排,有的還加比較附註欄位錯位,把上一年的數字當成本期
腳註與星號數字後面跟著上標 a、b、c,對應頁底說明上標在抽取時丟失,或被誤讀成數字的一部分

其中最陰險的是跨頁表格與單位。跨頁表格的錯誤是「看起來完全正常」的:每一行都有數字,只是配錯了標籤,除非你回去看原始頁面,否則不會發現。單位的錯誤則是系統性的:表頭一個「千元」沒讀到,整張表全部放大或縮小一千倍,而且表內部的加總關係依然成立,勾稽檢查也抓不出來——這類錯誤只能靠「錨點數字對帳」防住(下文與 300 頁年報轉結構化 JSON:三表與分部數據 會展開)。

工具選型:三代技術路線

讀財報的工具大致經歷了三代路線,選型時按手上的文件類型匹配,而不是追新:

路線適用場景優點主要風險
版面解析函式庫文字層 PDF快、便宜、結果確定(同樣輸入永遠同樣輸出)依賴 PDF 內部結構,版面稍特殊就容易解析失敗
OCR+版面分析引擎掃描檔、混合文件通吃所有文件類型,開源方案成熟辨識錯誤不可完全避免,必須配校對環節
多模態大模型(VLM)快速原型、版面極複雜的文件省事:頁面圖像進去、結構化結果出來幻覺:讀不到時可能「憑常識」補一個而不是承認讀不到;逐頁成本較高

第一代路線的常見選擇是開源的 PDF 解析函式庫(例如 pdfplumber、PyMuPDF 這類工具),按座標與線框把文字和表格抽出來。第二代路線以 PaddleOCR 等開源引擎為代表,本站對港股年報做過完整的端到端實測,見 PaddleOCR 實戰:83 秒提取港股年報財務數據。第三代路線目前最活躍,也最需要警惕:「什麼都能讀」的模型,同時也是「什麼都敢編」的模型——用它時必須搭配下文的人工校對與勾稽機制,而且數字類產出一律回查原頁。

三代路線並不互斥,實務上常混用:文字層頁面走解析函式庫,掃描頁面走 OCR,兩條路結果分歧的頁面才交給人工或多模態模型裁定。這樣成本最低,而且每一頁的處理路徑都有記錄可查。

OCR 之後:為什麼還需要人工校對

OCR 引擎會對每個辨識結果給出一個信心度(confidence,介於 0 與 1 之間的數值,代表引擎對自己這次辨識的把握)。信心度高不等於正確,但在財務場景,辨識錯誤的代價結構非常不對稱:錯誤率很低,但單個錯誤的代價極高。

錯誤類型辨識錯誤示例後果
形近字元混淆1 與 7、0 與 8、5 與 6 互認單一數字差數倍
千分位符號逗號被誤讀成 1 或小數點數量級錯誤
小數點位置小數點漏認或錯位十倍、百倍偏差
負號遺失括號或減號沒被當成數字的一部分方向反轉,資產變負債
行列錯位版面分析把數字配到隔壁科目數字本身對,意義全錯

所以實務上不是「要不要校對」,而是「怎麼校對才劃算」。四條策略:

  1. 分級校對:三大報表與關鍵附註全量校對;董事會報告、業務回顧等文字頁抽樣即可。
  2. 先錨點、後明細:先核對「應該平」的數字——各表的合計、小計、勾稽關係(例如資產總計是否等於負債加權益)。錨點全對,代表大結構沒塌;再抽查明細項。
  3. 雙引擎比對:同一頁用兩個不同的 OCR 引擎(或不同模型)各跑一次,結果一致的自動通過,不一致的才進人工。人力集中在分歧點,效率最高。
  4. 低信心優先:保留每個數字的信心度,按信心度由低到高排序人工核對,把時間花在刀刃上。

結構化輸出:JSON schema 的概念

抽取的終點不是「一堆文字」,而是「可查詢、可校驗、可比對的數據」。這裡需要兩個名詞:

  • JSON:一種用鍵值對儲存資料的文字格式,機器與人都讀得懂,是結構化數據的事實標準。
  • Schema(綱要):對「這份 JSON 應該有哪些欄位、每個欄位是什麼型別、哪些必填」的書面約定。可以理解成一張制式表格的模板:先定好格子,資料只能填進格子裡。

財報結構化最重要的設計原則只有一條:每個數字都要帶著三樣東西一起存——數值本身、來源座標(第幾頁)、處理狀態(校對過沒有)。 以下為教學用假設數字,非任何真實公司:

{
  "meta": {
    "company": "教學用假設公司",
    "fiscalYear": "2025",
    "currency": "HKD",
    "unit": "thousand",
    "sourceFile": "ar2025.pdf"
  },
  "incomeStatement": {
    "revenue": {
      "value": 1000000,
      "page": 88,
      "ocrConfidence": 0.99,
      "humanVerified": true
    },
    "grossProfit": {
      "value": 300000,
      "page": 88,
      "ocrConfidence": 0.97,
      "humanVerified": false
    }
  }
}

注意範例裡的細節:幣別與單位寫在 meta 而不是靠人記憶;每個數值都掛著頁碼;humanVerified 明確標出哪些數字還沒人看過。這樣的設計帶來三個好處:

好處說明
可校驗欄位缺失、單位未宣告,程式可以直接報錯,不靠自覺
可比對多份年報用同一套 schema,就能直接合併成多年數據表
可回溯三個月後質疑任何一個數字,都能沿著頁碼回到原始文件

完整的 schema 設計、欄位對應與勾稽校對機制,在 300 頁年報轉結構化 JSON:三表與分部數據 有端到端的實作。

AI 會在這裡出錯

最後照本站慣例,把這一環節的典型錯誤與驗證方法整理成清單:

出錯形態為什麼危險驗證方法
把掃描檔直接丟給對話模型要數字模型讀不到圖像內容時,可能「憑常識」編一個合理數字給你,而不是告訴你讀不到先確認 PDF 類型;要求模型回報「無法讀取」而不是猜測
單位假設錯誤模型不看表頭的「千元」「百萬元」,用預設單位輸出每個抽取結果強制帶單位與幣別欄位
跨頁表格靜默配錯輸出看起來完全正常,錯誤無法從結果本身發現對照原始頁面抽查跨頁表格的接續處
把信心度當準確率信心度 0.99 只代表引擎自認有把握,不代表對關鍵數字一律人工回看原頁,不信任何單一指標

發布前的最終檢查清單:

  • 已確認每份 PDF 的類型(文字層/掃描/混合)
  • 每張表的單位與幣別都已記錄在結構化數據中
  • 錨點數字(各表合計與勾稽關係)已對帳通過
  • 關鍵數字已抽樣回看原始頁面
  • 每個數字都保留來源頁碼與校對狀態

下一步