Recap: 昨天把履歷拆成欄位了,但輸入還是靠貼的
沒有人的履歷是純文字檔
從人力銀行下載、從 Word 匯出,拿到的都是 PDF
今天讓它可以上傳
全域範圍裡排除了雲端 PDF 解析服務,所以沒有 Document AI 那種選項pypdf 一個套件,page.extract_text() 一行就有文字
問題是抽出來的東西不一定能用
/extract/pdf 只做一件事:回傳抽出來的文字,然後停住
// 刻意只填進 textarea,不直接送分析:使用者確認過的文字才是分析的依據。
resumeText.value = data.text || "";
因為 pypdf 對版面複雜的履歷常常把欄位順序打亂
兩欄式排版會被拉成一長條,技能欄插進工作經歷中間
直接送去分析的話,使用者看到的是一份「不知道為什麼怪怪的」報告
而他永遠不會知道問題出在抽取那一步,不是模型
所以抽完先填進輸入框,讓他自己看、自己改,改完再按分析
畫面上寫「共 N 頁,抽出 N 個字。請確認下方文字是否正確」
抽取會失敗的狀況很多,但使用者能做的補救完全不同,所以訊息要分開
| 狀況 | 回什麼 | 使用者能做什麼 |
|---|---|---|
| 有密碼 | 400 | 先解除密碼再上傳 |
| 整份抽不出文字 | 422 | 改貼純文字,通常是掃描檔 |
| 只有某幾頁抽不到 | 200 + warning | 自己看那幾頁補上 |
| 超過 5 MB 或 10 頁 | 400 | 縮檔案 |
| 上傳的不是 PDF | 415 | — |
| 是 PDF 但檔案壞了 | 400 | — |
第三列是重點
一份十頁的履歷,第 7 頁是張圖,沒道理整份退回
except Exception: # pypdf 對破損頁面會丟各種例外,單頁失敗不該讓整份失敗
text = ""
一頁少於 20 個字就當作沒抽到,記進 empty_pages
最後回一句「第 7 頁幾乎沒有抽到文字,可能是圖片或掃描。請確認下方內容是否完整」
加密那邊有個陷阱:有些 PDF 只設了空密碼
所以先試 reader.decrypt(""),解不開才報錯
repo 裡不放真實履歷,happy path 沒東西可測
但這個模組大部分的工作本來就是處理壞輸入
空白頁 PDF 拿來當掃描檔用:
def _blank_pdf(pages: int = 1) -> bytes:
w = PdfWriter()
for _ in range(pages):
w.add_blank_page(width=595, height=842) # A4
五個測試:空檔、超大、不是 PDF、頁數超標、整份抽不出文字
最後一個順便斷言狀態碼是 422,不是 400
「檔案沒問題但內容抽不出來」跟「檔案有問題」要分得開
版本:pypdf 6.18.0、python-multipart 0.0.32、fastapi 0.141.1
輸入有了,結構也有了
明天開始對照:職缺要求一條一條拿去履歷裡找證據,找不到的就說找不到