Несколько недель назад мой руководитель дал мне задание посмотреть, смогу ли я придумать рабочий процесс для решения конкретной проблемы, с которой мы столкнулись. Мы хотели поместить письма Pre/ACT в нашу SMS (систему управления студентами), которой в нашем случае была Skyward. Проблема, с которой мы столкнулись, заключается в том, что письма Pre/ACT представлены либо в виде массового PDF-файла, либо в виде отдельного PDF-файла, и чтобы попасть в Skyward, нам понадобится PDF-файл с именем каждого студента в качестве его идентификационного номера. Для этого я решил написать программу на Python, используя Streamlit в качестве пользовательского интерфейса.
Давайте посмотрим на проблемы, которые нам нужно решить, начиная с PDF. Было разумнее просто получить массовый экспорт писем в один PDF-файл, это означало, что нам нужно было разделить массовый экспорт на отдельные PDF-файлы. Хотя каждое письмо обычно занимает две страницы, это не всегда так, поэтому простой разрыв каждой второй страницы может привести к ошибкам.
Вторая проблема заключалась в чтении PDF-файла каждого учащегося и переименовании его в соответствующий идентификационный номер. В основном это зависело от шаблона Regex, который извлекал то, что мне нужно.
Поскольку это также было проблемой времени, я работал с ИИ, чтобы помочь сгенерировать код. ПРИМЕЧАНИЕ. Это не заменяет знание логики и языка, которые вы используете. При написании этой статьи с помощью AI/LLM я использовал цепочку мыслей, давая небольшие фрагменты того, что мне нужно, а затем отлаживая и тестируя каждый фрагмент, прежде чем добавлять новые. Приведенный ниже код является окончательным использованным кодом. Я разберу каждый раздел по разделам. Если вы хотите реализовать это как решение в своем округе, см. TLDR в конце этого поста.
Эта часть довольно проста и является основой, на которой работает программа.
Содержимое файла require.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-файле и созданию списка страниц, которые будут использоваться для их разделения. Это та часть, которая зависит от регулярного выражения и, возможно, ее придется изменить в вашей ситуации.
Следующий фрагмент посвящен поиску идентификаторов в большом PDF-файле и созданию списка страниц, которые будут использоваться для их разделения. &&&]
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 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)Почти готово
Далее идет пара коротких функций: одна для архивирования всех разделенных PDF-файлов (на случай, если вы хотите запустить это на внутреннем сервере), а другая для очистки всех временных файлов, чтобы не висеть там, где хранятся личные данные учащихся. ему не обязательно жить.
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")Создание пользовательского интерфейса
Последний фрагмент кода предназначен для пользовательского интерфейса. Streamlit — это универсальный веб-интерфейс (да, вы можете запускать его в одиночку). После нескольких попыток и с учетом удобства использования. Чтобы упростить задачу, я свел ее к кнопке загрузки, кнопке действия (т. е. разделению) и кнопке загрузки для получения сжатых 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, надеюсь, вы найдете это полезным. Если да, хлопайте в ладоши или подумайте о том, чтобы купить мне кофе. До следующих встреч, попутного ветра и попутного моря.
Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.
Copyright© 2022 湘ICP备2022001581号-3