PDF操作,PDF提取文字并统计词频—快速预览PDF报告,


通过统计词频来快速预览PDF报告。本文提供了文字PDF和图片PDF提取文字的两类方式。
对于是文字类的PDF可以快速的提取其中文字,但是有许多PDF是图片格式,并不能直接提取文字。本文采取PDF转图片,并通过OCR识别文字生成文本,进而统计文本的词频的方式进行快速预览。

一、PDF转图片

1、PDF转图片

本文使用PyMuPDF模块进行转化。
1、 PyMuPD网上有许多资料,但是多数比较老,这个模块的API已有变动,本文做了更新。本模块安装需要pip install PyMuPDF,但是导入是fitz。该库不支持python3.10以上版本。
2、本文加了文件路径处理的功能find_pdf_files(directory)函数和以下部分。

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结尾的文件的完整文件路径
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()  # 开始时间
    print("imagePath=" + imagePath)
    pdfDoc = fitz.open(pdf)
    for pg in range(pdfDoc.page_count):
        page = pdfDoc[pg]
        rotate = int(0)
        # 每个尺寸的缩放系数为1.3,这将为我们生成分辨率提高2.6的图像。
        # 此处若是不做设置,默认图片大小为: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)  # 若图片文件夹不存在就创建
        # 提取不带扩展名的文件名
        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)  # 将图片写入指定的文件夹内
    endTime_pdf2img = datetime.datetime.now()  # 结束时间
    print('pdf2img时间=', (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、需要储存图片 的目录
        pyMuPDF_fitz(pdf, imagePath)

2、OCR图片转文字

本文使用的是百度开源的paddleocr库
pip3.10 install paddlepaddlepip install paddleocr,注意这两个库暂时不支持python3.10以上的版本,主要是paddleocr依赖的PyMuPDF不支持python3.10以上版本。

2.1、将图片上指定区域转换为文字
from paddleocr import PaddleOCR
import os
import re


#输出结果转字符串
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函数处理提取的文本
            processed_text = text_noposition(result, left=0, right=10000, bottom=500, top=2000)

            # 将处理后的文本追加到输出文本中
            output_text += processed_text + "\n"

            # 将输出文本写入.txt文件并关闭该文件
    with open(output_path, "a") as file:  # 可以根据需要更改文件名和路径
        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)
2.2、将全部图片转换为文字

去掉了区域选择参数,也可以采样将选择区域函数中,区域设置为极端值,例如(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函数处理提取的文本
            processed_text = text_noposition(result, left=0, right=10000, bottom=500, top=2000)

            # 将处理后的文本追加到输出文本中
            output_text += processed_text + "\n"

            # 将输出文本写入.txt文件并关闭该文件
    with open(output_path, "a") as file:  # 可以根据需要更改文件名和路径
        file.write(output_text)


3、读取高频词

读取结果、使用结巴分词,并统计词频。

视文件编码不同,如果报错gbk编码问题,打开文件部分需要改为:
f = open(file_path, encoding=‘utf-8’)

from collections import Counter
import jieba
import pandas as pd


def cut_with_filter(sentence, stopwords):
    # 使用结巴分词的精确模式进行分词
    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\结果.txt"

    # 要分词的文本
    f = open(file_path)
    text = f.read()
    #text = read_doc_file(file_path)
    # 停用词列表,你可以根据需要自行添加或修改
    stopwords = ["的", "了", "在", "是", "我", "有", "和", "就", "不", "人", "都", "一", "一个", "上", "也", "很", "到"]
    word_list=cut_with_filter(text,stopwords)
    chinese_list = [word for word in word_list if isinstance(word, str) and word.isalpha()]
    # 统计每个词的词频
    counter = Counter(chinese_list)
    word_freq = dict(counter)

    keys = pd.Series(list(word_freq.keys()))
    values = pd.Series(list(word_freq.values()))
        # 将分词结果和词频保存到DataFrame
    df = pd.DataFrame({'词': keys, '词频': values})

    print(df)

    # 将DataFrame保存到Excel文件
    df.to_excel('分词结果1.xlsx', index=False)

二、提取文字型PDF的文字

使用PyMuPDF库可以快速提取文字型PDF的文字。本文做了封装。

1、转化单个文件,使用pdf2txt函数,输入路径是PDF文件的路径
2、转化一个文件夹下,使用 pdf2txt_multi函数,输入路径是PDF所在的文件夹

import fitz  
import os
#转化单个文件
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)
            # 构建输入文件路径
            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__":
    # 输入和输出文件路径,当要转化一个文件夹时是文件夹路径。
    input_file =r"xx"
    output_file = "output.txt"
    pdf2txt_multi(input_file,output_file)

三、合并文字型PDF

使用python的fitz库将一个文件夹下的pdf合并成一个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")]

    # 创建一个新的PDF文件
    merged_pdf = fitz.open()

    # 遍历每个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:\工作\科创专班\资料\会议报告\2024研讨会"
    # 保存合并后的PDF文件
    output_pdf_path = "output_merged_pdf.pdf"
    print(f"合并完成,保存为:{output_pdf_path}")

四、图片型PDF转为word并合并

1、单进程模式

import datetime
import os
import fitz
from paddleocr import PaddleOCR
from docx import Document


# 输出以.pdf结尾的文件的完整文件路径
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()  # 开始时间
    pdf_doc = fitz.open(pdf)
    # 创建OCR模型
    ocr = PaddleOCR(use_angle_cls=True, lang="ch")

    # 创建Word文档
    doc = Document()

    for pg in range(pdf_doc.page_count):
        page = pdf_doc[pg]
        rotate = int(0)
        # 每个尺寸的缩放系数为1.3,这将为我们生成分辨率提高2.6的图像。
        # 此处若是不做设置,默认图片大小为: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)  # 若图片文件夹不存在就创建
        # 提取不带扩展名的文件名
        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)  # 将图片写入指定的文件夹内

        # 识别图片中的文字
        result = ocr.ocr(image_path)

        # 将识别结果写入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文件夹不存在就创建
    # 保存Word文档
    doc_name = f"{file_name}.docx"
    doc_path=f"{word_path}\\{doc_name}"

    doc.save(doc_path)

    end_time_pdf2img = datetime.datetime.now()  # 结束时间
    print('pdf2img时间=', (end_time_pdf2img - start_time_pdf2img).seconds)

    return doc_name

if __name__ == '__main__':

    # 测试
    pdf_folder = r"D:\工作\科创专班\资料\会议报告\24年工作会"
    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、多进程模式

多进程需要注意在每个进程内部import paddleocr包,否则无法序列化这个包导致程序无法运行。

def pyMuPDF_fitz(pdf, image_folder_path):
      from paddleocr import PaddleOCR

不能再开头导入包

import datetime
import os
import fitz
#from paddleocr import PaddleOCR
from joblib import Parallel, delayed
from docx import Document


# 输出以.pdf结尾的文件的完整文件路径
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()  # 开始时间
    pdf_doc = fitz.open(pdf)
    # 创建OCR模型
    ocr = PaddleOCR(use_angle_cls=True, lang="ch")

    # 创建Word文档
    doc = Document()

    for pg in range(pdf_doc.page_count):
        page = pdf_doc[pg]
        rotate = int(0)
        # 每个尺寸的缩放系数为1.3,这将为我们生成分辨率提高2.6的图像。
        # 此处若是不做设置,默认图片大小为: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)  # 若图片文件夹不存在就创建
        # 提取不带扩展名的文件名
        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)  # 将图片写入指定的文件夹内

        # 识别图片中的文字
        result = ocr.ocr(image_path)
        # 将识别结果写入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文件夹不存在就创建
    # 保存Word文档
    doc_name = f"{file_name}.docx"
    doc_path=f"{word_path}\\{doc_name}"

    doc.save(doc_path)

    end_time_pdf2img = datetime.datetime.now()  # 结束时间
    print('pdf2img时间=', (end_time_pdf2img - start_time_pdf2img).seconds)

    return doc_name

if __name__ == '__main__':

    # 测试
    pdf_folder = r"D:\data\2024\会议报告\24年工作会"
    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):
    # 创建一个新的Word文档
    merged_document = Document()

    # 遍历文件夹中的每个Word文档
    for filename in os.listdir(folder_path):
        if filename.endswith(".docx"):
            file_path = os.path.join(folder_path, filename)

            # 打开当前的Word文档
            current_document = Document(file_path)

            # 将当前文档的内容复制到合并文档中
            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)

六、将整个图片转换为文字并写入pandas表

采用先把内如写入list,再把list转DataFrame的形式实现。

import os
import pandas as pd
from paddleocr import PaddleOCR
from  pandasrw import view

#输出结果转字符串
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)
    # 创建 DataFrame 并写入数据
    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, [起始页, 结束页]) 提取开始到结束页的连续PDF,对于不连续的页面提取转换为多次连续的页面提取。

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)

    # 创建一个新的PDF文档对象
    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)

    # 关闭文档
    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])
  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风暴之零

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值