识别PDF关键词,在文件页数和坐标

1.引入MAVEN依赖

在这里插入图片描述

 <dependency>
            <groupId>com.aspose.cells</groupId>
            <artifactId>aspose-cells</artifactId>
            <version>cell-8.5.2</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/src/main/resources/lib/aspose-cells-17.7.jar</systemPath>
        </dependency>

 <!-- https://mvnrepository.com/artifact/com.itextpdf/itextpdf -->
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.12</version>
        </dependency>

2.Excel转PDF

/**
     * excel 转换  Pdf
     *
     * @param fileFullPath 旧文件全路径   /home/2022-07/保密协议.xlsx
     */
    public static String excelPdf(String fileFullPath) {
        if (!getLicense()) {          // 验证License 若不验证则转化出的pdf文档会有水印产生
            return null;
        }
        FileInputStream excelstream = null;
        Workbook wb = null;
        FileOutputStream fileOS = null;
        PdfSaveOptions pdfSaveOptions = null;
        try {
            String path = fileFullPath.substring(0, fileFullPath.lastIndexOf("/") + 1);
            String fileName = fileFullPath.substring(fileFullPath.lastIndexOf("/") + 1, fileFullPath.lastIndexOf("."));
            String outFIleFullPath = path + fileName + ".pdf";
            File pdfFile = new File(outFIleFullPath); // 输出路径
            excelstream = new FileInputStream(fileFullPath);
            wb = new Workbook(excelstream);// excel路径,这里是先把数据放进缓存表里,然后把缓存表转化成PDF
            fileOS = new FileOutputStream(pdfFile);
            pdfSaveOptions = new PdfSaveOptions();
            pdfSaveOptions.setOnePagePerSheet(true);//参数true把内容放在一张PDF页面上;
            wb.save(fileOS, pdfSaveOptions);
            fileOS.close();
            return outFIleFullPath;
        } catch (Exception e) {
            e.printStackTrace();
            log.info("excel转换异常");
            return null;
        } finally {
            try {
                excelstream.close();
                fileOS.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }

        }
    }

    public static boolean getLicense() {
        boolean result = false;
        InputStream is = null;
        try {
            is =
                    FileUtil.class
                            .getClassLoader()
                            .getResourceAsStream(
                                    "license.xml"); //
            // license.xml这个文件你放在静态文件资源目录下就行了
            License aposeLic = new License();
            aposeLic.setLicense(is);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

3.word转PDF

    public static String wordTurnPdf(String doc, String pdf) {

        try {
            //word转PDF   pdf文件名
            File outputFile = new File(pdf);
            InputStream doc1 = new FileInputStream(doc);
            OutputStream outputStream = new FileOutputStream(outputFile);
            IConverter converter = LocalConverter.builder().build();
            converter.convert(doc1).as(DocumentType.DOCX).to(outputStream).as(DocumentType.PDF).execute();
            outputStream.close();
            converter.shutDown();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return pdf;
    }

4.PDF关键词定位识别

package com.datago.robot.common.utils;



import com.itextpdf.awt.geom.Rectangle2D.Float;
import com.itextpdf.text.pdf.PdfDictionary;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.parser.*;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
 * 获取pdf 劳模所在页数
 * HBO
 * 2022-10-27
 */
@Slf4j
public class ReadPDF {


    public static List<Integer> readPDF(String pdfFilePath, String keyword) {
        //1.给定文件
//        File pdfFile = new File("C:\\Users\\Administrator\\Desktop\\劳模先进基本信息模板-有数据.pdf");
        File pdfFile = new File(pdfFilePath);
        //2.定义一个byte数组,长度为文件的长度
        byte[] pdfData = new byte[(int) pdfFile.length()];
        //3.IO流读取文件内容到byte数组
        FileInputStream inputStream = null;
        try {
            inputStream = new FileInputStream(pdfFile);
            inputStream.read(pdfData);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                }
            }
        }
        //4.指定关键字
//        String keyword = "分部";
        //5.调用方法,给定关键字和文件
        List<float[]> positions = null;
        try {
            positions = findKeywordPostions(pdfData, keyword);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        //6.返回值类型是 List<float[]> 每个list元素代表一个匹配的位置,分别为 float[0]所在页码 float[1]所在x轴 float[2]所在y轴
//        System.out.println("total:" + positions.size());
        List<  Integer> list=new ArrayList();
        if (positions != null && positions.size() > 0) {
            for (float[] position : positions) {
//                System.out.print("pageNum: " + (int) position[0]);
//                System.out.print("\tx: " + position[1]);
//                System.out.println("\ty: " + position[2]);
//                map.put("pageNum", (int) position[0]);
                list.add((int) position[0]);
            }
        }
        return list;
    }

    /**
     * findKeywordPostions
     *
     * @param pdfData 通过IO流 PDF文件转化的byte数组
     * @param keyword 关键字
     * @return List<float [ ]> : float[0]:pageNum float[1]:x float[2]:y
     * @throws IOException
     */
    public static List<float[]> findKeywordPostions(byte[] pdfData, String keyword) throws IOException {
        List<float[]> result = new ArrayList<>();
        List<PdfPageContentPositions> pdfPageContentPositions = getPdfContentPostionsList(pdfData);
        for (PdfPageContentPositions pdfPageContentPosition : pdfPageContentPositions) {
            List<float[]> charPositions = findPositions(keyword, pdfPageContentPosition);
            if (charPositions == null || charPositions.size() < 1) {
                continue;
            }
            result.addAll(charPositions);
        }
        return result;
    }

    private static List<PdfPageContentPositions> getPdfContentPostionsList(byte[] pdfData) throws IOException {
        PdfReader reader = new PdfReader(pdfData);
        List<PdfPageContentPositions> result = new ArrayList<>();
        int pages = reader.getNumberOfPages();
        for (int pageNum = 1; pageNum <= pages; pageNum++) {
            float width = reader.getPageSize(pageNum).getWidth();
            float height = reader.getPageSize(pageNum).getHeight();
            PdfRenderListener pdfRenderListener = new PdfRenderListener(pageNum, width, height);
            //解析pdf,定位位置
            PdfContentStreamProcessor processor = new PdfContentStreamProcessor(pdfRenderListener);
            PdfDictionary pageDic = reader.getPageN(pageNum);
            PdfDictionary resourcesDic = pageDic.getAsDict(PdfName.RESOURCES);
            try {
                processor.processContent(ContentByteUtils.getContentBytesForPage(reader, pageNum), resourcesDic);
            } catch (IOException e) {
                reader.close();
                throw e;
            }
            String content = pdfRenderListener.getContent();
            List<CharPosition> charPositions = pdfRenderListener.getcharPositions();
            List<float[]> positionsList = new ArrayList<>();
            for (CharPosition charPosition : charPositions) {
                float[] positions = new float[]{charPosition.getPageNum(), charPosition.getX(), charPosition.getY()};
                positionsList.add(positions);
            }
            PdfPageContentPositions pdfPageContentPositions = new PdfPageContentPositions();
            pdfPageContentPositions.setContent(content);
            pdfPageContentPositions.setPostions(positionsList);
            result.add(pdfPageContentPositions);
        }
        reader.close();
        return result;
    }

    private static List<float[]> findPositions(String keyword, PdfPageContentPositions pdfPageContentPositions) {
        List<float[]> result = new ArrayList<>();
        String content = pdfPageContentPositions.getContent();
        List<float[]> charPositions = pdfPageContentPositions.getPositions();
        for (int pos = 0; pos < content.length(); ) {
            int positionIndex = content.indexOf(keyword, pos);
            if (positionIndex == -1) {
                break;
            }
            float[] postions = charPositions.get(positionIndex);
            result.add(postions);
            pos = positionIndex + 1;
        }
        return result;
    }

    private static class PdfPageContentPositions {
        private String content;
        private List<float[]> positions;

        public String getContent() {
            return content;
        }

        public void setContent(String content) {
            this.content = content;
        }

        public List<float[]> getPositions() {
            return positions;
        }

        public void setPostions(List<float[]> positions) {
            this.positions = positions;
        }
    }

    private static class PdfRenderListener implements RenderListener {
        private int pageNum;
        private float pageWidth;
        private float pageHeight;
        private StringBuilder contentBuilder = new StringBuilder();
        private List<CharPosition> charPositions = new ArrayList<>();

        public PdfRenderListener(int pageNum, float pageWidth, float pageHeight) {
            this.pageNum = pageNum;
            this.pageWidth = pageWidth;
            this.pageHeight = pageHeight;
        }

        public void beginTextBlock() {
        }

        public void renderText(TextRenderInfo renderInfo) {
            List<TextRenderInfo> characterRenderInfos = renderInfo.getCharacterRenderInfos();
            for (TextRenderInfo textRenderInfo : characterRenderInfos) {
                String word = textRenderInfo.getText();
                if (word.length() > 1) {
                    word = word.substring(word.length() - 1, word.length());
                }
                Float rectangle = textRenderInfo.getAscentLine().getBoundingRectange();
                float x = (float) rectangle.getX();
                float y = (float) rectangle.getY();
                //这两个是关键字在所在页面的XY轴的百分比
                float xPercent = Math.round(x / pageWidth * 10000) / 10000f;
                float yPercent = Math.round((1 - y / pageHeight) * 10000) / 10000f;
                CharPosition charPosition = new CharPosition(pageNum, (float) x, (float) y);
                charPositions.add(charPosition);
                contentBuilder.append(word);
            }
        }

        public void endTextBlock() {
        }

        public void renderImage(ImageRenderInfo renderInfo) {
        }

        public String getContent() {
            return contentBuilder.toString();
        }

        public List<CharPosition> getcharPositions() {
            return charPositions;
        }
    }

    private static class CharPosition {
        private int pageNum = 0;
        private float x = 0;
        private float y = 0;

        public CharPosition(int pageNum, float x, float y) {
            this.pageNum = pageNum;
            this.x = x;
            this.y = y;
        }

        public int getPageNum() {
            return pageNum;
        }

        public float getX() {
            return x;
        }

        public float getY() {
            return y;
        }

        @Override
        public String toString() {
            return "[pageNum=" + this.pageNum + ",x=" + this.x + ",y=" + this.y + "]";
        }
    }

}


5.aspose各种依赖包

aspose依赖

<think>嗯,用户想要遍历所有的PDF文件,这些PDF是图片型的,然后找到变更编号,并用这个编号来重命名文件。首先,我需要确认几个关键点。首先,图片型PDF指的是扫描件或者由图片组成的PDF,里面的文字不是可选的,对吧?这样的话,直接用常规的文本提取方法可能不行,得用OCR技术来识别文字。 接下来,用户提到要找到“变更编号”。这个变更编号的具体格式是什么样的呢?比如是固定位置出现的,还是有一定模式,比如包含“变更号:”后面跟着数字或字母的组合?如果用户没有说明,可能需要假设常见的格式,或者建议用户先确认样本中的编号规律。 然后,遍历PDF文件的部分。在Python中,可以用os模块来遍历目录,筛选出.pdf结尾的文件。对于每个PDF文件,需要将其转换为图像,然后使用OCR识别文字。可能需要用到PyMuPDF或者pdf2image库来处理PDF,转换为图片,再用Tesseract OCR进行识别。 不过,处理图片型PDF可能会比较耗时,特别是如果PDF页数多的话。用户可能需要考虑处理效率,比如是否只处理第一页或者特定页面,因为变更编号可能出现在固定的位置,比如首页的某个区域。 另外,重命名文件时要注意避免重复,以及处理特殊字符。还有,OCR的准确性可能影响结果,可能需要设置一些校验机制,比如正则表达式匹配,确保提取到的编号符合预期格式。如果找不到编号,可能需要记录错误或者跳过该文件。 用户可能没有提到的点包括:是否需要递归遍历子目录,处理后的文件存放位置,以及是否保留原文件等。这些可能需要进一步询问,但作为初步方案,可以默认处理当前目录下的所有PDF,直接重命名。 总结步骤大概是:1. 安装必要的库工具(Tesseract、PyMuPDF等)。2. 遍历PDF文件。3. 将每页PDF转为图片。4. 对图片进行OCR,提取文字。5. 用正则表达式找变更编号。6. 重命名文件。 可能需要提醒用户环境配置问题,比如Tesseract的安装路径,以及语言包的支持。如果变更编号包含中文,可能需要下载中文的训练数据。此外,测试单个文件确认流程正确性,再批量处理,避免意外错误。 还有,处理过程中最好记录成功失败的情况,方便用户后续检查。对于部分识别错误的文件,可能需要手动处理。代码方面,要确保异常处理,比如捕捉OCR错误或者文件访问问题,避免程序中途崩溃。</think>以下是通过Python实现图片型PDF文件识别并批量重命名的分步解决方案: 1. 环境准备 ```bash # 安装必需库 pip install pdf2image pytesseract python-docx # 安装Tesseract OCR引擎(Windows需单独下载安装) ``` 2. 代码实现 ```python import os import re import pytesseract from pdf2image import convert_from_path from PIL import Image # 配置Tesseract路径(Windows需要) pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe' def find_change_number(pdf_path): # 将PDF转换为图像列表 images = convert_from_path(pdf_path, dpi=300) # 定义编号正则表达式(根据实际格式调整) pattern = r'变更编号[::]\s*([A-Z0-9-]+)' for i, img in enumerate(images): # 裁剪关键区域(根据实际位置调整) width, height = img.size area = (width//4, height//10, width*3//4, height//5) # 示例区域 cropped = img.crop(area) # OCR识别 text = pytesseract.image_to_string(cropped, lang='chi_sim') # 正则匹配 match = re.search(pattern, text) if match: return match.group(1) # 可选:仅检查前3页提高效率 if i >= 2: break return None def rename_pdfs(folder_path): for filename in os.listdir(folder_path): if filename.lower().endswith('.pdf'): pdf_path = os.path.join(folder_path, filename) change_no = find_change_number(pdf_path) if change_no: new_name = f"{change_no}.pdf" new_path = os.path.join(folder_path, new_name) # 避免重复 counter = 1 while os.path.exists(new_path): new_name = f"{change_no}_{counter}.pdf" new_path = os.path.join(folder_path, new_name) counter += 1 os.rename(pdf_path, new_path) print(f"已重命名: {filename} -> {new_name}") else: print(f"未找到编号: {filename}") # 使用示例 rename_pdfs(r'您的PDF文件夹路径') ``` 3. 关键调整点 - 区域裁剪:通过修改`area`坐标定位编号位置 - 正则表达式:根据实际编号格式调整`pattern` - 语言设置:若含英文需添加`+eng`(`lang='chi_sim+eng'`) - 处理效率:通过`dpi`参数平衡识别质量与速度 4. 注意事项 - 建议先备份原始文件 - 大文件处理时需注意内存使用 - 中文识别准确率可通过以下方式提升: - 增加图像DPI(建议300-600) - 优化裁剪区域 - 添加自定义词典到Tesseract 5. 扩展优化方向 - 添加多线程处理 - 实现日志记录 - 支持子目录递归处理 - 添加GUI界面 请根据实际文件特征调整区域坐标正则表达式,建议先用单个文件测试后再批量处理。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值