1. 程式人生 > 其它 >合併pdf檔案帶書籤(利用python的PyPDF2,並解決PyPDF2 編碼問題'latin-1'和PyPDF2報錯:PdfReadError: EOF marker not found)

合併pdf檔案帶書籤(利用python的PyPDF2,並解決PyPDF2 編碼問題'latin-1'和PyPDF2報錯:PdfReadError: EOF marker not found)

1.檔案準備:

先將掃描的pdf檔案,每一章放到一個資料夾中,資料夾名字用章節名命名。

這樣最終程式就能將章節名作為書籤了,而不是預設將每頁都生成書籤。

 

 

 

 

 

 

 2.程式程式碼

程式碼執行環境:python310

根據檔案和資料夾所在位置改下面熒光黃的程式碼部分即可

# -*- coding: utf-8 -*- '''    本指令碼用來合併pdf檔案,支援帶一級子目錄的    每章內容分別放在不同的目錄下,目錄名為章節名    最終生成的pdf,按章節名生成書籤 '''
import os import sys import codecs from PyPDF2 import PdfFileReader, PdfFileWriter, PdfFileMerger
import glob

def getFileName(filepath):     '''         獲取當前目錄下的所有pdf檔案     '''     file_list = glob.glob(filepath + "/*.pdf")     # 預設安裝字典序排序,也可以安裝自定義的方式排序     # file_list.sort()     return file_list

def get_dirs(filepath='', dirlist_out=[], dirpathlist_out=[]):     # 遍歷filepath下的所有目錄     for dir in os.listdir(filepath):
        dirpathlist_out.append(filepath + '\\' + dir)
    return dirpathlist_out

def merge_childdir_files(path):     '''         每個子目錄下合併生成一個pdf     '''     dirpathlist = get_dirs(path)     if len(dirpathlist) == 0:         print("當前目錄不存在子目錄")         sys.exit()     for dir in dirpathlist:         mergefiles(dir, dir)


def mergefiles(path, output_filename, import_bookmarks=False):     # 遍歷目錄下的所有pdf將其合併輸出到一個pdf檔案中,輸出的pdf檔案預設帶書籤,書籤名為之前的檔名     # 預設情況下原始檔案的書籤不會匯入,使用import_bookmarks=True可以將原檔案所帶的書籤也匯入到輸出的pdf檔案中     merger = PdfFileMerger()     filelist = getFileName(path)     if len(filelist) == 0:         print("當前目錄及子目錄下不存在pdf檔案")         sys.exit()     for filename in filelist:         f = codecs.open(filename, 'rb')         file_rd = PdfFileReader(f)         short_filename = os.path.basename(os.path.splitext(filename)[0])         if file_rd.isEncrypted == True:             print('不支援的加密檔案:%s' % (filename))             continue         merger.append(file_rd,                       bookmark=short_filename,                       import_bookmarks=import_bookmarks)         print('合併檔案:%s' % (filename))         f.close()     # out_filename = os.path.join(os.path.abspath(path), output_filename)     merger.write(output_filename + ".pdf")     print('合併後的輸出檔案:%s' % (output_filename))     merger.close()

if __name__ == "__main__":     # 每個章節一個子目錄,先分別合併每個子目錄檔案為一個pdf,然後再將這些pdf合併為一個大的pdf,這樣做目的是想生成每個章節的書籤
    # 1.指定目錄     # 原始pdf所在目錄     path = "D:\VScode\python-automate\pdf\第 01 章 電路模型與基本定律"     # 輸出pdf路徑和檔名     output_filename = "D:\VScode\python-automate\pdf\第 01 章 電路模型與基本定律"
    # 2.生成子目錄的pdf     # merge_childdir_files(path)
    # 3.子目錄pdf合併為總的pdf     mergefiles(path, output_filename)    3.進一步合成  

 

 

此時目標路徑會出現上述檔案,若程式碼執行成功後開啟pdf無異常則表示第一章pdf已經合併好

且有每個檔名的標籤,接下來只需要對每個章節再次進行合併即可(很可惜我把所有章節合併後subtitle消失了)

 全合併完

 

 

 

 4.可能出現的問題     ①PyPDF2 編碼問題'latin-1' codec can't encode characters in position 8-11: ordinal not in range(256) 通常這情況是出現了中文字元編碼

解決方法

1、修改pypdf2包中的generic.py檔案

我的目錄是c:\……python310\Lib\site-packages\PyPDF2\generic.py

1)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

 

②PyPDF2報錯:PdfReadError: EOF marker not found

查到的解決方法有 1)把檔案複製到別的資料夾 2)開啟檔案再重新儲存 3)(我自己)開啟pdf發現有些pdf開啟失敗於是重新合成   參考: ————————————————
版權宣告:本文為CSDN博主「huahuazhu」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處連結及本宣告。
原文連結:使用python合併pdf檔案帶書籤_huahuazhu的部落格-CSDN部落格_python 合併pdf
版權宣告:本文為CSDN博主「小羊瓜瓜的部落格」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處連結及本宣告。 原文連結:PyPDF2 編碼問題'latin-1' codec can't encode characters in position 8-11: ordinal not in range(256)