輕鬆分割並重新命名 Skyward 的 PDF

王林
發布: 2024-07-30 01:14:33
原創
769 人瀏覽過

Easily Split and Rename PDFs for Skyward

為什麼要建造它以及它有什麼作用

幾週前,我的主管給了我一個挑戰,看看我是否可以針對我們遇到的特定問題提出一個工作流程。我們希望將 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。

要求和進口

這部分相當簡單,是程式運作的基礎。

  • 我們的 UI 的 Streamlit
  • 用於 PDF 操作的 pypdf2、pymupdf 和 fitz

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
登入後複製

尋找ID

下一個片段涉及在批量 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的。這將使用一個函數來提取每個 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.")
登入後複製

TLDR 啟動並運行

要啟動並執行,只需使用以下命令(假設為 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中文網其他相關文章!

來源:dev.to
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!