Python實(shí)現(xiàn)PDF提取文字并統(tǒng)計(jì)詞頻
通過統(tǒng)計(jì)詞頻來快速預(yù)覽PDF報(bào)告。本文提供了文字PDF和圖片PDF提取文字的兩類方式。
對(duì)于是文字類的PDF可以快速的提取其中文字,但是有許多PDF是圖片格式,并不能直接提取文字。本文采取PDF轉(zhuǎn)圖片,并通過OCR識(shí)別文字生成文本,進(jìn)而統(tǒng)計(jì)文本的詞頻的方式進(jìn)行快速預(yù)覽。
一、PDF轉(zhuǎn)圖片
1、PDF轉(zhuǎn)圖片
本文使用PyMuPDF模塊進(jìn)行轉(zhuǎn)化。
1、 PyMuPD網(wǎng)上有許多資料,但是多數(shù)比較老,這個(gè)模塊的API已有變動(dòng),本文做了更新。本模塊安裝需要pip install PyMuPDF,但是導(dǎo)入是fitz。該庫不支持python3.10以上版本。
2、本文加了文件路徑處理的功能find_pdf_files(directory)函數(shù)和以下部分。
filename = os.path.basename(pdf)
file_name, file_extension = os.path.splitext(filename)
image_path = f"{imagePath}\{file_name}{pg}.jpg"
代碼
import datetime
import os
import fitz
#輸出以.pdf結(jié)尾的文件的完整文件路徑
def find_pdf_files(directory):
pdf_files = []
for root, dirs, files in os.walk(directory):
for file in files:
if file.endswith('.pdf'):
pdf_file_path = os.path.join(root, file)
pdf_files.append(pdf_file_path)
return pdf_files
def pyMuPDF_fitz(pdf, imagePath):
startTime_pdf2img = datetime.datetime.now() # 開始時(shí)間
print("imagePath=" + imagePath)
pdfDoc = fitz.open(pdf)
for pg in range(pdfDoc.page_count):
page = pdfDoc[pg]
rotate = int(0)
# 每個(gè)尺寸的縮放系數(shù)為1.3,這將為我們生成分辨率提高2.6的圖像。
# 此處若是不做設(shè)置,默認(rèn)圖片大小為:792X612, dpi=96
zoom_x = 1.33333333 # (1.33333333-->1056x816) (2-->1584x1224)
zoom_y = 1.33333333
mat = fitz.Matrix(zoom_x, zoom_y).prerotate(rotate)
pix = page.get_pixmap(matrix=mat, alpha=False)
if not os.path.exists(imagePath): # 判斷存放圖片的文件夾是否存在
os.makedirs(imagePath) # 若圖片文件夾不存在就創(chuàng)建
# 提取不帶擴(kuò)展名的文件名
filename = os.path.basename(pdf)
file_name, file_extension = os.path.splitext(filename)
image_path = f"{imagePath}\{file_name}{pg}.jpg"
pix.save(image_path) # 將圖片寫入指定的文件夾內(nèi)
endTime_pdf2img = datetime.datetime.now() # 結(jié)束時(shí)間
print('pdf2img時(shí)間=', (endTime_pdf2img - startTime_pdf2img).seconds)
if __name__ == "__main__":
path=r"xx"
flist=find_pdf_files(path)
# 1、PDF地址
imagePath = r"xx"
for pdf in flist:
# 2、需要儲(chǔ)存圖片 的目錄
pyMuPDF_fitz(pdf, imagePath)
2、OCR圖片轉(zhuǎn)文字
本文使用的是百度開源的paddleocr庫
先pip3.10 install paddlepaddle再pip install paddleocr,注意這兩個(gè)庫暫時(shí)不支持python3.10以上的版本,主要是paddleocr依賴的PyMuPDF不支持python3.10以上版本。
將圖片上指定區(qū)域轉(zhuǎn)換為文字
from paddleocr import PaddleOCR
import os
import re
#輸出結(jié)果轉(zhuǎn)字符串
def text_noposition(data, left, right, bottom, top):
text_res = ""
# data[0]包含位置和文本信息
for i in data[0]:
# i[0][0][0]是橫向,i[0][0][1]是位置的縱向
x, y = i[0][0][0], i[0][0][1]
if left < x < right and bottom < y < top:
# i[1][0]是文字
text_res = text_res + i[1][0]
return text_res
def convert_png_to_txt(dir_path,output_path):
# 初始化PaddleOCR
ocr = PaddleOCR(use_angle_cls=True, lang="ch")
output_text = ""
# 遍歷指定目錄下的所有.png文件
for filename in os.listdir(dir_path):
if filename.endswith('.jpg'):
file_path = os.path.join(dir_path, filename)
# 使用PaddleOCR提取圖片中的文本
result = ocr.ocr(file_path, cls=True)
print(result)
# 使用text_noposition函數(shù)處理提取的文本
processed_text = text_noposition(result, left=0, right=10000, bottom=500, top=2000)
# 將處理后的文本追加到輸出文本中
output_text += processed_text + "\n"
# 將輸出文本寫入.txt文件并關(guān)閉該文件
with open(output_path, "a") as file: # 可以根據(jù)需要更改文件名和路徑
file.write(output_text)
# 指定要處理的圖片的目錄
dir_path = r'D:\data\2024\PDF\xx'
# 文件輸出路徑
output_path = r'D:\data\2024\PDF\xx'
convert_png_to_txt(dir_path,output_path)
將全部圖片轉(zhuǎn)換為文字
去掉了區(qū)域選擇參數(shù),也可以采樣將選擇區(qū)域函數(shù)中,區(qū)域設(shè)置為極端值,例如(0,10000,0,10000)
def text_noposition(data):
text_res = ""
# data[0]包含位置和文本信息
for i in data[0]:
# i[1][0]是文字
text_res = text_res + i[1][0]
return text_res
def convert_png_to_txt(dir_path,output_path):
# 初始化PaddleOCR
ocr = PaddleOCR(use_angle_cls=True, lang="ch")
output_text = ""
# 遍歷指定目錄下的所有.png文件
for filename in os.listdir(dir_path):
if filename.endswith('.jpg'):
file_path = os.path.join(dir_path, filename)
# 使用PaddleOCR提取圖片中的文本
result = ocr.ocr(file_path, cls=True)
print(result)
# 使用text_noposition函數(shù)處理提取的文本
processed_text = text_noposition(result, left=0, right=10000, bottom=500, top=2000)
# 將處理后的文本追加到輸出文本中
output_text += processed_text + "\n"
# 將輸出文本寫入.txt文件并關(guān)閉該文件
with open(output_path, "a") as file: # 可以根據(jù)需要更改文件名和路徑
file.write(output_text)
3、讀取高頻詞
讀取結(jié)果、使用結(jié)巴分詞,并統(tǒng)計(jì)詞頻。
視文件編碼不同,如果報(bào)錯(cuò)gbk編碼問題,打開文件部分需要改為:
f = open(file_path, encoding=‘utf-8’)
from collections import Counter
import jieba
import pandas as pd
def cut_with_filter(sentence, stopwords):
# 使用結(jié)巴分詞的精確模式進(jìn)行分詞
seg_list = jieba.cut(sentence, cut_all=False)
# 去除停用詞
filtered_seg_list = [word for word in seg_list if word not in stopwords]
return filtered_seg_list
if __name__ == '__main__':
file_path = r"D:\data\2023\pdf\pdf\結(jié)果.txt"
# 要分詞的文本
f = open(file_path)
text = f.read()
#text = read_doc_file(file_path)
# 停用詞列表,你可以根據(jù)需要自行添加或修改
stopwords = ["的", "了", "在", "是", "我", "有", "和", "就", "不", "人", "都", "一", "一個(gè)", "上", "也", "很", "到"]
word_list=cut_with_filter(text,stopwords)
chinese_list = [word for word in word_list if isinstance(word, str) and word.isalpha()]
# 統(tǒng)計(jì)每個(gè)詞的詞頻
counter = Counter(chinese_list)
word_freq = dict(counter)
keys = pd.Series(list(word_freq.keys()))
values = pd.Series(list(word_freq.values()))
# 將分詞結(jié)果和詞頻保存到DataFrame
df = pd.DataFrame({'詞': keys, '詞頻': values})
print(df)
# 將DataFrame保存到Excel文件
df.to_excel('分詞結(jié)果1.xlsx', index=False)
二、提取文字型PDF的文字
使用PyMuPDF庫可以快速提取文字型PDF的文字。本文做了封裝。
1、轉(zhuǎn)化單個(gè)文件,使用pdf2txt函數(shù),輸入路徑是PDF文件的路徑
2、轉(zhuǎn)化一個(gè)文件夾下,使用 pdf2txt_multi函數(shù),輸入路徑是PDF所在的文件夾
import fitz
import os
#轉(zhuǎn)化單個(gè)文件
def pdf2txt(input_file,output_file):
with fitz.open(input_file) as doc:
text = ""
for page in doc.pages():
text += page.get_text() # 注意這里使用了 get_text() 方法
with open(output_file, "w", encoding="utf-8") as f:
f.write(text)
return text
def pdf2txt_multi(input_folder, output_file):
# 遍歷輸入文件夾中的所有文件
for file_name in os.listdir(input_folder):
if file_name.endswith(".pdf"):
print(file_name)
# 構(gòu)建輸入文件路徑
input_file = os.path.join(input_folder, file_name)
# 打開PDF文件,并寫入txt文件
with fitz.open(input_file) as doc:
text = ""
for page in doc.pages():
text += page.get_text() # 注意這里使用了 get_text() 方法
with open(output_file, "w", encoding="utf-8") as f:
f.write(text)
return text
if __name__ == "__main__":
# 輸入和輸出文件路徑,當(dāng)要轉(zhuǎn)化一個(gè)文件夾時(shí)是文件夾路徑。
input_file =r"xx"
output_file = "output.txt"
pdf2txt_multi(input_file,output_file)三、合并文字型PDF
使用python的fitz庫將一個(gè)文件夾下的pdf合并成一個(gè)pdf
import os
import fitz
def merge_pdfs(pdf_folder, output_pdf_path):
pdf_files = [f for f in os.listdir(pdf_folder) if f.endswith(".pdf")]
# 創(chuàng)建一個(gè)新的PDF文件
merged_pdf = fitz.open()
# 遍歷每個(gè)PDF文件并將其插入到合并文件中
for pdf_file in pdf_files:
pdf_path = os.path.join(pdf_folder, pdf_file)
pdf = fitz.open(pdf_path)
merged_pdf.insert_pdf(pdf)
merged_pdf.save(output_pdf_path)
merged_pdf.close()
if __name__ == '__main__':
# 獲取文件夾下所有PDF文件的路徑
pdf_folder = r"D:\工作\科創(chuàng)專班\資料\會(huì)議報(bào)告\2024研討會(huì)"
# 保存合并后的PDF文件
output_pdf_path = "output_merged_pdf.pdf"
print(f"合并完成,保存為:{output_pdf_path}")
四、圖片型PDF轉(zhuǎn)為word并合并
1、單進(jìn)程模式
import datetime
import os
import fitz
from paddleocr import PaddleOCR
from docx import Document
# 輸出以.pdf結(jié)尾的文件的完整文件路徑
def find_pdf_files(directory):
pdf_files = []
for root, dirs, files in os.walk(directory):
for file in files:
if file.endswith('.pdf'):
pdf_file_path = os.path.join(root, file)
pdf_files.append(pdf_file_path)
return pdf_files
def text_noposition(data, left, right, bottom, top):
text_res = ""
# data[0]包含位置和文本信息
for i in data[0]:
# i[0][0][0]是橫向,i[0][0][1]是位置的縱向
x, y = i[0][0][0], i[0][0][1]
if left < x < right and bottom < y < top:
# i[1][0]是文字
text_res = text_res + i[1][0]
return text_res
def pyMuPDF_fitz(pdf, image_folder_path):
start_time_pdf2img = datetime.datetime.now() # 開始時(shí)間
pdf_doc = fitz.open(pdf)
# 創(chuàng)建OCR模型
ocr = PaddleOCR(use_angle_cls=True, lang="ch")
# 創(chuàng)建Word文檔
doc = Document()
for pg in range(pdf_doc.page_count):
page = pdf_doc[pg]
rotate = int(0)
# 每個(gè)尺寸的縮放系數(shù)為1.3,這將為我們生成分辨率提高2.6的圖像。
# 此處若是不做設(shè)置,默認(rèn)圖片大小為:792X612, dpi=96
zoom_x = 1.33333333 # (1.33333333-->1056x816) (2-->1584x1224)
zoom_y = 1.33333333
mat = fitz.Matrix(zoom_x, zoom_y).prerotate(rotate)
pix = page.get_pixmap(matrix=mat, alpha=False)
if not os.path.exists(image_folder_path): # 判斷存放圖片的文件夾是否存在
os.makedirs(image_folder_path) # 若圖片文件夾不存在就創(chuàng)建
# 提取不帶擴(kuò)展名的文件名
filename = os.path.basename(pdf)
file_name, file_extension = os.path.splitext(filename)
print(file_name,"頁碼",pg)
image_path = f"{image_folder_path}\\{file_name}_{pg}.jpg"
pix.save(image_path) # 將圖片寫入指定的文件夾內(nèi)
# 識(shí)別圖片中的文字
result = ocr.ocr(image_path)
# 將識(shí)別結(jié)果寫入Word文檔
doc.add_paragraph(f"{file_name}")
doc.add_paragraph(f"頁碼:{pg+1}")
processed_text = text_noposition(result, left=0, right=10000, bottom=500, top=2000)
doc.add_paragraph(processed_text)
if not os.path.exists(word_path): # 判斷存放word的文件夾是否存在
os.makedirs(word_path) # 若word文件夾不存在就創(chuàng)建
# 保存Word文檔
doc_name = f"{file_name}.docx"
doc_path=f"{word_path}\\{doc_name}"
doc.save(doc_path)
end_time_pdf2img = datetime.datetime.now() # 結(jié)束時(shí)間
print('pdf2img時(shí)間=', (end_time_pdf2img - start_time_pdf2img).seconds)
return doc_name
if __name__ == '__main__':
# 測(cè)試
pdf_folder = r"D:\工作\科創(chuàng)專班\資料\會(huì)議報(bào)告\24年工作會(huì)"
image_folder = r"xx"
word_path = r"xx"
pdf_files = find_pdf_files(pdf_folder)
for pdf_file in pdf_files:
pyMuPDF_fitz(pdf_file, image_folder)
2、多進(jìn)程模式
多進(jìn)程需要注意在每個(gè)進(jìn)程內(nèi)部import paddleocr包,否則無法序列化這個(gè)包導(dǎo)致程序無法運(yùn)行。
def pyMuPDF_fitz(pdf, image_folder_path):
from paddleocr import PaddleOCR
不能再開頭導(dǎo)入包
import datetime
import os
import fitz
#from paddleocr import PaddleOCR
from joblib import Parallel, delayed
from docx import Document
# 輸出以.pdf結(jié)尾的文件的完整文件路徑
def find_pdf_files(directory):
pdf_files = []
for root, dirs, files in os.walk(directory):
for file in files:
if file.endswith('.pdf'):
pdf_file_path = os.path.join(root, file)
pdf_files.append(pdf_file_path)
return pdf_files
def text_noposition(data, left, right, bottom, top):
text_res = ""
# data[0]包含位置和文本信息
for i in data[0]:
# i[0][0][0]是橫向,i[0][0][1]是位置的縱向
x, y = i[0][0][0], i[0][0][1]
if left < x < right and bottom < y < top:
# i[1][0]是文字
text_res = text_res + i[1][0]
return text_res
def pyMuPDF_fitz(pdf, image_folder_path):
from paddleocr import PaddleOCR
start_time_pdf2img = datetime.datetime.now() # 開始時(shí)間
pdf_doc = fitz.open(pdf)
# 創(chuàng)建OCR模型
ocr = PaddleOCR(use_angle_cls=True, lang="ch")
# 創(chuàng)建Word文檔
doc = Document()
for pg in range(pdf_doc.page_count):
page = pdf_doc[pg]
rotate = int(0)
# 每個(gè)尺寸的縮放系數(shù)為1.3,這將為我們生成分辨率提高2.6的圖像。
# 此處若是不做設(shè)置,默認(rèn)圖片大小為:792X612, dpi=96
zoom_x = 1.33333333 # (1.33333333-->1056x816) (2-->1584x1224)
zoom_y = 1.33333333
mat = fitz.Matrix(zoom_x, zoom_y).prerotate(rotate)
pix = page.get_pixmap(matrix=mat, alpha=False)
if not os.path.exists(image_folder_path): # 判斷存放圖片的文件夾是否存在
os.makedirs(image_folder_path) # 若圖片文件夾不存在就創(chuàng)建
# 提取不帶擴(kuò)展名的文件名
filename = os.path.basename(pdf)
file_name, file_extension = os.path.splitext(filename)
print(file_name,"頁碼",pg)
image_path = f"{image_folder_path}\\{file_name}_{pg}.jpg"
pix.save(image_path) # 將圖片寫入指定的文件夾內(nèi)
# 識(shí)別圖片中的文字
result = ocr.ocr(image_path)
# 將識(shí)別結(jié)果寫入Word文檔
doc.add_paragraph(f"{file_name}")
doc.add_paragraph(f"頁碼:{pg+1}")
processed_text = text_noposition(result, left=0, right=10000, bottom=500, top=2000)
doc.add_paragraph(processed_text)
if not os.path.exists(word_path): # 判斷存放word的文件夾是否存在
os.makedirs(word_path) # 若word文件夾不存在就創(chuàng)建
# 保存Word文檔
doc_name = f"{file_name}.docx"
doc_path=f"{word_path}\\{doc_name}"
doc.save(doc_path)
end_time_pdf2img = datetime.datetime.now() # 結(jié)束時(shí)間
print('pdf2img時(shí)間=', (end_time_pdf2img - start_time_pdf2img).seconds)
return doc_name
if __name__ == '__main__':
# 測(cè)試
pdf_folder = r"D:\data\2024\會(huì)議報(bào)告\24年工作會(huì)"
image_folder = r"D:\data\2024\picture"
word_path = r"D:\data\2024\word"
pdf_files = find_pdf_files(pdf_folder)
# for pdf_file in pdf_files:
# pyMuPDF_fitz(pdf_file, image_folder)
#paddleocr不能序列化,不能使用
results = Parallel(n_jobs=-1,)(
delayed(pyMuPDF_fitz)(pdf_file, image_folder) for pdf_file in pdf_files)
五、合并文件夾中的word
from docx import Document
import os
def merge_word_documents(folder_path, output_path):
# 創(chuàng)建一個(gè)新的Word文檔
merged_document = Document()
# 遍歷文件夾中的每個(gè)Word文檔
for filename in os.listdir(folder_path):
if filename.endswith(".docx"):
file_path = os.path.join(folder_path, filename)
# 打開當(dāng)前的Word文檔
current_document = Document(file_path)
# 將當(dāng)前文檔的內(nèi)容復(fù)制到合并文檔中
for element in current_document.element.body:
merged_document.element.body.append(element)
# 保存合并后的文檔
merged_document.save(output_path)
# 程序入口
if __name__ == "__main__":
folder_path = r"your_folder_path"
output_path = r"output_folder/merged_document.docx"
merge_word_documents(folder_path, output_path)
六、將整個(gè)圖片轉(zhuǎn)換為文字并寫入pandas表
采用先把內(nèi)如寫入list,再把list轉(zhuǎn)DataFrame的形式實(shí)現(xiàn)。
import os
import pandas as pd
from paddleocr import PaddleOCR
from pandasrw import view
#輸出結(jié)果轉(zhuǎn)字符串
def text_noposition(data):
data_res = []
# data[0]包含位置和文本信息
for i in data[0]:
# i[0][0][0]是橫向,i[0][0][1]是位置的縱向
x, y = i[0][0][0], i[0][0][1]
# i[1][0]是文字
data_res.append(i[1][0])
return data_res
def convert_png_to_txt(dir_path):
# 初始化PaddleOCR
ocr = PaddleOCR(use_angle_cls=True, lang="ch")
list_text =[]
data_text=[]
# 遍歷指定目錄下的所有.png文件
for filename in os.listdir(dir_path):
if filename.endswith('.jpg'):
file_path = os.path.join(dir_path, filename)
# 使用PaddleOCR提取圖片中的文本
result = ocr.ocr(file_path, cls=True)
data_text = text_noposition(result)
list_text=list_text+data_text
print(list_text)
# 創(chuàng)建 DataFrame 并寫入數(shù)據(jù)
df = pd.DataFrame(list_text)
return df
# 指定要處理的圖片的目錄
dir_path = r"D:\data\2024\pic\d"
df=convert_png_to_txt(dir_path)
view(df)
七、提取PDF部分頁
extract_pages_to_new_pdf(input_path, output_path, [起始頁, 結(jié)束頁]) 提取開始到結(jié)束頁的連續(xù)PDF,對(duì)于不連續(xù)的頁面提取轉(zhuǎn)換為多次連續(xù)的頁面提取。
import fitz # PyMuPDF
def extract_pages_to_new_pdf(input_pdf_path, output_pdf_path, page_numbers):
# 打開原始PDF文件
pdf_doc = fitz.open(input_pdf_path)
# 創(chuàng)建一個(gè)新的PDF文檔對(duì)象
new_pdf = fitz.open()
# 遍歷要提取的頁面索引
new_pdf.insert_pdf(pdf_doc, from_page=min(page_numbers), to_page=max(page_numbers))
# 保存新的PDF文件
new_pdf.save(output_pdf_path)
# 關(guān)閉文檔
pdf_doc.close()
new_pdf.close()
if __name__ == '__main__':
input_path=r 文件名
output_path=r""
extract_pages_to_new_pdf(input_path, output_path, [25, 42])
到此這篇關(guān)于Python實(shí)現(xiàn)PDF提取文字并統(tǒng)計(jì)詞頻的文章就介紹到這了,更多相關(guān)Python PDF操作內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
利用python實(shí)現(xiàn)全屏愛心雨向喜歡的人表白
馬上520了,教大家用Python做一個(gè)下愛心雨的特效,這篇文章主要給大家介紹了關(guān)于利用python實(shí)現(xiàn)全屏愛心雨向喜歡的人表白的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-05-05
Python實(shí)現(xiàn)自動(dòng)化接收與處理手機(jī)驗(yàn)證碼
在移動(dòng)互聯(lián)網(wǎng)時(shí)代,短信驗(yàn)證碼已成為身份驗(yàn)證、賬號(hào)注冊(cè)等環(huán)節(jié)的重要安全手段,本文將介紹如何利用Python實(shí)現(xiàn)驗(yàn)證碼的自動(dòng)接收,識(shí)別與轉(zhuǎn)發(fā),需要的可以參考下2025-03-03
python中使用百度音樂搜索的api下載指定歌曲的lrc歌詞
這篇文章主要介紹了python中使用百度音樂搜索的api下載指定歌曲的lrc歌詞,同時(shí)也分析出了歌曲的下載地址,需要的朋友可以參考下2014-07-07
Python使用擴(kuò)展庫pywin32實(shí)現(xiàn)批量文檔打印實(shí)例
這篇文章主要介紹了Python使用擴(kuò)展庫pywin32實(shí)現(xiàn)批量文檔打印實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-04-04
Python操作PDF實(shí)現(xiàn)制作數(shù)據(jù)報(bào)告
Python操作PDF的庫有很多,比如PyPDF2、pdfplumber、PyMuPDF等等。本文將利用FPDF模塊操作PDF實(shí)現(xiàn)制作數(shù)據(jù)報(bào)告,感興趣的小伙伴可以嘗試一下2022-12-12

