”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 轻松拆分和重命名 Skyward 的 PDF

轻松拆分和重命名 Skyward 的 PDF

发布于2024-07-31
浏览:162

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/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 





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 学校,我希望这对您有所帮助。如果是这样,请鼓掌或考虑给我买杯咖啡。下次再见,顺风顺水。

版本声明 本文转载于:https://dev.to/blacknight318/easily-split-and-rename-pdfs-for-skyward-17ha?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 如何修复 macOS 上 Django 中的“配置不正确:加载 MySQLdb 模块时出错”?
    如何修复 macOS 上 Django 中的“配置不正确:加载 MySQLdb 模块时出错”?
    MySQL配置不正确:相对路径的问题在Django中运行python manage.py runserver时,可能会遇到以下错误:ImproperlyConfigured: Error loading MySQLdb module: dlopen(/Library/Python/2.7/site-...
    编程 发布于2024-12-21
  • Bootstrap 4 Beta 中的列偏移发生了什么?
    Bootstrap 4 Beta 中的列偏移发生了什么?
    Bootstrap 4 Beta:列偏移的删除和恢复Bootstrap 4 在其 Beta 1 版本中引入了重大更改柱子偏移了。然而,随着 Beta 2 的后续发布,这些变化已经逆转。从 offset-md-* 到 ml-auto在 Bootstrap 4 Beta 1 中, offset-md-*...
    编程 发布于2024-12-21
  • 尽管代码有效,为什么 POST 请求无法捕获 PHP 中的输入?
    尽管代码有效,为什么 POST 请求无法捕获 PHP 中的输入?
    解决 PHP 中的 POST 请求故障在提供的代码片段中:action=''而不是:action="<?php echo $_SERVER['PHP_SELF'];?>";?>"检查 $_POST数组:表单提交后使用 var_dump 检查 $_POST 数...
    编程 发布于2024-12-21
  • 大批
    大批
    方法是可以在对象上调用的 fns 数组是对象,因此它们在 JS 中也有方法。 slice(begin):将数组的一部分提取到新数组中,而不改变原始数组。 let arr = ['a','b','c','d','e']; // Usecase: Extract till index p...
    编程 发布于2024-12-21
  • 在 Go 中使用 WebSocket 进行实时通信
    在 Go 中使用 WebSocket 进行实时通信
    构建需要实时更新的应用程序(例如聊天应用程序、实时通知或协作工具)需要一种比传统 HTTP 更快、更具交互性的通信方法。这就是 WebSockets 发挥作用的地方!今天,我们将探讨如何在 Go 中使用 WebSocket,以便您可以向应用程序添加实时功能。 在这篇文章中,我们将介绍: WebSoc...
    编程 发布于2024-12-21
  • 如何使用 MySQL 查找今天生日的用户?
    如何使用 MySQL 查找今天生日的用户?
    如何使用 MySQL 识别今天生日的用户使用 MySQL 确定今天是否是用户的生日涉及查找生日匹配的所有行今天的日期。这可以通过一个简单的 MySQL 查询来实现,该查询将存储为 UNIX 时间戳的生日与今天的日期进行比较。以下 SQL 查询将获取今天有生日的所有用户: FROM USERS ...
    编程 发布于2024-12-21
  • 如何在 PHP 中组合两个关联数组,同时保留唯一 ID 并处理重复名称?
    如何在 PHP 中组合两个关联数组,同时保留唯一 ID 并处理重复名称?
    在 PHP 中组合关联数组在 PHP 中,将两个关联数组组合成一个数组是一项常见任务。考虑以下请求:问题描述:提供的代码定义了两个关联数组,$array1 和 $array2。目标是创建一个新数组 $array3,它合并两个数组中的所有键值对。 此外,提供的数组具有唯一的 ID,而名称可能重合。要求...
    编程 发布于2024-12-21
  • 除了“if”语句之外:还有哪些地方可以在不进行强制转换的情况下使用具有显式“bool”转换的类型?
    除了“if”语句之外:还有哪些地方可以在不进行强制转换的情况下使用具有显式“bool”转换的类型?
    无需强制转换即可上下文转换为 bool您的类定义了对 bool 的显式转换,使您能够在条件语句中直接使用其实例“t”。然而,这种显式转换提出了一个问题:“t”在哪里可以在不进行强制转换的情况下用作 bool?上下文转换场景C 标准指定了四种值可以根据上下文转换为的主要场景bool:语句:if、whi...
    编程 发布于2024-12-21
  • 插入数据时如何修复“常规错误:2006 MySQL 服务器已消失”?
    插入数据时如何修复“常规错误:2006 MySQL 服务器已消失”?
    插入记录时如何解决“一般错误:2006 MySQL 服务器已消失”介绍:将数据插入 MySQL 数据库有时会导致错误“一般错误:2006 MySQL 服务器已消失”。当与服务器的连接丢失时会出现此错误,通常是由于 MySQL 配置中的两个变量之一所致。解决方案:解决此错误的关键是调整wait_tim...
    编程 发布于2024-12-21
  • 如何在 Python 中访问和处理命令行参数?
    如何在 Python 中访问和处理命令行参数?
    在 Python 中处理命令行参数在 Python 中,命令行参数位于名为 sys.argv 的列表中。要访问这些参数,请使用以下语法:import sys # Print all command line arguments print("\n".join(sys.argv))...
    编程 发布于2024-12-20
  • Python If 语句中逻辑 AND (&&) 运算符的等价物是什么?
    Python If 语句中逻辑 AND (&&) 运算符的等价物是什么?
    Python中的If语句中&&(逻辑与)的等价是什么?在Python中,无法像其他编程语言那样使用&&作为逻辑与运算符。当使用if语句时,必须使用and关键字。示例:以下示例尝试使用&&作为逻辑与运算符,但会引发语法错误:if cond1 &amp;&amp; cond2:正确方法:...
    编程 发布于2024-12-20
  • 如何修改 Go 中作为函数参数传递的切片?
    如何修改 Go 中作为函数参数传递的切片?
    将切片作为函数参数传递并修改原始切片在 Go 中,将参数传递给函数是按值完成的,这意味着对参数所做的任何更改函数内的内容不会反映在原始变量中。当使用可变数据类型(例如切片)时,这可能会出现问题,因为附加到函数内的切片不会影响超出函数范围的原始切片。考虑以下示例:nums := []int{1, 2,...
    编程 发布于2024-12-20
  • 为什么模板类定义必须包含在头文件中?
    为什么模板类定义必须包含在头文件中?
    在头文件中包含模板类定义:必要性问题是为什么需要模板类的实现和声明驻留在同一头文件中。为了解决这个问题,至关重要的是要了解编译器需要访问整个模板定义(不仅仅是其签名)才能为模板的每个实例化生成代码。因此,函数定义必须移至标题。包含模型提供了对此要求的全面解释。本质上,当实例化模板类时,编译器会为该特...
    编程 发布于2024-12-20
  • 在 JavaScript 中使用浮点数时如何控制小数精度?
    在 JavaScript 中使用浮点数时如何控制小数精度?
    控制 JavaScript 中的小数精度在 JavaScript 中处理浮点数时,您可能会遇到需要控制小数点后显示的位数的情况观点。例如,您可能希望仅显示两位小数的价格。以固定精度格式化浮点型为了实现此目的,JavaScript 提供了 toFixed() 函数。该函数采用一个参数来指定要保留的小数...
    编程 发布于2024-12-20
  • 填充空 Python 列表时如何避免 IndexError?
    填充空 Python 列表时如何避免 IndexError?
    修复将元素分配给列表时的 IndexError尝试通过依次分配每个元素来创建列表时,您可能会遇到 IndexError如果目标列表最初为空。出现此错误的原因是您试图访问列表中不存在的索引。要解决此问题并将元素正确添加到列表中,您可以使用追加方法:for l in i: j.append(l)...
    编程 发布于2024-12-20

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3