在真實應用場景中,許多 PDF 檔案的網址並不會以 .pdf 結尾。如果系統僅依靠「網址字串長相」來決定處理方式,這些 PDF 會被錯誤地送進一般網頁的處理通道。這會導致爬蟲套件強制讀取二進位亂碼,而 AI 則可能根據殘留的 Metadata(如標題、作者)產生嚴重的 Hallucination,自行編造出根本不存在的內文摘要。為了解決這個漏洞,我們必須將判斷資料格式的責任從 n8n 轉移到後端 FastAPI。
系統不再瞎猜網址,而是由 FastAPI 發送請求後,直接讀取伺服器真實回傳的 Content Type。若是 application/pdf 就交由 PDF 引擎解析;若是 text/html 則交由網頁爬蟲處理。這正是系統設計中「關注點分離」的最佳實踐。
因此我們需要修改原來的 /extract-url ,讓原本的網頁萃取功能升級為強大的 /extract-url 動態處理端點
pip install requests pypdf trafilatura
main.pyimport requests
import io
import trafilatura
from pypdf import PdfReader
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
並且將原本的 @app.post("/extract-web") 部分程式碼改為以下內容:
@app.post("/extract-url")
def extract_url(data: URLRequest):
try:
response = requests.get(data.url, timeout=10)
if response.status_code != 200:
raise HTTPException(status_code=400, detail="無法讀取該網址")
content_type = response.headers.get('Content-Type', '').lower()
if 'application/pdf' in content_type:
pdf_stream = io.BytesIO(response.content)
reader = PdfReader(pdf_stream)
text = "".join([page.extract_text() for page in reader.pages if page.extract_text()])
if not text.strip():
raise ValueError("無法從此 PDF 萃取文字(可能為圖片掃描檔)")
else:
text = trafilatura.extract(response.content)
if not text:
raise ValueError("無法萃取網頁正文")
return {
"status": "success",
"type": "pdf" if 'application/pdf' in content_type else "web",
"text": text
}
except Exception as e:
raise HTTPException(status_code=500, detail=f"網址解析失敗: {str(e)}")
修改完程式碼後要將 n8n 中處理 網址的 HTTP Request 節點的設定稍微修改,要將此節點的url修改成 http://host.docker.internal:8000/extract-url ,因為有修改他的名字。
這樣再去傳 pdf 網址的時候,就不會讀到二進制的亂碼,會成功讀到我們可以閱讀的文字。