Python实现为pdf添加水印功能

 更新时间:2022年04月02日 15:22:39   作者:KjPrime  
这篇文章主要介绍了Python实现给普通PDF添加水印的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

创建需要的水印模板

wps创建

输出pdf

水印pdf

实现步骤

安装依赖

pip install PyPDF2

代码

import os
from PyPDF2 import PdfFileReader as pr
from PyPDF2 import PdfFileWriter as pw


def write_watermark(watermark_pdf_path: str, target_pdf_path: str):
    result_pdf = pw()
    pdf_file_name = os.path.basename(target_pdf_path)
    f_target = open(target_pdf_path, 'rb')
    f_watermark = open(watermark_pdf_path, 'rb')
    target_pdf = pr(f_target)
    watermark_page = pr(f_watermark).getPage(0)
    for page in range(target_pdf.getNumPages()):
        try: # 这一段try except是一个让我超级麻烦的bug,让我解决了一天。
            target_pdf.getPage(page).mergePage(watermark_page)
            result_pdf.addPage(target_pdf.getPage(page))
        except Exception as e:
            result_pdf.addPage(watermark_page)
    if not os.path.exists("output"):
        os.makedirs("output")
    result_pdf.write(open("output/已添加水印_" + pdf_file_name, 'wb'))
    f_target.close()
    f_watermark.close()


def folder_pdf_files(folder: str) -> list[str]:  # 一个文件夹里面有多少pdf文件
    file_list = []
    for a, b, c in os.walk(folder):
        if b == []:
            for filename in c:
                if filename[-3:].lower() == 'pdf':
                    file_path = os.path.join(a, filename)
                    file_list.append(file_path)
    print(folder, ": 有", len(file_list), "个pdf文件")
    return file_list


def group_write_watermark(path_array: list[str], watermark_pdf_path: str):  # 一组pdf文件添加水印
    for pdf_path in path_array:
        print(pdf_path, "添加水印中...")
        write_watermark(watermark_pdf_path, pdf_path)
    print("完成")


if __name__ == '__main__':
    watermark_pdf_path = "水印文件.pdf"
    folder_pdf = "目录"  # 需要添加水印的pdf的目录
    pdf_list = folder_pdf_files(folder_pdf)
    group_write_watermark(pdf_list, watermark_pdf_path)

问题

UnicodeEncodeError: ‘latin-1’ codec can’t encode characters in position 8-9: ordinal not in range(256)

如果出现该错误,可以参考以下内容。

使用pypdf2出现编码问题

报错信息

‘latin-1’ codec can’t encode characters in position 8-11: ordinal not in range(256)

通常这情况是出现了中文字符编码问题

以下是使用pypdf2复制 pdf 时报错信息

//报错信息
<ipython-input-1-4f7e1b354328> in <module>()
     14      output.addPage(p)
     15 with open('D:\\Program Files\\2.pdf', 'wb') as f:
---> 16     output.write(f)

D:\Program Files (x86)\anaconda\lib\site-packages\PyPDF2\pdf.py in write(self, stream)
    499                 md5_hash = md5(key).digest()
    500                 key = md5_hash[:min(16, len(self._encrypt_key) + 5)]
--> 501             obj.writeToStream(stream, key)
    502             stream.write(b_("\nendobj\n"))
    503 

D:\Program Files (x86)\anaconda\lib\site-packages\PyPDF2\generic.py in writeToStream(self, stream, encryption_key)
    547             key.writeToStream(stream, encryption_key)
    548             stream.write(b_(" "))
--> 549             value.writeToStream(stream, encryption_key)
    550             stream.write(b_("\n"))
    551         stream.write(b_(">>"))

D:\Program Files (x86)\anaconda\lib\site-packages\PyPDF2\generic.py in writeToStream(self, stream, encryption_key)
    470 
    471     def writeToStream(self, stream, encryption_key):
--> 472         stream.write(b_(self))
    473 
    474     def readFromStream(stream, pdf):

D:\Program Files (x86)\anaconda\lib\site-packages\PyPDF2\utils.py in b_(s)
    236             return s
    237         else:
--> 238             r = s.encode('latin-1')
    239             if len(s) < 2:
    240                 bc[s] = r

UnicodeEncodeError: 'latin-1' codec can't encode characters in position 8-11: ordinal not in range(256)

解决方法

1、修改pypdf2包中的generic.py文件

由于我使用的是anaconda,路径为anaconda\Lib\site-packages\PyPDF2\generic.py

generic.py文件第488行原文

try:
   return NameObject(name.decode('utf-8'))
   except (UnicodeEncodeError, UnicodeDecodeError) as e:
   # Name objects should represent irregular characters
   # with a '#' followed by the symbol's hex number
   if not pdf.strict:
      warnings.warn("Illegal character in Name Object", utils.PdfReadWarning)
      return NameObject(name)
   else:
      raise utils.PdfReadError("Illegal character in Name Object")

改成

try:
     return NameObject(name.decode('utf-8'))
 except (UnicodeEncodeError, UnicodeDecodeError) as e:
     try:
         return NameObject(name.decode('gbk'))
     except (UnicodeEncodeError, UnicodeDecodeError) as e:
         # Name objects should represent irregular characters
         # with a '#' followed by the symbol's hex number
         if not pdf.strict:
             warnings.warn("Illegal character in Name Object", utils.PdfReadWarning)
             return NameObject(name)
         else:
             raise utils.PdfReadError("Illegal character in Name Object")

2、修改pypdf2包中的utils.py文件

utils.py238行原文

 r = s.encode('latin-1')
 if len(s) < 2:
   		bc[s] = r
 return r

修改为

try:
    r = s.encode('latin-1')
    if len(s) < 2:
        bc[s] = r
    return r
except Exception as e:
    print(s)
    r = s.encode('utf-8')
    if len(s) < 2:
        bc[s] = r
    return r

问题解决

感悟

此代码的创新点在于可以实现文件夹遍历添加水印。

其实第一点也没有什么,我感觉我最有成功感的就是write_watermark函数里那段try except语句处,这个一段代码解决pdf空白页而发送的错误。解决了一天,网络上都没有解决方法。我摸着石头过河。

有一个问题就是,这个代码对于图片pdf的水印效果不好,因为图片pdf的也页面大小比普通的文字pdf大一些,难以控制水印的位置。我想的是在创建水印pdf的时候就把pdf的大小放大。

到此这篇关于Python实现为pdf添加水印功能的文章就介绍到这了,更多相关Python pdf水印内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python中print函数简单使用总结

    Python中print函数简单使用总结

    在本篇文章里小编给大家整理的是关于Python中怎么使用print函数的相关知识点内容,需要的朋友们可以学习下。
    2019-08-08
  • 使用Termux在手机上运行Python的详细过程

    使用Termux在手机上运行Python的详细过程

    这篇文章主要介绍了使用Termux在手机上运行Python的详细过程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-10-10
  • Django视图和URL配置详解

    Django视图和URL配置详解

    这篇文章主要介绍了Django视图和URL配置详解,分享了相关代码示例,小编觉得还是挺不错的,具有一定借鉴价值,需要的朋友可以参考下
    2018-01-01
  • Python入门之三角函数sin()函数实例详解

    Python入门之三角函数sin()函数实例详解

    这篇文章主要介绍了Python入门之三角函数sin()函数实例详解,分享了相关实例,具有一定参考价值,需要的朋友可以了解下。
    2017-11-11
  • Windows下安装Scrapy

    Windows下安装Scrapy

    今天小编就为大家分享一篇关于Windows下安装Scrapy,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-10-10
  • python学习实操案例(五)

    python学习实操案例(五)

    这篇文章主要介绍了pyth学习实操案例,主要分享的小练习有我的咖啡馆你做主、显示2019中超联赛中前五名排行、模拟手机通讯录,适合初学者,需要的小伙伴可以参考一下
    2022-02-02
  • python脚本设置系统时间的两种方法

    python脚本设置系统时间的两种方法

    这篇文章主要介绍了python脚本设置系统时间的两种方法,其一是调用socket直接发送udp包到国家授时中心,其二是调用ntplib包,感兴趣的小伙伴们可以参考一下
    2016-02-02
  • 基于python SMTP实现自动发送邮件教程解析

    基于python SMTP实现自动发送邮件教程解析

    这篇文章主要介绍了基于python实现自动发送邮件教程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-06-06
  • Python+Turtle绘制可爱的多啦A梦的示例代码

    Python+Turtle绘制可爱的多啦A梦的示例代码

    这篇文章主要介绍了如何利用python中的Turtle模块绘制一个童年记忆的卡通人物哆啦A梦,文中的示例代码讲解详细,感兴趣的可以了解一下
    2022-03-03
  • python中Switch/Case实现的示例代码

    python中Switch/Case实现的示例代码

    本篇文章主要介绍了python中Switch/Case实现的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-11-11

最新评论