幾週前,我的主管給了我一個挑戰,看看我是否可以針對我們遇到的特定問題提出一個工作流程。我們希望將 Pre/ACT 信件放入我們的 SMS(學生管理系統)中,在我們的例子中是 Skyward。我們遇到的問題是,Pre/ACT 信件要么是批量 PDF,要么是單獨的 PDF,要進入 Skyward,我們需要每個學生的姓名作為 ID 號碼的 PDF。為了實現這一目標,我決定用 Python 編寫一個程序,並使用 Streamlit 作為 UI。
讓我們看看我們需要解決的問題,從 PDF 開始。取得信件的大量單一 PDF 匯出更有意義,這意味著我們需要將批次匯出拆分為單獨的 PDF。雖然每個字母通常有 2 頁,但情況並非總是如此,因此每隔一頁進行簡單的分隔可能很容易出錯。
第二個問題是讀取每個學生的PDF並將其重新命名為對應的ID Number。這主要取決於能夠滿足我需求的正規表示式模式。
由於這也是一個時間挑戰,我與 AI 合作來幫助產生程式碼。注意:這並不能取代了解您正在使用的邏輯和語言。當使用 AI/LLM 編寫本文時,我使用了思維鏈方法,給出了我想要的小塊,然後在添加更多區塊之前調試和測試每個區塊。下面的程式碼是最終使用的程式碼,我將逐節分解每個程式碼。如果您希望在您的學區將此作為解決方案實施,請參閱本文末尾的 TLDR。
這部分相當簡單,是程式運作的基礎。
requirements.txt內容
streamlit pypdf2 fitz pymupdf
app.py 導入
import PyPDF2 import fitz # PyMuPDF import re from pathlib import Path import concurrent.futures import streamlit as st import shutil import zipfile import os
下一個片段涉及在批量 PDF 中查找 ID 並創建用於拆分它們的頁面列表,這是取決於正則表達式的部分,可能需要根據您的情況進行更改。
def find_id_pages(input_pdf): doc = fitz.open(input_pdf) id_pages = [] id_pattern = re.compile(r'\(ID#:\s*(\d+)\)') for i, page in enumerate(doc): text = page.get_text() if id_pattern.search(text): id_pages.append(i) return id_pages
如標題所說,這是用來分割PDF的。這將使用一個函數來提取每個 PDF 的名稱。您還會注意到,這會將它們並行拆分(一次最多 10 個),以提高效能。
def split_pdf(input_pdf, output_folder, progress_callback): input_path = Path(input_pdf) output_folder = Path(output_folder) output_folder.mkdir(parents=True, exist_ok=True) # Find pages with IDs id_pages = find_id_pages(input_pdf) if not id_pages: st.error("No ID pages found in the PDF.") return pdf_reader = PyPDF2.PdfReader(str(input_path)) total_pages = len(pdf_reader.pages) temp_pdfs = [] for i in range(len(id_pages)): start_page = id_pages[i] end_page = id_pages[i + 1] if i + 1 < len(id_pages) else total_pages pdf_writer = PyPDF2.PdfWriter() for j in range(start_page, end_page): pdf_writer.add_page(pdf_reader.pages[j]) temp_pdf_path = output_folder / f'temp_{i}.pdf' with open(temp_pdf_path, 'wb') as output_pdf: pdf_writer.write(output_pdf) temp_pdfs.append(temp_pdf_path) progress_callback((i + 1) / len(id_pages)) # Update progress bar # Process renaming in parallel with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor: executor.map(lambda pdf_path: extract_and_rename_pdf(pdf_path, output_folder), temp_pdfs)
def extract_and_rename_pdf(pdf_path, output_folder): doc = fitz.open(pdf_path) text_first_page = doc[0].get_text() # Extract ID using a regex pattern for the format (ID#: 01234) match_first_page = re.search(r'\(ID#:\s*(\d+)\)', text_first_page) if match_first_page: id_value = match_first_page.group(1) new_pdf_path = output_folder / f'{id_value}.pdf' pdf_path.rename(new_pdf_path) else: new_pdf_path = output_folder / f'unknown_{pdf_path.stem}.pdf' pdf_path.rename(new_pdf_path)
接下來是幾個簡短的函數,一個用於壓縮所有拆分的PDF(如果您想在內部伺服器上運行它),另一個用於清理任何臨時文件,這樣就不會出現PII 學生信息它不需要生存。
def zip_output_folder(output_folder, zip_name): shutil.make_archive(zip_name, 'zip', output_folder)
def clean_up(output_folder, zip_name): shutil.rmtree(output_folder) os.remove(f"{zip_name}.zip")
最後一段程式碼是用於 UI 的。 Streamlit 是一個多功能的 WebUI(是的,您可以單獨運行它)。經過幾次嘗試並考慮可用性。為了簡單起見,我將其簡化為上傳按鈕、操作按鈕(即分割)和下載按鈕以取得壓縮的 PDF。
# Streamlit App Portion st.title("PDF Splitter and Renamer") uploaded_file = st.file_uploader("Choose a PDF file", type="pdf") output_folder = "output_folder" if st.button("Split and Rename PDF"): if uploaded_file and output_folder: try: # Save uploaded file temporarily with open("temp_input.pdf", "wb") as f: f.write(uploaded_file.getbuffer()) progress_bar = st.progress(0) def update_progress(progress): progress_bar.progress(progress) split_pdf("temp_input.pdf", output_folder, update_progress) zip_name = "output_pdfs" zip_output_folder(output_folder, zip_name) st.success("PDF split and renamed successfully!") with open(f"{zip_name}.zip", "rb") as f: st.download_button( label="Download ZIP", data=f, file_name=f"{zip_name}.zip", mime="application/zip" ) # Remove temporary file Path("temp_input.pdf").unlink() clean_up(output_folder, zip_name) except Exception as e: st.error(f"An error occurred: {e}") else: st.error("Please upload a PDF file and specify an output folder.")
要啟動並執行,只需使用以下命令(假設為 Linux、WSL 和 MacOS)。您可以透過造訪 http://localhost:8501 來存取該應用程式。
git clone https://github.com/Blacknight318/act-to-sms.git cd act-to-sms python3 -m venv venv source venv/bin/activate pip install -r requirements.txt streamlit run app.py
如果您就讀 K12 學校,我希望這對您有幫助。如果是這樣,請鼓掌或考慮為我買杯咖啡。下次見,順風順水。
以上是輕鬆分割並重新命名 Skyward 的 PDF的詳細內容。更多資訊請關注PHP中文網其他相關文章!