Python 操作 PDF
相關(guān)介紹
1)Python 操作 PDF 會用到兩個(gè)庫,分別是:PyPDF2 和 pdfplumber
其中 PyPDF2 可以更好的讀取、寫入、分割、合并PDF文件,而 pdfplumber 可以更好的讀取 PDF 文件中內(nèi)容和提取 PDF 中的表格
由于這兩個(gè)庫都不是 Python 的標(biāo)準(zhǔn)庫,所以在使用之前都需要單獨(dú)安裝
安裝命令如下:
pip install PyPDF
pip install pdfplumber
批量拆分
1)PDF 拆分成幾個(gè)小的 PDF
大致思路:讀取 PDF ,以每個(gè) step 為間隔將 PDF 存成每一個(gè)小的文件塊,
將小的文件塊重新保存為新的 PDF 文件
示例代碼:
import PyPDF2
from PyPDF2 import PdfFileReader, PdfFileWriter
import os
def split_pdf(filename, filepath, save_dirpath, step):
"""
拆分PDF為多個(gè)小的PDF文件,
@param filename:文件名
@param filepath:文件路徑
@param save_dirpath:保存小的PDF的文件路徑
@param step: 每step間隔的頁面生成一個(gè)文件,例如step=5,表示0-4頁、5-9頁...為一個(gè)文件
@return:
"""
if not os.path.exists(save_dirpath):
os.mkdir(save_dirpath)
pdf_reader = PdfFileReader(filepath)
# 讀取每一頁的數(shù)據(jù)
pages = pdf_reader.getNumPages()
for page in range(0, pages, step):
pdf_writer = PdfFileWriter()
# 拆分pdf,每 step 頁的拆分為一個(gè)文件
for index in range(page, page+step):
if index < pages:
pdf_writer.addPage(pdf_reader.getPage(index))
# 保存拆分后的小文件
save_path = os.path.join(save_dirpath, filename+str(int(page/step)+1)+'.pdf')
print(save_path)
with open(save_path, "wb") as out:
pdf_writer.write(out)
print("文件已成功拆分,保存路徑為:"+save_dirpath)
filename = 'Python.pdf'
filepath = "D:\\Python操作PDF\\Python.pdf"
save_dirpath= 'D:\\Python操作PDF\\Python'
step=60
split_pdf(filename, filepath, save_dirpath, step)
結(jié)果:
D:\Python操作PDF\Python\Python.pdf1.pdf
D:\Python操作PDF\Python\Python.pdf2.pdf
D:\Python操作PDF\Python\Python.pdf3.pdf
D:\Python操作PDF\Python\Python.pdf4.pdf
D:\Python操作PDF\Python\Python.pdf5.pdf
D:\Python操作PDF\Python\Python.pdf6.pdf
文件已成功拆分,保存路徑為:D:\Python操作PDF\Python
Process finished with exit code 0


批量合并
1)大致思路:
確定要合并的 文件順序
循環(huán)追加到一個(gè)文件塊中
保存成一個(gè)新的文件
def concat_pdf(filename, read_dirpath, save_filepath):
"""
合并多個(gè)PDF文件
@param filename:文件名
@param read_dirpath:要合并的PDF目錄
@param save_filepath:合并后的PDF文件路徑
@return:
"""
pdf_writer = PdfFileWriter()
# 對文件名進(jìn)行排序
list_filename = os.listdir(read_dirpath)
list_filename.sort(key=lambda x: int(x[:-4].replace(filename, "")))
for filename in list_filename:
print(filename)
filepath = os.path.join(read_dirpath, filename)
# 讀取文件并獲取文件的頁數(shù)
pdf_reader = PdfFileReader(filepath)
pages = pdf_reader.getNumPages()
# 逐頁添加
for page in range(pages):
pdf_writer.addPage(pdf_reader.getPage(page))
# 保存合并后的文件
with open(save_filepath, "wb") as out:
pdf_writer.write(out)
print("文件已成功合并,保存路徑為:"+save_filepath)
提取文字內(nèi)容
1)提取指定頁內(nèi)容
示例代碼:
def extract_text_info(filepath):
"""
提取PDF中的文字
@param filepath:文件路徑
@return:
"""
with pdfplumber.open(filepath) as pdf:
# 獲取第2頁數(shù)據(jù)
page = pdf.pages[1]
print(page.extract_text())
2)獲取整個(gè)文件
ef extract_text_info(filepath):
"""
提取PDF中的文字
@param filepath:文件路徑
@return:
"""
with pdfplumber.open(filepath) as pdf:
# 獲取全部數(shù)據(jù)
for page in pdf.pages
print(page.extract_text())
提取表格內(nèi)容
1)提取一個(gè)表格
def extract_table_info(filepath):
"""
提取PDF中的圖表數(shù)據(jù)
@param filepath:
@return:
"""
with pdfplumber.open(filepath) as pdf:
# 獲取第18頁數(shù)據(jù)
page = pdf.pages[17]
# 如果一頁有一個(gè)表格,設(shè)置表格的第一行為表頭,其余為數(shù)據(jù)
table_info = page.extract_table()
df_table = pd.DataFrame(table_info[1:], columns=table_info[0])
df_table.to_csv('dmeo.csv', index=False, encoding='gbk')
2)提取多個(gè)表格
def extract_table_info(filepath):
"""
提取PDF中的圖表數(shù)據(jù)
@param filepath:
@return:
"""
# 如果一頁有多個(gè)表格,對應(yīng)的數(shù)據(jù)是一個(gè)三維數(shù)組
tables_info = page.extract_tables()
for index in range(len(tables_info)):
# 設(shè)置表格的第一行為表頭,其余為數(shù)據(jù)
df_table = pd.DataFrame(tables_info[index][1:], columns=tables_info[index][0])
print(df_table)
# df_table.to_csv('dmeo.csv', index=False, encoding='gbk')
提取圖片內(nèi)容
1)安裝 PyMuPDF 模塊
pip install PyMuPDF
大致·思路:打開文檔>遍歷元素>正則匹配>生成圖片>過濾圖片
示例:
"""2. 遍歷PDF中的對象,遇到是圖像才進(jìn)行下一步,不然就continue"""
for index in range(1, xref_len):
# 1.16.8版本用法 text = doc._getXrefString(index)
# 最新版本
text = pdf_info.xref_object(index)
is_XObject = re.search(check_XObject, text)
is_Image = re.search(check_Image, text)
# 如果不是對象也不是圖片,則不操作
if is_XObject or is_Image:
img_count += 1
# 根據(jù)索引生成圖像
pix = fitz.Pixmap(pdf_info, index)
pic_filepath = os.path.join(pic_dirpath, 'img_' + str(img_count) + '.png')
"""pix.size 可以反映像素多少,簡單的色素塊該值較低,可以通過設(shè)置一個(gè)閾值過濾。以閾值 10000 為例過濾"""
# if pix.size < 10000:
# continue
"""三、 將圖像存為png格式"""
if pix.n >= 5:
# 先轉(zhuǎn)換CMYK
pix = fitz.Pixmap(fitz.csRGB, pix)
# 存為PNG
pix.writePNG(pic_filepath)
轉(zhuǎn)換為圖片
1)安裝 pdf2image模塊
2)安裝組件
windows 用戶需要安裝 poppler for Windows,安裝鏈接是:http://blog.alivate.com.au/poppler-windows/
mac 用戶,需要安裝 poppler for Mac,具體可以參考這個(gè)鏈接:http://macappstore.org/poppler/
示例:
if not os.path.exists(pic_dirpath):
os.makedirs(pic_dirpath)
images = convert_from_bytes(open(filepath, 'rb').read())
# images = convert_from_path(filepath, dpi=200)
for image in images:
# 保存圖片
pic_filepath = os.path.join(pic_dirpath, 'img_'+str(images.index(image))+'.png')
image.save(pic_filepath, 'PNG')
添加水印
主要代碼:
watermark = PdfFileReader(watermark_filepath)
watermark_page = watermark.getPage(0)
pdf_reader = PdfFileReader(filepath)
pdf_writer = PdfFileWriter()
for page_index in range(pdf_reader.getNumPages()):
current_page = pdf_reader.getPage(page_index)
# 封面頁不添加水印
if page_index == 0:
new_page = current_page
else:
new_page = copy(watermark_page)
new_page.mergePage(current_page)
pdf_writer.addPage(new_page)
# 保存水印后的文件
with open(save_filepath, "wb") as out:
pdf_writer.write(out)
文檔加密與解密
1)加密操作
pdf_reader = PdfFileReader(filepath)
pdf_writer = PdfFileWriter()
for page_index in range(pdf_reader.getNumPages()):
pdf_writer.addPage(pdf_reader.getPage(page_index))
# 添加密碼
pdf_writer.encrypt(passwd)
with open(save_filepath, "wb") as out:
pdf_writer.write(out)
2)解密操作
pdf_reader = PdfFileReader(filepath)
# PDF文檔解密
pdf_reader.decrypt('python')
pdf_writer = PdfFileWriter()
for page_index in range(pdf_reader.getNumPages()):
pdf_writer.addPage(pdf_reader.getPage(page_index))
with open(save_filepath, "wb") as out:
pdf_writer.write(out)