PyPDF2 | 利用 Python 实现 PDF 分割

PyPDF2 | 利用 Python 实现 PDF 分割1.PDF分割由于疫情影响被迫在家上网课,因此教材也只能用电子版。但有一门教材是对开的扫描版,导致在iPad上阅读很不友好,因此决定寻找一个工具将PDF对半分开。图1分割前的PDF在百度了一番后,发现大多都是使用AdobeAcrobat软件进行剪裁,这完全不Pythonic,因此又找了用Python处理PDF文件的方法,最后发现了PyPDF2这个库,本…

大家好,又见面了,我是你们的朋友全栈君。

1. PDF 分割

由于疫情影响被迫在家上网课,因此教材也只能用电子版。但有一门教材是对开的扫描版,导致在 iPad 上阅读很不友好,因此决定寻找一个工具将 PDF 对半分开。


PyPDF2 | 利用 Python 实现 PDF 分割


图1 分割前的 PDF

在百度了一番后,发现大多都是使用 Adobe Acrobat 软件进行剪裁,这完全不 Pythonic,因此又找了用 Python 处理 PDF 文件的方法,最后发现了 PyPDF2 这个库,本文将利用这个库,实现对 PDF 的分割。

首先,你需要通过 pip 安装这个库:

pip install PyPDF2

实现切割 PDF 的思想很简单,只要我们能测量出 PDF 的长宽,接着分别将左右裁剪拼接即可,而 PyPDF2 已经提供了这些功能:

# PdfFileReader 模块用于读取 pdf
# PdfFileWriter 模块用于创建要保存的 pdf
from PyPDF2 import PdfFileReader, PdfFileWriter

# 1. 读取 pdf
pdf_input = PdfFileReader(open('xxx.pdf', 'rb'))

# 2. 创建要保存的 pdf 对象
pdf_output = PdfFileWriter()

# 3. 选取第一页 pdf 读取长宽
page = pdf_input_left.getPage(0)
width = float(page.mediaBox.getWidth())
height = float(page.mediaBox.getHeight())

# 4. 计算 pdf 的总页数
page_count = pdf_input_left.getNumPages()

# 5. 修改某一页 pdf 的尺寸
page = pdf_input.getPage(i)
page.mediaBox.lowerLeft = (x,y)
page.mediaBox.lowerRight = (x,y)
page.mediaBox.upperLeft = (x,y)
page.mediaBox.upperRight = (x,y)

# 6. 将修改好的 pdf 添加到我们要输出的文件中
pdf_output.addPage(page)

# 7. 循环所有的页数后,将文件输出为 pdf 文件
pdf_output.write(open('xxx,pdf', 'wb'))

需要注意的是,PyPDF2 默认将较短的边作为 X 轴,较长的边作为 Y 轴,对应的坐标如下:


PyPDF2 | 利用 Python 实现 PDF 分割


图2 纵向比例下的 PyPDF2 坐标

然而我们的 PDF 是横向比例的,如下图所示:


PyPDF2 | 利用 Python 实现 PDF 分割

图3 横向比例 PDF 示例

相当于:


PyPDF2 | 利用 Python 实现 PDF 分割


图4 横向比例下的 PyPDF2 坐标

即:


PyPDF2 | 利用 Python 实现 PDF 分割


图5 旋转后的横向比例下的 PyPDF2 坐标

要注意与图 1 坐标的区别。

在弄清楚了 PyPDF 的坐标后,我们就可以通过调整四个角的坐标来分别获得左右两个 PDF 了,对于左边的 PDF,其对应的坐标为:


PyPDF2 | 利用 Python 实现 PDF 分割


图6 左半图的 PyPDF2 坐标

因此坐标设置如下:

page_left.mediaBox.lowerLeft = (0, height/2)
page_left.mediaBox.lowerRight = (width, height/2)
page_left.mediaBox.upperLeft = (0, height)
page_left.mediaBox.upperRight = (width, height)

而右半图的坐标为:


PyPDF2 | 利用 Python 实现 PDF 分割


图7 右半图的 PyPDF2 坐标

对应的坐标设置为:

page_right.mediaBox.lowerLeft = (0, 0)
page_right.mediaBox.lowerRight = (width, 0)
page_right.mediaBox.upperLeft = (0, height/2)
page_right.mediaBox.upperRight = (width, height/2)

最后汇总得:

from PyPDF2 import PdfFileReader, PdfFileWriter

infile = '应用多元统计分析 高惠璇.pdf'
outfile = '应用多元统计分析 高惠璇 split.pdf'

pdf_input_left = PdfFileReader(open(infile, 'rb'))
pdf_input_right = PdfFileReader(open(infile, 'rb'))
pdf_output = PdfFileWriter()

page = pdf_input_left.getPage(0)
width = float(page.mediaBox.getWidth())
height = float(page.mediaBox.getHeight())
page_count = pdf_input_left.getNumPages()

for i in range(page_count):
    # left page
    page_left = pdf_input_left.getPage(i)
    page_left.mediaBox.lowerLeft = (0, height/2)
    page_left.mediaBox.lowerRight = (width, height/2)
    page_left.mediaBox.upperLeft = (0, height)
    page_left.mediaBox.upperRight = (width, height)
    pdf_output.addPage(page_left)
    
    # right page
    page_right = pdf_input_right.getPage(i)
    page_right.mediaBox.lowerLeft = (0, 0)
    page_right.mediaBox.lowerRight = (width, 0)
    page_right.mediaBox.upperLeft = (0, height/2)
    page_right.mediaBox.upperRight = (width, height/2)
    pdf_output.addPage(page_right)

pdf_output.write(open(outfile, 'wb'))

看下转换效果,Bingo!


PyPDF2 | 利用 Python 实现 PDF 分割


图8 转换后的 PDF 效果

2. 调整边缘

转换后发现,PDF 存在这黑边,因此我们可以通过调整对应的坐标来减少黑边的现象:


PyPDF2 | 利用 Python 实现 PDF 分割


图9 PDF 黑边

from PyPDF2 import PdfFileReader, PdfFileWriter
def pdf_split(infile, outfile, left_margin=0, right_margin=0, down_margin=0):
    pdf_input_left = PdfFileReader(open(infile, 'rb'))    # 读取切割为左边的 pdf
    pdf_input_right = PdfFileReader(open(infile, 'rb'))   # 读取切割为右边的 pdf
    pdf_output = PdfFileWriter()                          # 定义要保存的 pdf

    page = pdf_input_left.getPage(0)                      # 选取第一页 来读取 pdf 的长宽
    width = float(page.mediaBox.getWidth())
    height = float(page.mediaBox.getHeight())
    page_count = pdf_input_left.getNumPages()             # 读取 pdf 页数

    for i in range(page_count):
        # 切割左边 pdf
        page_left = pdf_input_left.getPage(i)
        page_left.mediaBox.lowerLeft = (0, height/2)
        page_left.mediaBox.lowerRight = (width, height/2)
        page_left.mediaBox.upperLeft = (down_margin, height-left_margin)
        page_left.mediaBox.upperRight = (width, height-left_margin)
        pdf_output.addPage(page_left)
    
        # 切割右边 pdf
        page_right = pdf_input_right.getPage(i)
        page_right.mediaBox.lowerLeft = (down_margin, right_margin)
        page_right.mediaBox.lowerRight = (width, right_margin)
        page_right.mediaBox.upperLeft = (down_margin, height/2)
        page_right.mediaBox.upperRight = (width, height/2)
        pdf_output.addPage(page_right)

    pdf_output.write(open(outfile, 'wb')) # 保存 pdf
    print('Done!')
infile = '应用多元统计分析 高惠璇.pdf'
outfile = '应用多元统计分析 高惠璇 split.pdf'
left_margin=10
right_margin=10
down_margin = 20
pdf_split(infile, outfile, left_margin, right_margin, down_margin)
Done!

看下最后效果:


PyPDF2 | 利用 Python 实现 PDF 分割


图10 调整后的 PDF 黑边情况


其他文章推荐

机器学习算法与 Python 实现专栏

SQL 入门教程专栏

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/152352.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(1)
blank

相关推荐

  • Eclipse中快速输入System.out.println()的快捷键

    Eclipse中快速输入System.out.println()的快捷键善用Eclipse组合键,可以提高输入效率。Step1:Eclipse的参数设置面板,工具栏窗口-》首选项-》常规-》键-》按类别筛选,编辑类别下找到“内容辅助”,英文即“ContentAssist”。检查该项是不是绑定了“Alt+/”,如果不是换成这个快捷键的组合,点击确定按钮。效果:1、例如:输入“tr”,然后按组合键

  • wcopy nfc pro智能读卡工具软件_手机NFC复制小区用的门禁卡[通俗易懂]

    wcopy nfc pro智能读卡工具软件_手机NFC复制小区用的门禁卡[通俗易懂]我们说一说目前的门禁卡到底有哪些类型呢?门禁卡一般分为:ID卡和IC卡。而EM卡、M1卡、CPU卡等等,都是这两种卡的细分。它们能够开门,都是基于RFID感应的原理来实现开门的。我们看一张图,在这张图中,能够看到一个数据名词,频率:ID卡的工作频率为125KHz频率,而IC卡的工作频率为13.56MHz,显然因为IC卡的频率高,所以,它的安全性比较高。小区基本上选择IC卡的概率会更高一…

  • ubuntu 卸载php「建议收藏」

    ubuntu 卸载php「建议收藏」卸载:一、删除php的相关包及配置sudoapt-getautoremovephp7*二、删除关联sudofind/etc-name”*php*”|xargsrm-rf三、清除dept列表sudoaptpurge`dpkg-l|grepphp|awk'{print$2}’|tr”\n”””`四、检查是否卸载干净(无返回就是卸载完成)dpkg-l|grepphp7.0…

  • 常见的图片类型_金鱼种类图片

    常见的图片类型_金鱼种类图片1、Jpg(jpeg):这是一种可以高度保留图片色彩信息的格式2、Png:该类型的图片可以实现透明3、Gif:图片所占体积小,可以实现动图4、Psd:它是一种分层的图片

  • 混合开发hybrid原理_unity引擎开源吗

    混合开发hybrid原理_unity引擎开源吗首先,我们先来罗列一下当前市面上,移动端的各种开发方法1.NativeApp纯原生的app开发模式,android(Java)或者ios(Swift,Oc)优点:有最好的性能,有最好的体验缺点:开发和发布的成本极高,两端需要不同的技术人员来维护,原生开发人员非常的稀缺2.WebApp移动端运行在浏览器上的网站,我们一般称之为H5应用,就是泛指我们经常开发的spa,map页面语言:js,vue,react,angular等优点:1.开发和发布非常方便2.用户看到的页面,会随着开发人

  • 基础版的音频功放电路(A类功放电路、B类功放电路、C类功放电路、D类功放电路、G类功放电路、H类功放电路、K类功放电路、T类功放电路)[通俗易懂]

    基础版的音频功放电路(A类功放电路、B类功放电路、C类功放电路、D类功放电路、G类功放电路、H类功放电路、K类功放电路、T类功放电路)[通俗易懂]  作为硬件工程师,特别是做纯粹模拟电路、应用于音频功放的工程师,对于A类,B类,AB类,D类,G类,H类,T类功放应该特别熟悉。大多数工程师或许只知道其中的一部分、或者知道大概,为了让更多的工程师掌握更加详尽的音频功放知识,下文对以上说的音频功放做详细的说明。  引用地址:http://www.eepw.com.cn/article/201611/340477.htm  功放,顾名思义,就是功率放大的缩写。与电压或者电流放大来说,功放要求获得一定的、不失真的功率,一般在大信号状态下工作,因此,功放电路

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号