在 Python 中搜索和替换 pdf 中的文本

新手上路,请多包涵

我正在编写邮件合并软件作为 Python 网络应用程序的一部分。

我有一个名为 letter.pdf 的模板,它是从 MS Word 文件生成的,包含文本 {name},居民的姓名将用于此位置。我还有一个c的列表。 100个居民的名字。

我想做的是读入 letter.pdf 搜索 "{name}" 并将其替换为居民姓名(对于每个居民),然后将结果写入另一个 pdf。然后我想将所有这些 pdf 一起收集成一个大 pdf(每个字母一页),我的网络应用程序的用户将打印出来以创建他们的字母。

是否有任何 Python 库可以执行此操作?我看过 pdfrw 和 pdfminer,但我看不出他们在哪里可以做到这一点。

(注意:我也有 MS Word 文件,所以如果有另一种使用它的方法,而不是通过 pdf,那也可以完成这项工作。)

原文由 Phil Hunt 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 2.2k
1 个回答

这可以通过 PyPDF2 包来完成。实现可能取决于原始 PDF 模板结构。但是,如果模板足够稳定并且不经常更改,则替换代码不应该是通用的,而应该是简单的。

我做了一个关于如何替换 PDF 文件 中的文本的小草图。它将所有出现的 PDF 标记替换为 DOC

 import os
import argparse
from PyPDF2 import PdfFileReader, PdfFileWriter
from PyPDF2.generic import DecodedStreamObject, EncodedStreamObject

def replace_text(content, replacements = dict()):
    lines = content.splitlines()

    result = ""
    in_text = False

    for line in lines:
        if line == "BT":
            in_text = True

        elif line == "ET":
            in_text = False

        elif in_text:
            cmd = line[-2:]
            if cmd.lower() == 'tj':
                replaced_line = line
                for k, v in replacements.items():
                    replaced_line = replaced_line.replace(k, v)
                result += replaced_line + "\n"
            else:
                result += line + "\n"
            continue

        result += line + "\n"

    return result

def process_data(object, replacements):
    data = object.getData()
    decoded_data = data.decode('utf-8')

    replaced_data = replace_text(decoded_data, replacements)

    encoded_data = replaced_data.encode('utf-8')
    if object.decodedSelf is not None:
        object.decodedSelf.setData(encoded_data)
    else:
        object.setData(encoded_data)

if __name__ == "__main__":
    ap = argparse.ArgumentParser()
    ap.add_argument("-i", "--input", required=True, help="path to PDF document")
    args = vars(ap.parse_args())

    in_file = args["input"]
    filename_base = in_file.replace(os.path.splitext(in_file)[1], "")

    # Provide replacements list that you need here
    replacements = { 'PDF': 'DOC'}

    pdf = PdfFileReader(in_file)
    writer = PdfFileWriter()

    for page_number in range(0, pdf.getNumPages()):

        page = pdf.getPage(page_number)
        contents = page.getContents()

        if isinstance(contents, DecodedStreamObject) or isinstance(contents, EncodedStreamObject):
            process_data(contents, replacements)
        elif len(contents) > 0:
            for obj in contents:
                if isinstance(obj, DecodedStreamObject) or isinstance(obj, EncodedStreamObject):
                    streamObj = obj.getObject()
                    process_data(streamObj, replacements)

        writer.addPage(page)

    with open(filename_base + ".result.pdf", 'wb') as out_file:
        writer.write(out_file)

结果是

原始PDF替换PDF

更新 2021-03-21:

更新了代码示例以处理 DecodedStreamObjectEncodedStreamObject 这实际上包含要更新的文本数据流。

原文由 Dmytro 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题