PDFtoWORD_V1.1版本支援PDF文件中的文字和圖片一起轉化到word文件中了~
昨天菜鳥小白做了一個小軟體——PDFtoWORD,作用就是將pdf檔案中的文字提取出來自動轉化為可編輯的word型別。但是這個軟體目前也只能將檔案PDF中的文字提取出來,還無法提取圖片。為了進一步完善這個小工具,菜鳥小白一下班就看有沒有什麼方法能夠將pdf中的圖片提取出來。
功夫不負有心人,還真讓菜鳥小白找到了方法。使用fitz庫能夠很好的提取出圖片,然後通過python-docx庫將提取出來的圖片拷貝到word中去。整體的過程如下:
PDF檔案中提取文字
接下來我們就來看看程式碼,通過pdfminer處理PDF檔案還是昨天的程式碼,有不理解的地方可以直接參考昨天的分享。
PDF檔案中提取圖片
我們先看看如何將PDF中的圖片從PDF中提取出來存放到資源池中。
# -*- coding:utf-8 -*-
#author:菜鳥小白的學習分享
import fitz
import time
import re
import os
def pdf2pic(path, pic_path):
t0 = time.clock() # 生成圖片初始時間
checkXO = r"/Type(?= */XObject)" # 使用正則表示式來查詢圖片
checkIM = r"/Subtype(?= */Image)"
doc = fitz.open(path) # 開啟pdf檔案
imgcount = 0 # 圖片計數
lenXREF = doc._getXrefLength() # 獲取物件數量長度
# 列印PDF的資訊
print("檔名:{}, 頁數: {}, 物件: {}".format(path, len(doc), lenXREF - 1))
# 遍歷每一個物件
for i in range(1, lenXREF):
text = doc._getXrefString(i) # 定義物件字串
isXObject = re.search(checkXO, text) # 使用正則表示式檢視是否是物件
isImage = re.search(checkIM, text) # 使用正則表示式檢視是否是圖片
if not isXObject or not isImage: # 如果不是物件也不是圖片,則continue
continue
imgcount += 1
pix = fitz.Pixmap(doc, i) # 生成影象物件
new_name = "圖片{}.png".format(imgcount) # 生成圖片的名稱
if pix.n < 5: # 如果pix.n<5,可以直接存為PNG
pix.writePNG(os.path.join(pic_path, new_name))
else: # 否則先轉換CMYK
pix0 = fitz.Pixmap(fitz.csRGB, pix)
pix0.writePNG(os.path.join(pic_path, new_name))
pix0 = None
pix = None # 釋放資源
t1 = time.clock() # 圖片完成時間
print("執行時間:{}s".format(t1 - t0))
print("提取了{}張圖片".format(imgcount))
if__name__=='__main__':
pic_path = r'.\圖片'
path = "oracle資料庫安裝.pdf"
# 建立儲存圖片的資料夾
if os.path.exists(pic_path):
print("資料夾已存在,不必重新建立!")
pass
else:
os.mkdir(pic_path)
pdf2pic(path, pic_path)
這個是一個可以獨立執行的程式,作用就是將pdf中的圖片存放在圖片資料夾下面。在執行之前我們首先要使用pip install pymupdf庫,庫中包含了我們需要使用的fitz庫。
將圖片寫入word文件
為了大致保證圖片貼上的位置和PDF中的位置一致,我們需要在昨天程式的基礎上修改一下對每一頁PDF檔案的處理,對每一頁的物件進行判斷,若是文字則直接拷貝到word中,若是圖片則按照pdf中的順序依次拷貝到word中。程式碼如下:
# 迴圈遍歷列表,每次處理一個page內容
# doc.get_pages()獲取page列表
for page in doc.get_pages():
interpreter.process_page(page)
# 接收該頁面的LTPage物件
layout = device.get_result()
# 這裡的layout是一個LTPage物件 裡面存放著page解析出來的各種物件
# 一般包括LTTextBox,LTFigure,LTImage,LTTextBoxHorizontal等等一些對像
# 想要獲取文字就得獲取物件的text屬性
for x in layout:
try:
if (isinstance(x, LTTextBoxHorizontal)):
# with open('%s' % (save_path), 'a') as f:
# result = x.get_text()
# print(result)
# f.write(result + "\n")
result = x.get_text()
print(result)
doc_object.add_paragraph(result)
elif (isinstance(x, LTFigure)):
cont +=1
images = r".\圖片\圖片{}.png".format(cont)
print(images)
# doc.add_paragraph(string) # 新增文字
doc_object.add_picture(images, width=Inches(7)) # 新增圖, 設定寬度
except:
print("Failed")
最後我們再將主函式修改一下,進行呼叫
if __name__ == '__main__':
# 解析本地PDF文字,儲存到本地TXT
file_name = input("請輸入需要轉化的檔名:")
doc_name = input("請輸入轉化後的檔名(支援TXT、doc、HTML格式):")
pic_path = r'.\圖片'
flag = False
# 建立儲存圖片的資料夾
if os.path.exists(pic_path):
print("資料夾已存在,不必重新建立!")
pass
else:
os.mkdir(pic_path)
flag = True
PNGfromPDF.pdf2pic(file_name,pic_path)
doc = Document() # doc物件
# with open(r'菜鳥小白.pdf', 'rb') as pdf_html:
# parse(pdf_html, r'菜鳥小白的學習分享.doc')
with open(file_name, 'rb') as pdf_html:
parse(pdf_html, doc_name,doc)
doc.save(doc_name) # 儲存路徑
最終實現效果
原始PDF檔案
轉化後的word
細心的小夥伴一定發現了一些問題,就是圖片並沒有完全按照PDF的順序進行放置。這個我後來查閱資料和除錯程式發現:pdfminer程式在處理每一頁PDF時會將物件進行分類,返回的結果也是按照不同型別的物件分塊的,這樣就造成了我們還原的word中每一頁都是所有的文字在前,圖片在後的情況。
這個遺留就當做軟體的一個bug遺留吧,版本先行釋出,有需要獲取最新轉化工具的關注“菜鳥小白的學習分享”公眾號,回覆"PDFtoWORD_V1.1"獲取吧。
好了,今天的分享就到這裡,如果你也喜歡菜鳥小白的分享,就給菜鳥小白點選一個關注、在看、點贊+雞腿吧。
晚安~