日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

Python:使用pypdf2合并、分割、加密pdf文件。

發布時間:2023/12/31 python 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Python:使用pypdf2合并、分割、加密pdf文件。 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

朋友需要對一個pdf文件進行分割,在網上查了查發現這個pypdf2可以完成這些操作,所以就研究了下這個庫,并做一些記錄。首先pypdf2是python3版本的,在之前的2版本有一個對應pypdf庫。

可以使用pip直接安裝:

pip install pypdf2 復制代碼

官方文檔:pythonhosted.org/PyPDF2/

里面主要有這幾個類:


PdfFileReader 。

該類主要提供了對pdf文件的讀操作,其構造方法為:

PdfFileReader(stream, strict=True, warndest=None, overwriteWarnings=True) 復制代碼

第一個參數可以傳入一個文件流,或者一個文件路徑。后面三個參數都是用來設置警告的處理方式,直接使用默認的即可。

得到實例之后,就可以對pdf進行一些操作了。主要的有以下幾個操作:

  • decrypt(password):如果pdf文件加密的話,可以使用該方法對其解密。

  • getDocumentInfo():檢索pdf文件的一些信息。其返回值為一個DocumentInformation 類型,直接輸出的話會得到類似下面的信息:

{'/ModDate': "D:20150310202949-07'00'", '/Title': '', '/Creator': 'LaTeX with hyperref package', '/CreationDate': "D:20150310202949-07'00'", '/PTEX.Fullbanner': 'This is pdfTeX, Version 3.14159265-2.6-1.40.15 (TeX Live 2014/MacPorts 2014_6) kpathsea version 6.2.0', '/Producer': 'pdfTeX-1.40.15', '/Keywords': '', '/Trapped': '/False', '/Author': '', '/Subject': ''}

  • getNumPages():這個會pdf文件中的頁數。

  • getPage(pageNumber):會得到pdf文件中對應的pageNumber頁數的頁面對象,返回值為PageObject實例。在得到PageObject實例之后就可以將其加添、插入等操作。

  • getPageNumber(page):與上面的方法對立,可以傳入PageObject實例,然后得到該實例是pdf文件中第幾頁的。

  • getOutlines(node=None, outlines=None):檢索文檔中出現的文檔大綱。

  • isEncrypted:記錄該pdf是否加密。如果文件本身加密,即使在使用解密decrypt方法之后,還是會返回true。

  • numPages:pdf總共的頁數,相當于訪問getNumPages()的只讀屬性。


PdfFileWriter 。

該類支持對pdf文件進行寫操作,通常是使用PdfFileReader讀取一些pdf數據,然后使用該類進行一些操作。

創建該類的實例時不需要參數。

其主要的方法有:

  • addAttachment(fname, fdata):向pdf添加文件。

  • addBlankPage(width=None, height=None):給pdf添加一個空白頁到最后,如果沒有指定大小就使用當前Weiter中pdf最后一頁的大小。

  • addPage(page):添加page到pdf中,通常這個page是由上面的Reader獲取的。

  • appendPagesFromReader(reader, after_page_append=None):將reader中的數據拷貝到當前的Writer實例中,并且如果指定after_page_append的話,最后還有回掉該函數并且將writer中的數據傳入其中。

  • encrypt(user_pwd, owner_pwd=None, use_128bit=True):將pdf進行加密,其中官方說userpwd是允許用戶使用一些限制的權限打開pdf文件,也就是使用該密碼的話可能會有一些限制,但是本人并沒有在文檔中找到設置權限的內容。而ownerpwd則是允許用戶無限制的使用。第三個參數是是否使用128位加密。

  • getNumPages():得到pdf頁數。

  • getPage(pageNumber):得到對應頁數的Page,是一個PageObject對象,可以使用上面的addPage方法將page進行添加。

  • insertPage(page, index=0):將page添加到pdf中,index指定的是被插入的位置。

  • write(stream):將該Writer中的內容寫入到文件中。


PdfFileMerger。

該類用來合并pdf文件,該類的構造方法有一個參數:PdfFileMerger(strict=True),注意這里的參數后面會介紹:

常用方法:

  • addBookmark(title, pagenum, parent=None):給pdf添加一個書簽,title是書簽的標題,pagenum是該書簽指向的頁面。

  • append(fileobj, bookmark=None, pages=None, import_bookmarks=True):將指定的fileobj文件添加到文件的末尾,bookmark是贖前,pages可以使用(start, stop[, step])或者一個 Page Range來設定將fileobj中的指定范圍的頁面進行添加。

  • merge(position, fileobj, bookmark=None, pages=None, import_bookmarks=True):與append方法類似,不過可以使用position參數指定添加的位置。

  • write(fileobj):將數據寫入到文件中。

使用的時候可以創建一個PdfFileMerger實例,然后使用append或者merge將想要融合的pdf文件依次添加進去,最后使用write保存即可。

def merge_pdf():# 創建一個用來合并文件的實例pdf_merger = PdfFileMerger()# 首先添加一個Week1_1.pdf文件pdf_merger.append('Week1_1.pdf')# 然后在第0頁后面添加ex1.pdf文件pdf_merger.merge(0, 'ex1.pdf')# 添加書簽pdf_merger.addBookmark('這是一個書簽', 1)# 將其寫入到文件中pdf_merger.write('merge_pdf.pdf') 復制代碼

下面看一下PdfFileMerger(strict=True)中的這個參數:

官方對這個參數的解釋:

strict (bool) – Determines whether user should be warned of all problems and also causes some correctable problems to be fatal. Defaults to True.

確定是否應該警告用戶所有問題,并且還會導致一些可糾正的問題。

剛開始感覺這個參數就是用來是否警告用戶一些錯誤的,直接使用默認即可,但是當本人嘗試合并帶中文的pdf時,出現了如下錯誤:

Traceback (most recent call last):File "I:\python3.5\lib\site-packages\PyPDF2\generic.py", line 484, in readFromStreamreturn NameObject(name.decode('utf-8')) UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc8 in position 10: invalid continuation byteDuring handling of the above exception, another exception occurred:PyPDF2.utils.PdfReadError: Illegal character in Name Object 復制代碼

在源碼包中使用utf解碼的時候出錯了,嘗試修改此處源碼,讓其使用gbk,但是還出現了其他的錯誤。最后發現當把構造函數中的strict設置為False時,控制臺會打印下面的錯誤:

PdfReadWarning: Illegal character in Name Object [generic.py:489] 復制代碼

但是兩個文件成功的合并了,并且大概看了下合并后的文件有時好又是壞,同樣的代碼運行多次,有時候能夠正常處理中文,但有時候中文亂碼。

除了列出的方法還有一些其他的方法,比如添加書簽、添加鏈接等等,可以參考官方文檔。


對pdf進行合并、分割、加密。

整合出來了加密、解密、合并、根據頁數進行分割、根據份數進行分割的樣例:

使用注意:如果時中文文件,運行結果可能會出現亂碼,但是多運行幾次,中間有正常顯示中文的問題。具體原因還不清楚,但就是這么玄學。。。

代碼傳送門

# @Time : 2018/3/26 23:48 # @Author : Leafage # @File : handlePDF.py # @Software: PyCharm # @Describe: 對pdf文件執行合并、分割、加密操作。 from PyPDF2 import PdfFileReader, PdfFileMerger, PdfFileWriterdef get_reader(filename, password):try:old_file = open(filename, 'rb')except IOError as err:print('文件打開失敗!' + str(err))return None# 創建讀實例pdf_reader = PdfFileReader(old_file, strict=False)# 解密操作if pdf_reader.isEncrypted:if password is None:print('%s文件被加密,需要密碼!' % filename)return Noneelse:if pdf_reader.decrypt(password) != 1:print('%s密碼不正確!' % filename)return Noneif old_file in locals():old_file.close()return pdf_readerdef encrypt_pdf(filename, new_password, old_password=None, encrypted_filename=None):"""對filename所對應的文件進行加密,并生成一個新的文件:param filename: 文件對應的路徑:param new_password: 對文件加密使用的密碼:param old_password: 如果舊文件進行了加密,需要密碼:param encrypted_filename: 加密之后的文件名,省卻時使用filename_encrypted;:return:"""# 創建一個Reader實例pdf_reader = get_reader(filename, old_password)if pdf_reader is None:return# 創建一個寫操作的實例pdf_writer = PdfFileWriter()# 從之前Reader中將數據寫入到Writer中pdf_writer.appendPagesFromReader(pdf_reader)# 重新使用新密碼加密pdf_writer.encrypt(new_password)if encrypted_filename is None:# 使用舊文件名 + encrypted 作為新的文件名encrypted_filename = "".join(filename.split('.')[:-1]) + '_' + 'encrypted' + '.pdf'pdf_writer.write(open(encrypted_filename, 'wb'))def decrypt_pdf(filename, password, decrypted_filename=None):"""將加密的文件及逆行解密,并生成一個無需密碼pdf文件:param filename: 原先加密的pdf文件:param password: 對應的密碼:param decrypted_filename: 解密之后的文件名:return:"""# 生成一個Reader和Writerpdf_reader = get_reader(filename, password)if pdf_reader is None:returnif not pdf_reader.isEncrypted:print('文件沒有被加密,無需操作!')returnpdf_writer = PdfFileWriter()pdf_writer.appendPagesFromReader(pdf_reader)if decrypted_filename is None:decrypted_filename = "".join(filename.split('.')[:-1]) + '_' + 'decrypted' + '.pdf'# 寫入新文件pdf_writer.write(open(decrypted_filename, 'wb'))def split_by_pages(filename, pages, password=None):"""將文件按照頁數進行平均分割:param filename: 所要分割的文件名:param pages: 分割之后每個文件對應的頁數:param password: 如果文件加密,需要進行解密操作:return:"""# 得到Readerpdf_reader = get_reader(filename, password)if pdf_reader is None:return# 得到總的頁數pages_nums = pdf_reader.numPagesif pages <= 1:print('每份文件必須大于1頁!')return# 得到切分之后每個pdf文件的頁數pdf_num = pages_nums // pages + 1 if pages_nums % pages else int(pages_nums / pages)print('pdf文件被分為%d份,每份有%d頁!' % (pdf_num, pages))# 依次生成pdf文件for cur_pdf_num in range(1, pdf_num + 1):# 創建一個新的寫實例pdf_writer = PdfFileWriter()# 生成對應的文件名稱split_pdf_name = "".join(filename)[:-1] + '_' + str(cur_pdf_num) + '.pdf'# 計算出當前開始的位置start = pages * (cur_pdf_num - 1)# 計算出結束的位置,如果是最后一份就直接返回最后的頁數,否則用每份頁數*已經分好的文件數end = pages * cur_pdf_num if cur_pdf_num != pdf_num else pages_nums# print(str(start) + ',' + str(end))# 依次讀取對應的頁數for i in range(start, end):pdf_writer.addPage(pdf_reader.getPage(i))# 寫入文件pdf_writer.write(open(split_pdf_name, 'wb'))def split_by_num(filename, nums, password=None):"""將pdf文件分為nums份:param filename: 文件名:param nums: 要分成的份數:param password: 如果需要解密,輸入密碼:return:"""pdf_reader = get_reader(filename, password)if not pdf_reader:returnif nums < 2:print('份數不能小于2!')return# 得到pdf的總頁數pages = pdf_reader.numPagesif pages < nums:print('份數不應該大于pdf總頁數!')return# 計算每份應該有多少頁each_pdf = pages // numsprint('pdf共有%d頁,分為%d份,每份有%d頁!' % (pages, nums, each_pdf))for num in range(1, nums + 1):pdf_writer = PdfFileWriter()# 生成對應的文件名稱split_pdf_name = "".join(filename)[:-1] + '_' + str(num) + '.pdf'# 計算出當前開始的位置start = each_pdf * (num - 1)# 計算出結束的位置,如果是最后一份就直接返回最后的頁數,否則用每份頁數*已經分好的文件數end = each_pdf * num if num != nums else pagesprint(str(start) + ',' + str(end))for i in range(start, end):pdf_writer.addPage(pdf_reader.getPage(i))pdf_writer.write(open(split_pdf_name, 'wb'))def merger_pdf(filenames, merged_name, passwords=None):"""傳進來一個文件列表,將其依次融合起來:param filenames: 文件列表:param passwords: 對應的密碼列表:return:"""# 計算共有多少文件filenums = len(filenames)# 注意需要使用False 參數pdf_merger = PdfFileMerger(False)for i in range(filenums):# 得到密碼if passwords is None:password = Noneelse:password = passwords[i]pdf_reader = get_reader(filenames[i], password)if not pdf_reader:return# append默認添加到最后pdf_merger.append(pdf_reader)pdf_merger.write(open(merged_name, 'wb'))def insert_pdf(pdf1, pdf2, insert_num, merged_name, password1=None, password2=None):"""將pdf2全部文件插入到pdf1中第insert_num頁:param pdf1: pdf1文件名稱:param pdf2: pdf2文件名稱:param insert_num: 插入的頁數:param merged_name: 融合后的文件名稱:param password1: pdf1對應的密碼:param password2: pdf2對應的密碼:return:"""pdf1_reader = get_reader(pdf1, password1)pdf2_reader = get_reader(pdf2, password2)# 如果有一個打不開就返回if not pdf1_reader or not pdf2_reader:return# 得到pdf1的總頁數pdf1_pages = pdf1_reader.numPagesif insert_num < 0 or insert_num > pdf1_pages:print('插入位置異常,想要插入的頁數為:%d,pdf1文件共有:%d頁!' % (insert_num, pdf1_pages))return# 注意需要使用False參數,可能會出現中文亂碼的情況m_pdf = PdfFileMerger(False)m_pdf.append(pdf1)m_pdf.merge(insert_num, pdf2)m_pdf.write(open(merged_name, 'wb'))if __name__ == '__main__':# encrypt_pdf('ex1.pdf', 'leafage')# decrypt_pdf('ex1123_encrypted.pdf', 'leafage')# split_by_pages('ex1.pdf', 5)split_by_num('ex2.pdf', 3)# merger_pdf(['ex1.pdf', 'ex2.pdf'], 'merger.pdf')# insert_pdf('ex1.pdf', 'ex2.pdf', 10, 'pdf12.pdf')復制代碼

總結

以上是生活随笔為你收集整理的Python:使用pypdf2合并、分割、加密pdf文件。的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。