查看原文
其他

使用pdfrw库对pdf文件进行读写操作

大邓 大邓和他的Python 2019-04-26

大家好,前几天分享了一篇读取pdf文章,但是依然无法少部分的pdf进行操作。今天看Python Weekly最新一期推送的文章中《Creating and Manipulate PDFs with pdfrw》,发现该库对pdf操作性能极好,且api更简洁,更适合我这样的小白使用。所以今天我就将该文章翻译一下,做成notebook分享给大家。

在本篇文章中,我们会学到以下内容:

  • 从pdf文件中提取特定的信息

  • 分割pdf文件

  • 合并pdf文件

  • 对pdf中的内容进行旋转

更多功能请查看pdfrw文档

https://github.com/pmaupin/pdfrw#examples

1. 安装

首先我们安装pdfrw库,在终端中输入命令

pip3 install pdfrw

如果你使用的jupyter notebook运行本教程notebook出错提示你没有该库,你需要进行以下操作。

在终端中输入命令

conda install -c nsidc pdfrw

可能网速比较慢,大概1-5min,终端会出现Proceed[y/n],你需要输入y回车

2. 从PDF中提取信息

pdfrw库会从pdf文件中提取并返回pdf文件相关信息,一码胜千言,直接上代码看运行结果可能比我说更好。这里我们使用了w9.pdf文件作为测试文件。

from pdfrw import PdfReader, PdfWriter


def get_pdf_info(path):
   pdf = PdfReader(path)

   #PdfReader的关键词keys
   print(pdf.keys())
   print(pdf.Info)
   print(pdf.Root.keys())

   #pdf文件页数
   print('PDF has {} pages'.format(len(pdf.pages)))


get_pdf_info('w9.pdf')
['/Root', '/Info', '/ID', '/Size']
{'/Author': '(SE:W:CAR:MP)', '/CreationDate': "(D:20171109144422-05'00')", '/Creator': '(Adobe LiveCycle Designer ES 9.0)', '/Keywords': '(Fillable)', '/ModDate': "(D:20171109144521-05'00')", '/Producer': '(Adobe LiveCycle Designer ES 9.0)', '/SPDF': '(1112)', '/Subject': '(Request for Taxpayer Identification Number and Certification)', '/Title': '(Form W-9 \\(Rev. November 2017\\))'}
['/AcroForm', '/Extensions', '/MarkInfo', '/Metadata', '/Names', '/Pages', '/StructTreeRoot', '/Type', '/Perms']
PDF has 6 pages

呈现方式可能不太友好,继续看下面的内容,pdfrw是不会让你失望的。

3. 分割pdf文件

我们可以使用pdfrw库将pdf文件分割为多份文件。比如,你有可能只想要pdf书籍中的封面,或者你想将这本书按照章节分割为多个文件。这就是pdfrw吸引大邓分享给你的初衷,真的是听强悍的一个pdf操作库。

split函数:

  • path: 待分割的pdf文件路径

  • page:待分割pdf文件第page页

  • output:第page页保存的新pdf文件路径

这里我使用一个 Introduction to Text Mining and Natural Language Processing.pdf 作为例子,将其第一页和第二页分割并保存为第一页.pdf、第二页.pdf两个pdf文件。

def split(path, page, output):
   pdf_obj = PdfReader(path)
   total_pages = len(pdf_obj.pages)

   writer = PdfWriter()
   if page <= total_pages:
       writer.addpage(pdf_obj.pages[page])
       writer.write(output)


path = 'Introduction to Text Mining and Natural Language Processing.pdf'
pages = [1, 2]
outputs = ['第一页.pdf', '第二页.pdf']
for page,output in zip(pages, outputs):
   split(path, page, output)

具体效果大家运行后看看文件夹中新生成的第一页.pdf、第二页.pdfIntroduction to Text Mining and Natural Language Processing.pdf做对比,完美的运行实现了我们的分割实验。

4. 合并多个pdf文件

pdfrw可以很容易的将多个pdf文件进行合并,Let's go

在上面的例子中我们创建了concatenate函数,

  • paths参数为待合并的多个pdf文件路径

  • output为合并后pdf文件路径

from pdfrw import PdfReader, PdfWriter, IndirectPdfDict

def concatenate(paths, output):
   writer = PdfWriter()

   for path in paths:
       reader = PdfReader(path)
       writer.addpages(reader.pages)

   #我们给新的pdf文件加一些看不到的信息。
   #Title、author这些词你可以换成你喜欢的,不会影响程序运行
   #这里我们将这些信息隐藏到新的pdf文件中。
   writer.trailer.Info = IndirectPdfDict(
       Title = '合并pdf文件',
       Author = '生成者:大邓',
       Subject= '多个PDF文件合并',
       HelloPdfrw = '真好用',
       PythonIsFun ='YES')

   writer.write(output)

paths = ['第一页.pdf', '第二页.pdf']
concatenate(paths, '合并后的文件.pdf')

我们打开合并后的文件.pdf后,发现确实是对 第一页.pdf、第二页.pdf进行的合并。而且也看不到

Title = '合并pdf文件',
Author = '生成者:大邓',
Subject= '多个PDF文件合并',
HelloPdfrw = '真好用',
PythonIsFun ='YES'

这些信息。

那我们使用get_pdf_info(path)函数查看下合并后的文件.pdf的信息

get_pdf_info('合并后的文件.pdf')
['/Info', '/Root', '/Size']
{'/Author': '<FEFF751F62108005FF1A59279093>', '/HelloPdfrw': '<FEFF771F597D7528>', '/PythonIsFun': '(YES)', '/Subject': '<FEFF591A4E2A00500044004665874EF654085E76>', '/Title': '<FEFF54085E7600700064006665874EF6>'}
['/Pages', '/Type']
PDF has 2 pages

我们发现上面多了

Author/HelloPdfrw/HelloPdfrw/PythonIsFun,

这些关键词都是我自己随便写的,居然都隐藏近新生产的文件了。

这个方法非常棒,比如我以后分享的内容如果以pdf文件保存,我可以将作者信息隐藏到pdf文件中。如果以后谁盗版我的内容,我可以读取这个pdf文件隐藏的信息证明这是我写的。

5. 旋转

有时候你见到的pdf文件某页可能是是旋转90度后的,需要你旋转屏幕才能阅读,那么我们就需要对该pdf文件进行选择。这里我没有这么奇怪的pdf文件,那么我们就对'Introduction to Text Mining and Natural Language Processing.pdf' 文件的奇数页面进行旋转并存储到新的奇数页内容(顺时针旋转90度).pdf,生成奇怪的文件,来试试旋转功能。

from pdfrw import PdfReader, PdfWriter, IndirectPdfDict

def rotate_odd(path, output):

   reader = PdfReader(path)
   writer = PdfWriter()
   pages = reader.pages

   for page in range(len(pages)):
       if page % 2:
           pages[page].Rotate = 90
           writer.addpage(pages[page])

   writer.write(output)

path = 'Introduction to Text Mining and Natural Language Processing.pdf'
output = '奇数页内容(顺时针旋转90度).pdf'
rotate_odd(path, output)


往期文章

100G Python学习资料:从入门到精通! 免费下载   

上百G文本数据集等你来认领|免费领取

在校大学生如何用知识月入3000 

昨晚一口气读完了吴军的《智能时代》

为什么你要为2019,而不是2018做计划?    

2017年度15个最好的数据科学领域Python库   

推荐系统与协同过滤、奇异值分解

初识K-means算法   

机器学习之使用逻辑回归识别图片中的数字

应用PCA降维加速模型训练

对于中文,nltk能做哪些事情 

使用sklearn做自然语言处理-1 

使用sklearn做自然语言处理-2

机器学习|八大步骤解决90%的NLP问题   

Python圈中的符号计算库-Sympy

Python中处理日期时间库的使用方法 

如何从文本中提取特征信息? 

【视频讲解】Scrapy递归抓取简书用户信息

美团商家信息采集神器 

用chardect库解决网页乱码问题

gevent:异步理论与实战  

selenium驱动器配置详解

数据及代码获取

公众号粉丝刚刚突破5000,开通了流量主。希望大家多多支持


    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存