Il y a quelques semaines, mon superviseur m'a lancé un défi pour voir si je pouvais proposer un flux de travail pour un problème particulier que nous rencontrions. Nous voulions intégrer les lettres Pre/ACT dans notre SMS (Student Management System), qui dans notre cas était Skyward. Le problème que nous avons rencontré est que les lettres Pre/ACT sont soit dans un PDF groupé, soit par PDF individuel, et pour accéder à Skyward, nous aurions besoin d'un PDF pour le nom de chaque élève comme numéro d'identification. Pour ce faire, j'ai décidé d'écrire un programme en Python, en utilisant Streamlit pour l'interface utilisateur.
Examinons les problèmes que nous devons résoudre, en commençant par le PDF. Il était plus logique de simplement récupérer l'exportation PDF unique en masse des lettres, cela signifiait que nous devions diviser l'exportation groupée en PDF individuels. Bien que chaque lettre fasse généralement 2 pages, ce n'est pas toujours le cas, donc une simple coupure d'une page sur deux est susceptible d'être sujette aux erreurs.
Le deuxième problème consistait à lire le PDF de chaque élève et à le renommer avec le numéro d'identification correspondant. Cela reposait principalement sur un modèle Regex qui tirait ce dont j'avais besoin.
Comme c'était aussi un défi de temps, j'ai travaillé avec l'IA pour aider à générer le code. REMARQUE : Cela ne remplace pas la connaissance de la logique et du langage que vous utilisez. Lors de l'écriture de ceci avec AI/LLM, j'ai utilisé l'approche de la chaîne de pensée, en donnant de petits morceaux de ce que je voulais, puis en déboguant et en testant chaque morceau avant d'en ajouter d'autres. Le code ci-dessous est le code final qui a été utilisé, je vais décomposer chaque section par section. Si vous cherchez à mettre en œuvre cette solution dans votre district, consultez les TLDR à la fin de cet article.
Cette partie est assez simple et constitue la base sur laquelle le programme fonctionne.
Contenu du fichier exigences.txt
streamlit pypdf2 fitz pymupdf
L'app.py importe
import PyPDF2 import fitz # PyMuPDF import re from pathlib import Path import concurrent.futures import streamlit as st import shutil import zipfile import os
Cet extrait suivant concerne la recherche des identifiants dans le PDF en masse et la création d'une liste de pages à utiliser pour les diviser. C'est la partie qui dépend de l'expression régulière et qui devra peut-être être modifiée en fonction de votre situation.
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
Comme le titre l'indique, ceci est utilisé pour diviser les PDF. Cela utilisera une fonction pour extraire les noms de chaque PDF individuel. Vous remarquerez également que cela les divise en parallèle, jusqu'à 10 à la fois, pour améliorer les performances.
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 1def 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)Presque là
Ensuite, quelques fonctions courtes, une pour compresser tous les PDF fractionnés (au cas où vous souhaiteriez l'exécuter sur un serveur interne), et une pour nettoyer tous les fichiers temporaires afin qu'il n'y ait aucune information PII sur les étudiants qui traîne où que ce soit. il n'a pas besoin de vivre.
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")Construire l'interface utilisateur
Le dernier morceau de code est destiné à l'interface utilisateur. Streamlit est une WebUI pour la polyvalence (oui, vous pouvez l'exécuter en solo). Après quelques tentatives et compte tenu de la convivialité. Pour faire simple, je l'ai résumé en un bouton de téléchargement, un bouton d'action (c'est-à-dire diviser) et un bouton de téléchargement pour obtenir les PDF compressés.
# 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 pour être opérationnel
Pour que les choses soient opérationnelles, utilisez simplement les commandes suivantes (cela suppose Linux, WSL et MacOS). et vous pourrez accéder à l'application en allant sur 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.pyEn conclusion
Si vous êtes dans une école K12, j'espère que cela vous sera utile. Si c'est le cas, applaudissez ou envisagez de m'offrir un café. A la prochaine fois, bon vent et mer favorable.
Clause de non-responsabilité: Toutes les ressources fournies proviennent en partie d'Internet. En cas de violation de vos droits d'auteur ou d'autres droits et intérêts, veuillez expliquer les raisons détaillées et fournir une preuve du droit d'auteur ou des droits et intérêts, puis l'envoyer à l'adresse e-mail : [email protected]. Nous nous en occuperons pour vous dans les plus brefs délais.
Copyright© 2022 湘ICP备2022001581号-3