使用Python搜索和替换PDF中的占位符文本

时间:2016-09-26 21:37:29

标签: python pdf

我需要生成模板文档的自定义PDF副本。 最简单的方法 - 我想 - 是创建一个源PDF,其中包含一些需要进行自定义的占位符文本,即<first_name><last_name>,然后用正确的值替换它们。

我搜索过高和低,但实际上没有办法基本上采用源模板PDF,用实际值替换占位符并写入新的PDF?

我查看了PyPDF2和ReportLab,但似乎都无法做到。 有什么建议?我的大多数搜索都导致使用Perl应用程序CAM :: PDF,但我更喜欢用Python保存它。

3 个答案:

答案 0 :(得分:6)

没有直接的方法来做到可靠地工作。 PDF与HTML不同:它们指定逐个字符的文本定位。它们甚至可能不包括用于呈现文本的整个字体,只包括呈现文档中特定文本所需的字符。我发现没有库会做更好的事情,比如在更新文本后重新包装段落。 PDF大部分是仅显示格式,因此使用将标记转换为PDF而不是就地更新PDF的工具会更好。

如果这不是一个选项,你可以在像Acrobat这样的东西中创建PDF form,然后使用像iText (AGPL)pdfbox这样的PDF操作库,它有一个很好的clojure包装器叫{ {3}}可以解决其中一些问题。

根据我的经验,Python对PDF编写的支持非常有限。到目前为止,Java是最好的语言支持。此外,您得到了您所支付的费用,因此如果您将其用于商业用途,则可能需要支付iText许可证。我已经有很好的结果编写python包装器围绕PDF操作CLI工具,如pdfboxing和ghostscript。对于您的用例而言,这可能比 更容易,而不是试图将其用于Python的PDF生态系统。

答案 1 :(得分:2)

没有明确的解决方案,但我找到了大多数时间都有效的解决方案。

在python中https://github.com/JoshData/pdf-redactor给出了很好的结果。以下是示例代码:

# Redact things that look like social security numbers, replacing the
# text with X's.
options.content_filters = [
        # First convert all dash-like characters to dashes.
        (
                re.compile(u"Tom Xavier"),
                lambda m : "XXXXXXX"
        ),

        # Then do an actual SSL regex.
        # See https://github.com/opendata/SSN-Redaction for why this regex is complicated.
        (
                re.compile(r"(?<!\d)(?!666|000|9\d{2})([OoIli0-9]{3})([\s-]?)(?!00)([OoIli0-9]{2})\2(?!0{4})([OoIli0-9]{4})(?!\d)"),
                lambda m : "XXX-XX-XXXX"
        ),
]

# Perform the redaction using PDF on standard input and writing to standard output.
pdf_redactor.redactor(options)

可以找到完整示例here

在ruby中https://github.com/gettalong/hexapdf适用于黑屏文本。 示例代码:

require 'hexapdf'

class ShowTextProcessor < HexaPDF::Content::Processor

  def initialize(page, to_hide_arr)
    super()
    @canvas = page.canvas(type: :overlay)
    @to_hide_arr = to_hide_arr
  end

  def show_text(str)
    boxes = decode_text_with_positioning(str)
    return if boxes.string.empty?
    if @to_hide_arr.include? boxes.string
        @canvas.stroke_color(0, 0 , 0)

        boxes.each do |box|
          x, y = *box.lower_left
          tx, ty = *box.upper_right
          @canvas.rectangle(x, y, tx - x, ty - y).fill
        end
    end

  end
  alias :show_text_with_positioning :show_text

end

file_name = ARGV[0]
strings_to_black = ARGV[1].split("|")

doc = HexaPDF::Document.open(file_name)
puts "Blacken strings [#{strings_to_black}], inside [#{file_name}]."
doc.pages.each.with_index do |page, index|
  processor = ShowTextProcessor.new(page, strings_to_black)
  page.process_contents(processor)
end

new_file_name = "#{file_name.split('.').first}_updated.pdf"
doc.write(new_file_name, optimize: true)

puts "Writing updated file [#{new_file_name}]."

在此处,您可以看到选定文字上的文字黑屏。

答案 2 :(得分:0)

作为另一种解决方案,您可以尝试Aspose.PDF Cloud SDK for Python,它提供了替换PDF文档中文本的功能。

首先,请安装适用于Python的Aspose.PDF Cloud SDK

pip install asposepdfcloud

示例代码将PDF文件上传到您的云存储,并替换PDF文档中的多个字符串

import os 
import asposepdfcloud 
from asposepdfcloud.apis.pdf_api import PdfApi 
 
# Get App key and App SID from https://aspose.cloud 
pdf_api_client = asposepdfcloud.api_client.ApiClient( 
    app_key='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 
    app_sid='xxxxx-xxxx-xxxx-xxxx-xxxxxxxx') 
 
pdf_api = PdfApi(pdf_api_client) 
filename = '02_pages.pdf' 
remote_name = '02_pages.pdf' 
 
#upload PDF file to storage 
pdf_api.upload_file(remote_name,filename) 
 
#Replace Text 
text_replace1 = asposepdfcloud.models.TextReplace(old_value='origami',new_value='aspose',regex='true') 
text_replace2 = asposepdfcloud.models.TextReplace(old_value='candy',new_value='biscuit',regex='true') 
text_replace_list = asposepdfcloud.models.TextReplaceListRequest(text_replaces=[text_replace1,text_replace2]) 
 
response = pdf_api.post_document_text_replace(remote_name, text_replace_list) 
print(response)

source and output PDF screenshots

我是aspose的开发人员布道者。