dseditor commited on
Commit
8822081
·
verified ·
1 Parent(s): 718071b

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +191 -51
app.py CHANGED
@@ -1,4 +1,12 @@
1
- import gradio as gr
 
 
 
 
 
 
 
 
2
  import requests
3
  import json
4
  import os
@@ -170,7 +178,7 @@ def extract_abstract(text: str) -> str:
170
 
171
  return abstract_text if abstract_text else "無摘要資訊"
172
 
173
- def process_json_data(json_input: str) -> str:
174
  """處理JSON數據,補充缺失欄位"""
175
  try:
176
  # 解析輸入的JSON
@@ -196,6 +204,9 @@ def process_json_data(json_input: str) -> str:
196
  "摘要": ""
197
  }
198
 
 
 
 
199
  # 如果有下載位置,嘗試下載並提取資訊
200
  if download_url:
201
  print(f"正在處理: {collection_name}")
@@ -225,8 +236,11 @@ def process_json_data(json_input: str) -> str:
225
  if not author or author == "犯罪防治研究中心彙編":
226
  processed_item["作者"] = pdf_author
227
 
228
- # 設定摘要
229
- processed_item["摘要"] = extracted_info.get("abstract", "無摘要資訊")
 
 
 
230
 
231
  finally:
232
  # 清理臨時文件
@@ -235,11 +249,11 @@ def process_json_data(json_input: str) -> str:
235
  else:
236
  # 如果無法下載PDF,使用現有資訊
237
  processed_item["名稱"] = extract_title_from_collection(collection_name)
238
- processed_item["摘要"] = "無法獲取摘要資訊"
239
  else:
240
  # 如果沒有下載位置,使用現有資訊
241
  processed_item["名稱"] = extract_title_from_collection(collection_name)
242
- processed_item["摘要"] = "無下載位置,無法提取摘要"
243
 
244
  processed_data.append(processed_item)
245
 
@@ -249,27 +263,51 @@ def process_json_data(json_input: str) -> str:
249
  except Exception as e:
250
  return f"處理錯誤: {str(e)}"
251
 
252
- def save_json_file(json_data: str, filename: str) -> str:
253
- """保存JSON文件"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
254
  try:
255
- if not filename:
 
 
 
256
  filename = "processed_data.json"
257
 
258
  if not filename.endswith('.json'):
259
  filename += '.json'
260
 
261
  # 確保文件名安全
262
- filename = re.sub(r'[^\w\-_\.]', '_', filename)
263
 
264
  with open(filename, 'w', encoding='utf-8') as f:
265
  f.write(json_data)
266
 
267
- return f"文件已保存: {filename}"
268
  except Exception as e:
269
- return f"保存失敗: {str(e)}"
270
 
271
  # PDF網址處理函數
272
- def process_pdf_urls(urls_text: str) -> str:
273
  """處理PDF網址列表���直接提取資訊"""
274
  try:
275
  # 解析網址
@@ -279,6 +317,7 @@ def process_pdf_urls(urls_text: str) -> str:
279
  return "請輸入至少一個PDF網址"
280
 
281
  processed_data = []
 
282
 
283
  for i, url in enumerate(urls, 1):
284
  print(f"正在處理第 {i}/{len(urls)} 個PDF: {url}")
@@ -295,7 +334,7 @@ def process_pdf_urls(urls_text: str) -> str:
295
  item = {
296
  "名稱": extracted_info.get("title", f"PDF文件 {i}"),
297
  "作者": extracted_info.get("author", "未知作者"),
298
- "摘要": extracted_info.get("abstract", "無摘要資訊"),
299
  "下載位置": url,
300
  "論文集名稱": f"直接處理PDF {i}"
301
  }
@@ -311,7 +350,7 @@ def process_pdf_urls(urls_text: str) -> str:
311
  item = {
312
  "名稱": f"無法下載的PDF {i}",
313
  "作者": "未知作者",
314
- "摘要": "PDF下載失敗,無法提取摘要",
315
  "下載位置": url,
316
  "論文集名稱": f"處理失敗 {i}"
317
  }
@@ -345,14 +384,27 @@ with gr.Blocks(title="PDF資料處理器", theme=gr.themes.Soft()) as demo:
345
  json_input = gr.Textbox(
346
  label="輸入JSON資料",
347
  placeholder="請貼上您的JSON資料...",
348
- lines=10,
349
  value='[\n {\n "論文集名稱": "刑事政策與犯罪防治研究36",\n "作者": "犯罪防治研究中心彙編",\n "下載位置": "https://www.cprc.moj.gov.tw/media/20213330/3_36%E6%9C%9F%E5%85%A8%E5%88%8A%E4%B8%8B%E8%BC%89.pdf?mediaDL=true"\n }\n]'
350
  )
351
 
 
 
 
 
 
 
 
 
 
 
 
 
352
  filename_input1 = gr.Textbox(
353
- label="保存文件名",
354
  placeholder="例: processed_papers.json",
355
- value="processed_papers.json"
 
356
  )
357
 
358
  process_json_btn = gr.Button("處理JSON資料", variant="primary", size="lg")
@@ -360,7 +412,7 @@ with gr.Blocks(title="PDF資料處理器", theme=gr.themes.Soft()) as demo:
360
  with gr.Column(scale=2):
361
  output_json1 = gr.Textbox(
362
  label="處理結果",
363
- lines=20,
364
  show_copy_button=True
365
  )
366
 
@@ -381,14 +433,27 @@ with gr.Blocks(title="PDF資料處理器", theme=gr.themes.Soft()) as demo:
381
  pdf_urls_input = gr.Textbox(
382
  label="輸入PDF網址",
383
  placeholder="請輸入PDF網址,每行一個...\n\n例如:\nhttps://example.com/paper1.pdf\nhttps://example.com/paper2.pdf\nhttps://example.com/paper3.pdf",
384
- lines=12,
385
  value="https://www.cprc.moj.gov.tw/media/20213330/3_36%E6%9C%9F%E5%85%A8%E5%88%8A%E4%B8%8B%E8%BC%89.pdf?mediaDL=true"
386
  )
387
 
 
 
 
 
 
 
 
 
 
 
 
 
388
  filename_input2 = gr.Textbox(
389
- label="保存文件名",
390
  placeholder="例: pdf_extracted_data.json",
391
- value="pdf_extracted_data.json"
 
392
  )
393
 
394
  process_urls_btn = gr.Button("處理PDF網址", variant="primary", size="lg")
@@ -396,7 +461,7 @@ with gr.Blocks(title="PDF資料處理器", theme=gr.themes.Soft()) as demo:
396
  with gr.Column(scale=2):
397
  output_json2 = gr.Textbox(
398
  label="處理結果",
399
- lines=20,
400
  show_copy_button=True
401
  )
402
 
@@ -410,76 +475,151 @@ with gr.Blocks(title="PDF資料處理器", theme=gr.themes.Soft()) as demo:
410
  visible=False
411
  )
412
 
413
- def process_and_save_json(json_input, filename):
414
  # 處理JSON資料
415
- result = process_json_data(json_input)
 
 
 
 
 
 
 
 
 
 
 
416
 
417
  # 保存文件
418
- save_msg = save_json_file(result, filename)
 
 
 
 
 
419
 
420
  # 如果保存成功,提供下載
421
- if "已保存" in save_msg:
422
- return result, save_msg, gr.update(visible=True, value=filename)
423
  else:
424
  return result, save_msg, gr.update(visible=False)
425
 
426
- def process_and_save_urls(urls_input, filename):
427
  # 處理PDF網址
428
- result = process_pdf_urls(urls_input)
 
 
 
 
 
 
 
 
 
 
429
 
430
  # 保存文件
431
- save_msg = save_json_file(result, filename)
 
 
 
 
 
432
 
433
  # 如果保存成功,提供下載
434
- if "已保存" in save_msg:
435
- return result, save_msg, gr.update(visible=True, value=filename)
436
  else:
437
  return result, save_msg, gr.update(visible=False)
438
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
439
  # JSON處理按鈕事件
440
  process_json_btn.click(
441
  process_and_save_json,
442
- inputs=[json_input, filename_input1],
443
  outputs=[output_json1, save_status1, download_file1]
444
  )
445
 
446
  # PDF網址處理按鈕事件
447
  process_urls_btn.click(
448
  process_and_save_urls,
449
- inputs=[pdf_urls_input, filename_input2],
450
  outputs=[output_json2, save_status2, download_file2]
451
  )
452
 
453
  gr.Markdown("""
454
  ## 使用說明:
455
 
 
 
 
 
 
456
  ### JSON資料處理模式:
457
  1. 將現有的JSON資料貼入文本框
458
- 2. 系統會根據下載位置自動獲取PDF並補充缺失欄位
459
- 3. 適合處理已有部分資訊的資料集
 
 
460
 
461
  ### PDF網址直接處理模式:
462
  1. 直接貼入PDF網址,每行一個
463
- 2. 系統會自動下載並提取完整資訊
464
- 3. 適合批量處理新的PDF文件
 
 
 
 
 
 
 
 
465
 
466
- ### 通用功能:
467
- - 自動提取標題、作者、摘要
468
- - 避免重複內容
469
- - 生成標準化JSON格式
470
- - 支援文件下載
471
 
472
  ## 注意事項:
473
- - 處理時間取決於PDF文件大小和數量
474
- - 系統會自動清理重複的標題內容
475
- - 如果PDF無法下載,會使用預設資訊
476
  - 建議分批處理大量文件以獲得最佳效果
 
 
 
 
 
 
 
 
 
 
 
 
 
477
 
478
- ## 範例PDF網址格式:
479
  ```
480
- https://example.com/paper1.pdf
481
- https://example.com/paper2.pdf
482
- https://example.com/paper3.pdf
483
  ```
484
  """)
485
 
 
1
+ gr.Markdown("""
2
+ ## 使用說明:
3
+
4
+ ### 🆕 新功能特色:
5
+ - **🔄 智能檔名**: 自動使用論文集名稱或PDF標題作為JSON檔名
6
+ - **📝 手動摘要**: 可貼上現有摘要,避免重複提取
7
+ - **⚡ 高效處理**: 有摘要就不用下載PDF,節省時間
8
+
9
+ ### JSON資料import gradio as gr
10
  import requests
11
  import json
12
  import os
 
178
 
179
  return abstract_text if abstract_text else "無摘要資訊"
180
 
181
+ def process_json_data(json_input: str, manual_abstract: str = "") -> str:
182
  """處理JSON數據,補充缺失欄位"""
183
  try:
184
  # 解析輸入的JSON
 
204
  "摘要": ""
205
  }
206
 
207
+ # 如果有手動輸入的摘要,優先使用
208
+ use_manual_abstract = manual_abstract.strip()
209
+
210
  # 如果有下載位置,嘗試下載並提取資訊
211
  if download_url:
212
  print(f"正在處理: {collection_name}")
 
236
  if not author or author == "犯罪防治研究中心彙編":
237
  processed_item["作者"] = pdf_author
238
 
239
+ # 設定摘要:優先使用手動輸入,否則使用PDF提取的
240
+ if use_manual_abstract:
241
+ processed_item["摘要"] = use_manual_abstract
242
+ else:
243
+ processed_item["摘要"] = extracted_info.get("abstract", "無摘要資訊")
244
 
245
  finally:
246
  # 清理臨時文件
 
249
  else:
250
  # 如果無法下載PDF,使用現有資訊
251
  processed_item["名稱"] = extract_title_from_collection(collection_name)
252
+ processed_item["摘要"] = use_manual_abstract if use_manual_abstract else "無法獲取摘要資訊"
253
  else:
254
  # 如果沒有下載位置,使用現有資訊
255
  processed_item["名稱"] = extract_title_from_collection(collection_name)
256
+ processed_item["摘要"] = use_manual_abstract if use_manual_abstract else "無下載位置,無法提取摘要"
257
 
258
  processed_data.append(processed_item)
259
 
 
263
  except Exception as e:
264
  return f"處理錯誤: {str(e)}"
265
 
266
+ def generate_filename_from_collection(collection_name: str) -> str:
267
+ """根據論文集名稱生成安全的文件名"""
268
+ if not collection_name:
269
+ return "processed_data.json"
270
+
271
+ # 移除特殊字符,保留中英文、數字、連字符
272
+ safe_name = re.sub(r'[^\w\u4e00-\u9fff\-]', '_', collection_name)
273
+
274
+ # 移除多餘的下劃線
275
+ safe_name = re.sub(r'_+', '_', safe_name).strip('_')
276
+
277
+ # 限制長度
278
+ if len(safe_name) > 50:
279
+ safe_name = safe_name[:50]
280
+
281
+ # 確保有副檔名
282
+ if not safe_name.endswith('.json'):
283
+ safe_name += '.json'
284
+
285
+ return safe_name
286
+
287
+ def save_json_file(json_data: str, filename: str = None, auto_filename: bool = False, collection_name: str = None) -> tuple:
288
+ """保存JSON文件,支持自動文件名生成"""
289
  try:
290
+ # 如果啟用自動文件名且有論文集名稱,使用論文集名稱
291
+ if auto_filename and collection_name:
292
+ filename = generate_filename_from_collection(collection_name)
293
+ elif not filename:
294
  filename = "processed_data.json"
295
 
296
  if not filename.endswith('.json'):
297
  filename += '.json'
298
 
299
  # 確保文件名安全
300
+ filename = re.sub(r'[^\w\u4e00-\u9fff\-_\.]', '_', filename)
301
 
302
  with open(filename, 'w', encoding='utf-8') as f:
303
  f.write(json_data)
304
 
305
+ return f"文件已保存: {filename}", filename
306
  except Exception as e:
307
+ return f"保存失敗: {str(e)}", None
308
 
309
  # PDF網址處理函數
310
+ def process_pdf_urls(urls_text: str, manual_abstract: str = "") -> str:
311
  """處理PDF網址列表���直接提取資訊"""
312
  try:
313
  # 解析網址
 
317
  return "請輸入至少一個PDF網址"
318
 
319
  processed_data = []
320
+ use_manual_abstract = manual_abstract.strip()
321
 
322
  for i, url in enumerate(urls, 1):
323
  print(f"正在處理第 {i}/{len(urls)} 個PDF: {url}")
 
334
  item = {
335
  "名稱": extracted_info.get("title", f"PDF文件 {i}"),
336
  "作者": extracted_info.get("author", "未知作者"),
337
+ "摘要": use_manual_abstract if use_manual_abstract else extracted_info.get("abstract", "無摘要資訊"),
338
  "下載位置": url,
339
  "論文集名稱": f"直接處理PDF {i}"
340
  }
 
350
  item = {
351
  "名稱": f"無法下載的PDF {i}",
352
  "作者": "未知作者",
353
+ "摘要": use_manual_abstract if use_manual_abstract else "PDF下載失敗,無法提取摘要",
354
  "下載位置": url,
355
  "論文集名稱": f"處理失敗 {i}"
356
  }
 
384
  json_input = gr.Textbox(
385
  label="輸入JSON資料",
386
  placeholder="請貼上您的JSON資料...",
387
+ lines=8,
388
  value='[\n {\n "論文集名稱": "刑事政策與犯罪防治研究36",\n "作者": "犯罪防治研究中心彙編",\n "下載位置": "https://www.cprc.moj.gov.tw/media/20213330/3_36%E6%9C%9F%E5%85%A8%E5%88%8A%E4%B8%8B%E8%BC%89.pdf?mediaDL=true"\n }\n]'
389
  )
390
 
391
+ manual_abstract1 = gr.Textbox(
392
+ label="手動輸入摘要 (選填)",
393
+ placeholder="如果有摘要,請在此輸入。留空則自動從PDF中提取。",
394
+ lines=4
395
+ )
396
+
397
+ with gr.Row():
398
+ auto_filename1 = gr.Checkbox(
399
+ label="自動使用論文集名稱作為檔名",
400
+ value=True
401
+ )
402
+
403
  filename_input1 = gr.Textbox(
404
+ label="自訂文件名 (僅在未勾選自動檔名時使用)",
405
  placeholder="例: processed_papers.json",
406
+ value="processed_papers.json",
407
+ visible=False
408
  )
409
 
410
  process_json_btn = gr.Button("處理JSON資料", variant="primary", size="lg")
 
412
  with gr.Column(scale=2):
413
  output_json1 = gr.Textbox(
414
  label="處理結果",
415
+ lines=18,
416
  show_copy_button=True
417
  )
418
 
 
433
  pdf_urls_input = gr.Textbox(
434
  label="輸入PDF網址",
435
  placeholder="請輸入PDF網址,每行一個...\n\n例如:\nhttps://example.com/paper1.pdf\nhttps://example.com/paper2.pdf\nhttps://example.com/paper3.pdf",
436
+ lines=8,
437
  value="https://www.cprc.moj.gov.tw/media/20213330/3_36%E6%9C%9F%E5%85%A8%E5%88%8A%E4%B8%8B%E8%BC%89.pdf?mediaDL=true"
438
  )
439
 
440
+ manual_abstract2 = gr.Textbox(
441
+ label="手動輸入摘要 (選填)",
442
+ placeholder="如果有摘要,請在此輸入。留空則自動從PDF中提取。",
443
+ lines=4
444
+ )
445
+
446
+ with gr.Row():
447
+ auto_filename2 = gr.Checkbox(
448
+ label="自動使用第一個PDF標題作為檔名",
449
+ value=True
450
+ )
451
+
452
  filename_input2 = gr.Textbox(
453
+ label="自訂文件名 (僅在未勾選自動檔名時使用)",
454
  placeholder="例: pdf_extracted_data.json",
455
+ value="pdf_extracted_data.json",
456
+ visible=False
457
  )
458
 
459
  process_urls_btn = gr.Button("處理PDF網址", variant="primary", size="lg")
 
461
  with gr.Column(scale=2):
462
  output_json2 = gr.Textbox(
463
  label="處理結果",
464
+ lines=18,
465
  show_copy_button=True
466
  )
467
 
 
475
  visible=False
476
  )
477
 
478
+ def process_and_save_json(json_input, manual_abstract, auto_filename, custom_filename):
479
  # 處理JSON資料
480
+ result = process_json_data(json_input, manual_abstract)
481
+
482
+ # 獲取論文集名稱用於自動檔名
483
+ collection_name = ""
484
+ try:
485
+ data = json.loads(json_input)
486
+ if isinstance(data, list) and len(data) > 0:
487
+ collection_name = data[0].get("論文集名稱", "")
488
+ elif isinstance(data, dict):
489
+ collection_name = data.get("論文集名稱", "")
490
+ except:
491
+ pass
492
 
493
  # 保存文件
494
+ save_msg, actual_filename = save_json_file(
495
+ result,
496
+ custom_filename if not auto_filename else None,
497
+ auto_filename,
498
+ collection_name
499
+ )
500
 
501
  # 如果保存成功,提供下載
502
+ if actual_filename and "已保存" in save_msg:
503
+ return result, save_msg, gr.update(visible=True, value=actual_filename)
504
  else:
505
  return result, save_msg, gr.update(visible=False)
506
 
507
+ def process_and_save_urls(urls_input, manual_abstract, auto_filename, custom_filename):
508
  # 處理PDF網址
509
+ result = process_pdf_urls(urls_input, manual_abstract)
510
+
511
+ # 獲取第一個PDF的標題用於自動檔名
512
+ title_for_filename = ""
513
+ if auto_filename:
514
+ try:
515
+ data = json.loads(result)
516
+ if isinstance(data, list) and len(data) > 0:
517
+ title_for_filename = data[0].get("名稱", "")
518
+ except:
519
+ pass
520
 
521
  # 保存文件
522
+ save_msg, actual_filename = save_json_file(
523
+ result,
524
+ custom_filename if not auto_filename else None,
525
+ auto_filename,
526
+ title_for_filename
527
+ )
528
 
529
  # 如果保存成功,提供下載
530
+ if actual_filename and "已保存" in save_msg:
531
+ return result, save_msg, gr.update(visible=True, value=actual_filename)
532
  else:
533
  return result, save_msg, gr.update(visible=False)
534
 
535
+ # 控制文件名輸入框的顯示/隱藏
536
+ def toggle_filename_input1(auto_filename):
537
+ return gr.update(visible=not auto_filename)
538
+
539
+ def toggle_filename_input2(auto_filename):
540
+ return gr.update(visible=not auto_filename)
541
+
542
+ # 綁定checkbox事件
543
+ auto_filename1.change(
544
+ toggle_filename_input1,
545
+ inputs=[auto_filename1],
546
+ outputs=[filename_input1]
547
+ )
548
+
549
+ auto_filename2.change(
550
+ toggle_filename_input2,
551
+ inputs=[auto_filename2],
552
+ outputs=[filename_input2]
553
+ )
554
+
555
  # JSON處理按鈕事件
556
  process_json_btn.click(
557
  process_and_save_json,
558
+ inputs=[json_input, manual_abstract1, auto_filename1, filename_input1],
559
  outputs=[output_json1, save_status1, download_file1]
560
  )
561
 
562
  # PDF網址處理按鈕事件
563
  process_urls_btn.click(
564
  process_and_save_urls,
565
+ inputs=[pdf_urls_input, manual_abstract2, auto_filename2, filename_input2],
566
  outputs=[output_json2, save_status2, download_file2]
567
  )
568
 
569
  gr.Markdown("""
570
  ## 使用說明:
571
 
572
+ ### 🆕 新功能特色:
573
+ - **🔄 智能檔名**: 自動使用論文集名稱或PDF標題作為JSON檔名
574
+ - **📝 手動摘要**: 可貼上現有摘要,避免重複提取
575
+ - **⚡ 高效處理**: 有摘要就不用下載PDF,���省時間
576
+
577
  ### JSON資料處理模式:
578
  1. 將現有的JSON資料貼入文本框
579
+ 2. **可選**: 在摘要欄位貼上已知的摘要內容
580
+ 3. 勾選"自動使用論文集名稱作為檔名"(推薦)
581
+ 4. 系統會根據下載位置自動獲取PDF並補充缺失欄位
582
+ 5. 如果已提供摘要,系統將跳過PDF摘要提取,節省處理時間
583
 
584
  ### PDF網址直接處理模式:
585
  1. 直接貼入PDF網址,每行一個
586
+ 2. **可選**: 在摘要欄位貼上統一的摘要內容
587
+ 3. 勾選"自動使用第一個PDF標題作為檔名"(推薦)
588
+ 4. 系統會自動下載並提取完整資訊
589
+ 5. 如果已提供摘要,將應用到所有PDF條目
590
+
591
+ ### 檔名規則:
592
+ - **自動檔名**: 使用論文集名稱或PDF標題,自動清理特殊字符
593
+ - **自訂檔名**: 取消勾選自動檔名後可手動指定
594
+ - 檔名會自動加上`.json`副檔名
595
+ - 特殊字符會被替換為安全字符
596
 
597
+ ### 摘要處理優先順序:
598
+ 1. **手動輸入的摘要** (最高優先級)
599
+ 2. PDF中提取的摘要
600
+ 3. 預設訊息 ("無摘要資訊")
 
601
 
602
  ## 注意事項:
603
+ - 提供手動摘要可大幅加快處理速度
604
+ - 自動檔名會避免檔案系統不支援的字符
 
605
  - 建議分批處理大量文件以獲得最佳效果
606
+ - 系統會自動清理重複的標題內容
607
+
608
+ ## 範例使用情境:
609
+
610
+ ### 情境1: 已知摘要的快速處理
611
+ ```
612
+ 有現成的論文摘要 → 貼入摘要欄位 → 勾選自動檔名 → 快速處理
613
+ ```
614
+
615
+ ### 情境2: 完全自動化處理
616
+ ```
617
+ 只有PDF網址 → 留空摘要欄位 → 勾選自動檔名 → 全自動提取
618
+ ```
619
 
620
+ ### 情境3: 批量處理相同摘要
621
  ```
622
+ 多個PDF同一主題 → 輸入統一摘要 → 批量處理 → 節省時間
 
 
623
  ```
624
  """)
625