123Sabrina commited on
Commit
eac5970
·
verified ·
1 Parent(s): 38da418

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +156 -18
app.py CHANGED
@@ -10,17 +10,44 @@ import zipfile
10
  from io import BytesIO
11
  import pandas as pd
12
  from datetime import datetime
 
 
 
13
 
14
  class PDFOCRProcessor:
15
  def __init__(self):
16
  self.results = []
17
  self.processing_log = []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
  def log_message(self, message):
20
  """添加日誌訊息"""
21
  timestamp = datetime.now().strftime("%H:%M:%S")
22
  log_entry = f"[{timestamp}] {message}"
23
  self.processing_log.append(log_entry)
 
24
  return log_entry
25
 
26
  def download_pdf(self, url, filename):
@@ -37,20 +64,91 @@ class PDFOCRProcessor:
37
  self.log_message(f"❌ 下載失敗: {e}")
38
  return False
39
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  def pdf_to_text_ocr(self, pdf_path):
41
  """將PDF轉換為文字(使用OCR)"""
42
  try:
43
  self.log_message(f"🔍 開始OCR處理: {os.path.basename(pdf_path)}")
44
- images = convert_from_path(pdf_path, dpi=300)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
 
46
  all_text = ""
47
  for i, img in enumerate(images):
48
  self.log_message(f" 處理第 {i+1}/{len(images)} 頁...")
49
- text = pytesseract.image_to_string(img, lang='chi_tra')
50
- all_text += f"\n--- 第 {i+1} 頁 ---\n{text}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
 
52
  self.log_message(f"✅ OCR完成,共處理 {len(images)} 頁")
53
  return all_text
 
54
  except Exception as e:
55
  self.log_message(f"❌ OCR處理失敗: {e}")
56
  return None
@@ -216,8 +314,34 @@ def create_interface():
216
  1. 在下方文字框中輸入PDF網址(每行一個)
217
  2. 點擊「開始處理」按鈕
218
  3. 等待處理完成後,可以下載包含所有結果的ZIP檔案
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
219
  """)
220
 
 
 
 
 
 
 
 
 
 
221
  with gr.Row():
222
  with gr.Column(scale=2):
223
  pdf_urls_input = gr.Textbox(
@@ -258,6 +382,16 @@ def create_interface():
258
  )
259
 
260
  # 綁定處理函數
 
 
 
 
 
 
 
 
 
 
261
  process_btn.click(
262
  fn=processor.process_multiple_pdfs,
263
  inputs=[pdf_urls_input],
@@ -282,26 +416,30 @@ def create_interface():
282
 
283
  return app
284
 
285
- # 啟動應用
286
  if __name__ == "__main__":
287
- # 檢查必要套件
288
- required_packages = """
289
- 在運行此應用前,請確保已安裝以下套件:
290
-
291
- pip install gradio requests pdf2image pillow pytesseract pandas
292
 
293
- # Ubuntu/Debian 系統
294
- apt-get install -y tesseract-ocr tesseract-ocr-chi-tra poppler-utils
295
 
296
- # macOS 系統
297
- brew install tesseract tesseract-lang poppler
298
-
299
- # Windows 系統
300
- # 請下載並安裝 Tesseract OCR 和 Poppler
301
- """
 
302
 
303
- print(required_packages)
 
 
 
304
 
 
305
  app = create_interface()
306
  app.launch(
307
  server_name="0.0.0.0",
 
10
  from io import BytesIO
11
  import pandas as pd
12
  from datetime import datetime
13
+ import subprocess
14
+ import sys
15
+ import fitz # PyMuPDF 作為備用方案
16
 
17
  class PDFOCRProcessor:
18
  def __init__(self):
19
  self.results = []
20
  self.processing_log = []
21
+ self.check_dependencies()
22
+
23
+ def check_dependencies(self):
24
+ """檢查系統依賴"""
25
+ self.log_message("🔍 檢查系統依賴...")
26
+
27
+ # 檢查 poppler
28
+ try:
29
+ result = subprocess.run(['pdftoppm', '-h'], capture_output=True, text=True)
30
+ self.log_message("✅ Poppler 已安裝")
31
+ self.has_poppler = True
32
+ except FileNotFoundError:
33
+ self.log_message("⚠️ 未找到 Poppler,將使用 PyMuPDF 作為備用方案")
34
+ self.has_poppler = False
35
+
36
+ # 檢查 tesseract
37
+ try:
38
+ result = subprocess.run(['tesseract', '--version'], capture_output=True, text=True)
39
+ self.log_message("✅ Tesseract 已安裝")
40
+ self.has_tesseract = True
41
+ except FileNotFoundError:
42
+ self.log_message("❌ 未找到 Tesseract OCR")
43
+ self.has_tesseract = False
44
 
45
  def log_message(self, message):
46
  """添加日誌訊息"""
47
  timestamp = datetime.now().strftime("%H:%M:%S")
48
  log_entry = f"[{timestamp}] {message}"
49
  self.processing_log.append(log_entry)
50
+ print(log_entry) # 同時輸出到控制台
51
  return log_entry
52
 
53
  def download_pdf(self, url, filename):
 
64
  self.log_message(f"❌ 下載失敗: {e}")
65
  return False
66
 
67
+ def pdf_to_images_poppler(self, pdf_path):
68
+ """使用 poppler 將PDF轉換為圖片"""
69
+ try:
70
+ images = convert_from_path(pdf_path, dpi=300)
71
+ return images
72
+ except Exception as e:
73
+ self.log_message(f"❌ Poppler 轉換失敗: {e}")
74
+ return None
75
+
76
+ def pdf_to_images_pymupdf(self, pdf_path):
77
+ """使用 PyMuPDF 將PDF轉換為圖片"""
78
+ try:
79
+ doc = fitz.open(pdf_path)
80
+ images = []
81
+
82
+ for page_num in range(len(doc)):
83
+ page = doc.load_page(page_num)
84
+ # 提高解析度
85
+ mat = fitz.Matrix(2.0, 2.0) # 2x zoom
86
+ pix = page.get_pixmap(matrix=mat)
87
+ img_data = pix.tobytes("ppm")
88
+ img = Image.open(BytesIO(img_data))
89
+ images.append(img)
90
+
91
+ doc.close()
92
+ return images
93
+ except Exception as e:
94
+ self.log_message(f"❌ PyMuPDF 轉換失敗: {e}")
95
+ return None
96
+
97
  def pdf_to_text_ocr(self, pdf_path):
98
  """將PDF轉換為文字(使用OCR)"""
99
  try:
100
  self.log_message(f"🔍 開始OCR處理: {os.path.basename(pdf_path)}")
101
+
102
+ # 嘗試不同的PDF處理方法
103
+ images = None
104
+
105
+ if self.has_poppler:
106
+ self.log_message(" 使用 Poppler 轉換PDF...")
107
+ images = self.pdf_to_images_poppler(pdf_path)
108
+
109
+ if images is None:
110
+ self.log_message(" 使用 PyMuPDF 轉換PDF...")
111
+ images = self.pdf_to_images_pymupdf(pdf_path)
112
+
113
+ if images is None:
114
+ self.log_message("❌ 無法轉換PDF為圖片")
115
+ return None
116
+
117
+ if not self.has_tesseract:
118
+ self.log_message("❌ Tesseract 未安裝,無法進行OCR")
119
+ return None
120
 
121
  all_text = ""
122
  for i, img in enumerate(images):
123
  self.log_message(f" 處理第 {i+1}/{len(images)} 頁...")
124
+ try:
125
+ # 嘗試不同的OCR語言設定
126
+ ocr_langs = ['chi_tra', 'chi_sim', 'eng']
127
+ text = None
128
+
129
+ for lang in ocr_langs:
130
+ try:
131
+ text = pytesseract.image_to_string(img, lang=lang)
132
+ if text.strip(): # 如果有內容就使用
133
+ self.log_message(f" 使用 {lang} 語言模型成功")
134
+ break
135
+ except Exception as lang_error:
136
+ self.log_message(f" {lang} 語言模型失敗: {lang_error}")
137
+ continue
138
+
139
+ if text is None:
140
+ # 最後嘗試預設設定
141
+ text = pytesseract.image_to_string(img)
142
+
143
+ all_text += f"\n--- 第 {i+1} 頁 ---\n{text}"
144
+
145
+ except Exception as page_error:
146
+ self.log_message(f" 第 {i+1} 頁處理失敗: {page_error}")
147
+ all_text += f"\n--- 第 {i+1} 頁 ---\n[處理失敗]\n"
148
 
149
  self.log_message(f"✅ OCR完成,共處理 {len(images)} 頁")
150
  return all_text
151
+
152
  except Exception as e:
153
  self.log_message(f"❌ OCR處理失敗: {e}")
154
  return None
 
314
  1. 在下方文字框中輸入PDF網址(每行一個)
315
  2. 點擊「開始處理」按鈕
316
  3. 等待處理完成後,可以下載包含所有結果的ZIP檔案
317
+
318
+ ## 🔧 安裝說明:
319
+ 如果遇到依賴問題,請安裝以下套件:
320
+ ```bash
321
+ # Python 套件
322
+ pip install gradio requests pdf2image pillow pytesseract pandas PyMuPDF
323
+
324
+ # Ubuntu/Debian 系統
325
+ sudo apt-get update
326
+ sudo apt-get install -y tesseract-ocr tesseract-ocr-chi-tra poppler-utils
327
+
328
+ # macOS 系統
329
+ brew install tesseract tesseract-lang poppler
330
+
331
+ # Windows 系統
332
+ # 請下載安裝 Tesseract OCR 和 Poppler for Windows
333
+ ```
334
  """)
335
 
336
+ # 添加依賴檢查按鈕
337
+ with gr.Row():
338
+ check_deps_btn = gr.Button("🔍 檢查系統依賴", variant="secondary")
339
+ deps_status = gr.Textbox(
340
+ label="依賴狀態",
341
+ lines=3,
342
+ interactive=False
343
+ )
344
+
345
  with gr.Row():
346
  with gr.Column(scale=2):
347
  pdf_urls_input = gr.Textbox(
 
382
  )
383
 
384
  # 綁定處理函數
385
+ def check_dependencies():
386
+ processor_temp = PDFOCRProcessor()
387
+ status_lines = processor_temp.processing_log[-4:] # 取最後4行日誌
388
+ return '\n'.join(status_lines)
389
+
390
+ check_deps_btn.click(
391
+ fn=check_dependencies,
392
+ outputs=[deps_status]
393
+ )
394
+
395
  process_btn.click(
396
  fn=processor.process_multiple_pdfs,
397
  inputs=[pdf_urls_input],
 
416
 
417
  return app
418
 
 
419
  if __name__ == "__main__":
420
+ # 檢查並安裝必要套件
421
+ required_packages = [
422
+ "gradio", "requests", "pdf2image", "pillow",
423
+ "pytesseract", "pandas", "PyMuPDF"
424
+ ]
425
 
426
+ print("📦 檢查 Python 套件...")
427
+ missing_packages = []
428
 
429
+ for package in required_packages:
430
+ try:
431
+ __import__(package.lower().replace('-', '_'))
432
+ print(f"✅ {package}")
433
+ except ImportError:
434
+ print(f"❌ {package}")
435
+ missing_packages.append(package)
436
 
437
+ if missing_packages:
438
+ print(f"\n⚠️ 缺少套件: {', '.join(missing_packages)}")
439
+ print("請執行以下命令安裝:")
440
+ print(f"pip install {' '.join(missing_packages)}")
441
 
442
+ print("\n🚀 啟動 Gradio 應用...")
443
  app = create_interface()
444
  app.launch(
445
  server_name="0.0.0.0",