「Python實用祕技04」為pdf檔案批量新增文字水印

費弗裡發表於2022-01-20

本文完整示例程式碼及檔案已上傳至我的Github倉庫https://github.com/CNFeffery/PythonPracticalSkills

  這是我的系列文章「Python實用祕技」的第4期,本系列立足於筆者日常工作中使用Python積累的心得體會,每一期為大家帶來一個3分鐘即可學會的簡單小技巧。

  作為系列第4期,我們即將學習的是:為pdf檔案批量新增文字水印

「Python實用祕技04」為pdf檔案批量新增文字水印

  有些情況下我們需要為單個或多個pdf檔案新增文字水印,尤其是那種需要在每一頁按照一定間距鋪滿的文字水印。而藉助reportlabpikepdf這兩個實用的pdf檔案操作庫,我們就可以很方便地實現批量文字水印新增工作。

  利用pip install reportlab pikepdf 完成安裝後,我們就可以按照步驟來實現需要的功能:

  • 生成指定的文字水印pdf檔案

  為了向目標pdf檔案新增水印,我們首先需要有單獨的pdf格式的文字水印檔案,我用reportlab編寫了一個方便易用的函式來生成水印檔案,你可以通過註釋來仔細學習其中的步驟,也可以直接呼叫即可:

from typing import Union, Tuple
from reportlab.lib import units
from reportlab.pdfgen import canvas
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont

# 註冊字型,這裡的字型是我從windows的字型目錄下複製過來的
pdfmetrics.registerFont(TTFont('msyh', r'./msyh.ttc'))

def create_watermark(content: str,
                     filename: str, 
                     width: Union[int, float], 
                     height: Union[int, float], 
                     font: str, 
                     fontsize: int,
                     angle: Union[int, float] = 45,
                     text_stroke_color_rgb: Tuple[int, int, int] = (0, 0, 0),
                     text_fill_color_rgb: Tuple[int, int, int] = (0, 0, 0),
                     text_fill_alpha: Union[int, float] = 1) -> None:
    '''
    用於生成包含content文字內容的水印pdf檔案
    content: 水印文字內容
    filename: 匯出的水印檔名
    width: 畫布寬度,單位:mm
    height: 畫布高度,單位:mm
    font: 對應註冊的字型代號
    fontsize: 字號大小
    angle: 旋轉角度
    text_stroke_color_rgb: 文字輪廓rgb色
    text_fill_color_rgb: 文字填充rgb色
    text_fill_alpha: 文字透明度
    '''

    # 建立pdf檔案,指定檔名及尺寸,這裡以畫素單位為例
    c = canvas.Canvas(f"{filename}.pdf", pagesize = (width*units.mm, height*units.mm))
    
    # 進行輕微的畫布平移保證文字的完整
    c.translate(0.1*width*units.mm, 0.1*height*units.mm)
    
    # 設定旋轉角度
    c.rotate(angle)
    
    # 設定字型及字號大小
    c.setFont(font, fontsize)
    
    # 設定文字輪廓色彩
    c.setStrokeColorRGB(*text_stroke_color_rgb)
    
    # 設定文字填充色
    c.setFillColorRGB(*text_fill_color_rgb)
    
    # 設定文字填充色透明度
    c.setFillAlpha(text_fill_alpha)
    
    # 繪製文字內容
    c.drawString(0, 0, content)
    
    # 儲存水印pdf檔案
    c.save()

  下面我們就利用這個函式來生成水印檔案:

# 製造示例文字水印pdf檔案
create_watermark(content='公眾號【Python大資料分析】作者:費弗裡', 
                 filename='水印示例', 
                 width=200,
                 height=200, 
                 font='msyh', 
                 fontsize=35,
                 text_fill_alpha=0.3)

  看看效果,非常的不錯,具體使用時,你可以自己動手調參以找到大小以及畫幅都令你滿意的水印匯出結果:

「Python實用祕技04」為pdf檔案批量新增文字水印
  • 將水印檔案批量覆蓋到目標pdf檔案中

  搞定了文字水印檔案的生成之後,接下來我們就可以把現成的水印檔案插入到目標pdf檔案中,這裡我們使用pikepdf中的相關功能就可以輕鬆實現,我寫了一個簡單的函式,大家在呼叫時只需要傳入幾個必要引數即可:

from typing import List
from pikepdf import Pdf, Page, Rectangle

def add_watermark(target_pdf_path: str,
                  watermark_pdf_path: str,
                  nrow: int,
                  ncol: int,
                  skip_pages: List[int] = []) -> None:
    '''
    向目標pdf檔案中新增平鋪水印
    target_pdf_path: 目標pdf檔案的路徑+檔名
    watermark_pdf_path: 水印pdf檔案的路徑+檔名
    nrow: 水印平鋪的行數
    ncol:水印平鋪的列數
    skip_pages: 需要跳過不新增水印的頁面序號(從0開始)
    '''
    
    # 讀入需要新增水印的pdf檔案
    target_pdf = Pdf.open(target_pdf_path)
    
    # 讀入水印pdf檔案並提取水印頁
    watermark_pdf = Pdf.open(watermark_pdf_path)
    watermark_page = watermark_pdf.pages[0]
    
    # 遍歷目標pdf檔案中的所有頁(排除skip_pages指定的若干頁)
    for idx, target_page in enumerate(target_pdf.pages):
        
        if idx not in skip_pages:
            for x in range(ncol):
                for y in range(nrow):
                    # 向目標頁指定範圍新增水印
                    target_page.add_overlay(watermark_page, Rectangle(target_page.trimbox[2] * x / ncol, 
                                                                      target_page.trimbox[3] * y / nrow,
                                                                      target_page.trimbox[2] * (x + 1) / ncol, 
                                                                      target_page.trimbox[3] * (y + 1) / nrow))
                    
    # 將新增完水印後的結果儲存為新的pdf
    target_pdf.save(target_pdf_path[:-4]+'_已新增水印.pdf')

  下面我們直接呼叫這個函式,對示例檔案【吳恩達】機器學習訓練祕籍-中文版.pdf中除了封面以外的每一頁,按照3行2列的平鋪密度,新增上我們的示例水印:

add_watermark(target_pdf_path='./【吳恩達】機器學習訓練祕籍-中文版.pdf',
              watermark_pdf_path='./水印示例.pdf',
              nrow=3,
              ncol=2,
              skip_pages=[0])

  效果槓槓的,讀者朋友們可以自己多試試,得到更多心得體會~

「Python實用祕技04」為pdf檔案批量新增文字水印

  本期分享結束,我們們下回見~?

相關文章