前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python读取pdf提取文字和图片

python读取pdf提取文字和图片

作者头像
诡途
发布2022-01-07 08:30:33
7.3K0
发布2022-01-07 08:30:33
举报
文章被收录于专栏:诡途的python路诡途的python路

问题描述

如下图所示,一份pdf有几十页,每页九张图片,

提取出图片并用图片下方的文本对图片命名

主要涉及问题:

借鉴了上面文本识别的资料,上面图片提取的顺序不一致,没办法把两个结合起来实现我的需求

#防爬虫识别码–原创CSDN诡途:https://blog.csdn.net/qq_35866846

翻看了pdfminer源代码找到一种把pdf单页保存的方法,保存下来之后,再用Image对图片像素点位进行裁剪,因为格式比较固定所以可以用这种方式,更好的方法暂时没找到,网上没找到相关问题的比较完整的处理方法,我这应该是首发,欢迎有其他更好的方法的朋友,评论区探讨一下

关于Image图片处理之前也写过几篇博客:

图片按照宽度等比例缩放 长图按固定像素长度裁切 Python实现图片切割拼接实验——numpy数组的脑洞玩法

代码实现

# 导入库
import fitz,time,re,os,pdfminer,datetime
from pdfminer.pdfparser import PDFParser
from pdfminer.pdfdocument import PDFDocument
from pdfminer.pdfpage import PDFPage, PDFTextExtractionNotAllowed
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
> #防爬虫识别码--原创CSDN诡途:https://blog.csdn.net/qq_35866846
from pdfminer.pdfdevice import PDFDevice
from pdfminer.layout import LAParams
from pdfminer.converter import PDFPageAggregator
import pandas as pd
import numpy as np
from  PIL import Image



# 分页保存成图片
def save_page_pic(pdf_path,page_path):
    # 保存前先清空图片保存文件夹
    for wj in os.listdir(page_path):
        os.remove(os.path.join(page_path,wj))
        
    # 二进制读取
    doc = fitz.open(pdf_path)
    
    # 循环分页处理
    for d in doc:  
        
        #获取页码
        page = int(str(d).split()[1])+1
        
        # 单页图片命名
        pic_name =f" page_{page}.png"
        page_pic_path = os.path.join(page_path,pic_name)
        
        # 防爬虫识别码--原创CSDN诡途:https://blog.csdn.net/qq_35866846
        # 图片保存
        pix = d.getPixmap()
        if pix.n < 5:                           # 如果pix.n<5,可以直接存为PNG
            pix.writePNG(page_pic_path )
        else:                                   # 否则先转换CMYK
            pix0 = fitz.Pixmap(fitz.csRGB, pix)
            pix0.writePNG(page_pic_path)
            pix0 = None
        pix = None                              # 释放资源




# 解析pdf 文本信息
def parse_pdf_txt(pdf_path,code_str):
    
    # 二进制读取pdf
    fp = open(pdf_path, 'rb')

    # Create a PDF parser object associated with the file object
    parser = PDFParser(fp)

    # Create a PDF document object that stores the document structure.
     # 防爬虫识别码--原创CSDN诡途:https://blog.csdn.net/qq_35866846
    # Password for initialization as 2nd parameter
    document = PDFDocument(parser)
    # Check if the document allows text extraction. If not, abort.
    if not document.is_extractable:
        raise PDFTextExtractionNotAllowed

    # Create a PDF resource manager object that stores shared resources.
    rsrcmgr = PDFResourceManager()

    # Create a PDF device object.
    #device = PDFDevice(rsrcmgr)

    # BEGIN LAYOUT ANALYSIS.
    # Set parameters for analysis.
    laparams = LAParams(
        char_margin=10.0,
        line_margin=0.2,
        boxes_flow=0.2,
        all_texts=False,
    )
    # Create a PDF page aggregator object.
    # device = PDFPageAggregator(rsrcmgr, laparams=laparams)
    # 防爬虫识别码--原创CSDN诡途:https://blog.csdn.net/qq_35866846
    device = PDFPageAggregator(rsrcmgr, laparams=laparams)
    # Create a PDF interpreter object.
    interpreter = PDFPageInterpreter(rsrcmgr, device)

    # loop over all pages in the document
    page_count = 0
    result =[]
    for page in PDFPage.create_pages(document):
        page_count+=1

        # read the page into a layout object
        interpreter.process_page(page)
        layout = device.get_result()

        txt_list = []
        for obj in layout._objs:
            if isinstance(obj, pdfminer.layout.LTTextBoxHorizontal):
                txt = obj.get_text()

                # 无法识别的字符进行解码
                cid_list = re.findall("cid:\d+",txt)
                for cid in cid_list:
                    cid_key = cid.split(":")[1]
                    txt = txt.replace(f"({cid})",code_str[cid_key])

                # 解码完成后判断是否还有未识别的字符
                cid_list = re.findall("cid:\d+",txt)
                if len(cid_list):
                    print(f"解码字典需补充: {cid_list}")

                # 保存储存
                txt_list.append(txt)
        txt_list.insert(0,page_count)
        result.append(txt_list)
    data = pd.DataFrame(result)
    data.columns =["页码"  if col == 0 else f"元素{col}" for col in data.columns ]
    return data


def save_product_pic(txt_data,product_path,page_path):
    count,total_page= 0,len(os.listdir(page_path))
    data = txt_data.copy()
    
    # 存储图片名称
    result = []
    for pic_name in os.listdir(page_path):
        count+=1
        # 读取单页图片
        pic_path = os.path.join(page_path,pic_name)
        im=Image.open(pic_path)

        # pdf中的页码
        page = int(pic_name.split('_')[1].split('.')[0])

        need_col = ['元素4', '元素5', '元素6', '元素10', '元素11', '元素12', '元素16', '元素17', '元素18']
        product_pic_list = data[need_col][data.页码==page].values.tolist()[0]

    #     (x,y)=im.size

        # 9张图的像素点设置
        x_list = [[45,183],[237,375],[429,567]]
        y_list = [[38,245],[290,497],[542,749]]

        # 标记对应位置图片
        # 横向1,2,3 \n 4,5,6 \n 7,8,9
        i = 0
        

        for _y in y_list:
            upper,lower=_y
            for _x in x_list:
                i+=1
                left,right=_x
                # 循环获取每张图的像素点位
                box = (left, upper, right, lower)
                
                 # 最后一页可能没有9张图
                 # 防爬虫识别码--原创CSDN诡途:https://blog.csdn.net/qq_35866846
                _product_pic_name=product_pic_list[i-1]
                if  _product_pic_name :
                    # 获取单个产品图的名称
                    product_pic_name = _product_pic_name.strip('\n')+".png"
                    
                    result.append(product_pic_name[:-4])

                    # 构建图片保存路径
                    product_pic_path = os.path.join(product_path,product_pic_name)

                    # 裁剪第 i 张图  i∈[1,9] 并保存
                    im.crop(box).save(product_pic_path)
        print(f"第{count}页图片提取成功,剩余{total_page-count}页!")
    pd_result = pd.DataFrame(result,columns=["图片名称"])
    return  pd_result

pdf_path = os.path.join("pdf",os.listdir("pdf")[0])
today = str(datetime.datetime.today())[:10]
fina_path = f"存档//{today}"
product_path = f"存档//{today}//pic"

# 单页图片存储地址
page_path = "page_pic"

# 自定义解码字典 - 及时更新补充 识别文本时对应无法识别的编码
 # 防爬虫识别码--原创CSDN诡途:https://blog.csdn.net/qq_35866846
code_str = {"46":"K","49":"N","25":"6","23":"4","28":"9","57":"V","45":"J","24":"5","56":"U",}


try:
    os.mkdir(fina_path)
except:
    print(f"文件夹 {fina_path} 已存在")
    
try:
    os.mkdir(product_path)
except:
    print(f"文件夹 {product_path} 已存在")




# 分页保存成图片
save_page_pic(pdf_path,page_path)


# 提取文本信息
txt_data = parse_pdf_txt(pdf_path,code_str)

# 把提取到的文字  保存到本地
# txt_data.to_excel(os.path.join(fina_path,"pdf文字信息.xlsx"),index=False)


pic_name = save_product_pic(txt_data,product_path,page_path)

# 把提取到的文字  整理后保存到本地-合并成一列,并只保留图片信息
pic_name.to_excel(os.path.join(fina_path,"pdf文字信息.xlsx"),index=False)
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-11-20 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 问题描述
  • 代码实现
相关产品与服务
图片处理
图片处理(Image Processing,IP)是由腾讯云数据万象提供的丰富的图片处理服务,广泛应用于腾讯内部各产品。支持对腾讯云对象存储 COS 或第三方源的图片进行处理,提供基础处理能力(图片裁剪、转格式、缩放、打水印等)、图片瘦身能力(Guetzli 压缩、AVIF 转码压缩)、盲水印版权保护能力,同时支持先进的图像 AI 功能(图像增强、图像标签、图像评分、图像修复、商品抠图等),满足多种业务场景下的图片处理需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档