如何使用python和matplotlib向PDF文件添加页码?

问题描述 投票:0回答:8

我正在使用

PdfPages
中的
matplotlib
,我可以循环遍历每个图形对象并将每个图形对象保存为同一 PDF 中的单独页面:

from matplotlib.backends.backend_pdf import PdfPages
pp = PdfPages('output.pdf')
for fig in figs:
    pp.savefig(fig)
pp.close()

这效果很好。但是有没有办法为 PDF 中的每一页添加页码?

谢谢。

python pdf matplotlib
8个回答
8
投票

使用reportlib和PyPDF的一个很好的解决方案(基于this):

import os

from PyPDF4.pdf import PdfFileReader, PdfFileWriter
from reportlab.lib.units import mm
from reportlab.pdfgen import canvas


def create_page_pdf(num, tmp):
    c = canvas.Canvas(tmp)
    for i in range(1, num + 1):
        c.drawString((210 // 2) * mm, (4) * mm, str(i))
        c.showPage()
    c.save()


def add_page_numgers(pdf_path):
    """
    Add page numbers to a pdf, save the result as a new pdf
    @param pdf_path: path to pdf
    """
    tmp = "__tmp.pdf"

    writer = PdfFileWriter()
    with open(pdf_path, "rb") as f:
        reader = PdfFileReader(f, strict=False)
        n = reader.getNumPages()

        # create new PDF with page numbers
        create_page_pdf(n, tmp)

        with open(tmp, "rb") as ftmp:
            number_pdf = PdfFileReader(ftmp)
            # iterarte pages
            for p in range(n):
                page = reader.getPage(p)
                numberLayer = number_pdf.getPage(p)
                # merge number page with actual page
                page.mergePage(numberLayer)
                writer.addPage(page)

            # write result
            if writer.getNumPages():
                newpath = pdf_path[:-4] + "_numbered.pdf"
                with open(newpath, "wb") as f:
                    writer.write(f)
        os.remove(tmp)

6
投票

类似这样的:

from matplotlib.backends.backend_pdf import PdfPages
pp = PdfPages('output.pdf')
for n, fig in enumerate(figs):
    fig.text(4.25/8.5, 0.5/11., str(n+1), ha='center', fontsize=8)
    pp.savefig(fig)
pp.close()

2
投票

使用 numbering2pdf 库。

from numbering2pdf import add_numbering_to_pdf

add_numbering_to_pdf("old_file.pdf", "new_file.pdf")

1
投票

PyPDF2pdfrw 都可以让您叠加两个 PDF(例如,您可以生成一个仅包含页码的 PDF,并使用它为图像添加水印)。 pdfrw 有一个使用单个水印页面的水印示例,但是可以轻松修改为使用一组水印页面,每个水印页面对应一个页码。

如果您想要更高级,您可以使用reportlab 动态生成这些页面。

pdfrw 还具有一个功能,允许您将 PDF 页面导入到 reportlab 中,就好像它是图像一样。 有几个动态执行此操作的示例 - here 是一个很好的起点。

最后,rst2pdf(维护得不是很好,但对于简单的情况来说效果很好)还可以让您将 PDF 作为图像导入——它在底层使用 pdfrw 和 reportlab——因此您可以轻松地使用 restructedText 用图像创建文档嵌入的。 AFAIK,与 rst2pdf 发布版本一起使用的最佳报告实验室是 2.7。

(免责声明:我是 pdfrw 作者,并对 rst2pdf 做出了贡献。)


1
投票

这是我的答案,它使用 Matplotlib PDF 后端生成仅包含页码的 PDF,并使用 PyPDF2 将“页脚”PDF 与所需的 PDF 合并:

def add_header_footer(source_path, save_path, footer_pdf_path=None, start_page=0, header_text=None):
    ''' Adds header & footer info to existing PDFs '''
    footer_pdf_path = os.path.join(os.path.dirname(source_path), 'footer.pdf')
    reader = PdfReader(source_path)
    writer = PdfWriter()
    n_pages = len(reader.pages)

    # Step 1: generate header/footer PDF to be merged into source PDF
    pp = PdfPages(footer_pdf_path)
    for p in range(n_pages):
        fig = plt.figure(num=613, figsize=(8.5, 11), constrained_layout=1, facecolor='white')
        fig.patch.set_alpha(0)
        fig.text(0.48, 0.04, f'{p + 1} | <FOOTER TEXT>',
                 horizontalalignment='center', weight='bold',
                 verticalalignment='bottom', fontsize=6, color='grey')
        if header_text is not None:
            fig.text(0.1, 0.95, header_text,
                     horizontalalignment='left', weight='bold',
                     verticalalignment='center', fontsize=6, color='grey')
        pp.savefig(fig)
        plt.close()
    pp.close()
    footer_reader = PdfReader(footer_pdf_path)

    # Step 2: merge source PDF & header/footer PDF
    for index in list(range(start_page, n_pages)):
        content_page = reader.pages[index]
        footer_page = footer_reader.pages[index]
        mediabox = content_page.mediabox
        content_page.merge_page(footer_page)
        content_page.mediabox = mediabox
        writer.add_page(content_page)

    # Step 3: save merged PDF
    with open(save_path, "wb") as fp:
        writer.write(fp)

    return None

1
投票

PyPDF2 >= 2.10.0

要求:

# generate a page with a page number:
pip install reportlab --upgrade

# merge that numbered (otherwise empty) page with the original:
pip install PyPDF2 --upgrade

使用ofir dubi代码的稍微修改版本:

import os

from PyPDF2 import PdfReader, PdfWriter
from reportlab.lib.units import mm
from reportlab.pdfgen import canvas


def create_page_pdf(num, tmp):
    c = canvas.Canvas(tmp)
    for i in range(1, num + 1):
        c.drawString((210 // 2) * mm, (4) * mm, str(i))
        c.showPage()
    c.save()


def add_page_numgers(pdf_path, newpath):
    """
    Add page numbers to a pdf, save the result as a new pdf
    @param pdf_path: path to pdf
    """
    tmp = "__tmp.pdf"

    writer = PdfWriter()
    with open(pdf_path, "rb") as f:
        reader = PdfReader(f)
        n = len(reader.pages)

        # create new PDF with page numbers
        create_page_pdf(n, tmp)

        with open(tmp, "rb") as ftmp:
            number_pdf = PdfReader(ftmp)
            # iterarte pages
            for p in range(n):
                page = reader.pages[p]
                number_layer = number_pdf.pages[p]
                # merge number page with actual page
                page.merge_page(number_layer)
                writer.add_page(page)

            # write result
            if len(writer.pages) > 0:
                with open(newpath, "wb") as f:
                    writer.write(f)
        os.remove(tmp)


if __name__ == "__main__"
    add_page_numgers("input.pdf", "output.pdf")

0
投票

您还可以使用fpdf2(pip install fpdf2)。 如果您保存了图像,那么您可以执行以下操作:

from fpdf import FPDF
import glob

class MyPDF(FPDF):
    def footer(self):
        # position footer from bottom of page
        self.set_y(-0.6)
        # set the font, I=italic
        self.set_font("helvetica", style="I", size=8)
        # set page number and center it
        pageNum = f'- {self.page_no()} -'
        self.cell(0, 0.5, pageNum, align="C")

filenames = glob.iglob('*.jpg')
pdf = MyPDF()
pdf = MyPDF(orientation='P', unit='in', format='Letter')
for fname in filenames:
    pdf.add_page(orientation='P')
    pdf.image(fname, x=1.0, h=4.8)
pdf.output('Images.pdf')

0
投票

pdfnumbering 库对我来说效果很好。这是我用来将 12 点页码添加到 letter 大小的 PDF 底部中心的命令行代码:

pdfnumbering --font-size 12 --text-align center --text-position 0 740 --text-color 000000 --output pfn_merged_numbered.pdf pfn_merged.pdf

(您也可以在 Python 中使用此库。)

© www.soinside.com 2019 - 2024. All rights reserved.