Java实战:高效提取PDF文件指定坐标的文本内容

这篇具有很好参考价值的文章主要介绍了Java实战:高效提取PDF文件指定坐标的文本内容。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Java实战:高效提取PDF文件指定坐标的文本内容,web开发,编程艺术,并发编程,java,pdf,批量PDF文本提取,pdfbox

前言

临时接到一个紧急需要处理的事项。业务侧一个同事有几千个PDF文件需要整理:需要从文件中的指定位置获取对应的编号和地址。
要的急,工作量大。所以就问到技术部有没有好的解决方案。
问技术的话就只能写个demo跑下了。

解决办法

1. 研究下PDF文档,找出解决方案

PDF的文档看起来比较简单,因为只是需要读取两个坐标位置的文本内容,而且位置相对固定。所以就直接用java的第三方库pdfbox来操作PDF文档。

2. 找个能操作PDF的第三方库pdfbox。

  1. 先下载pdfbox的jar包。
    官网介绍
  2. pdfbox能干啥:
    • pdfbox是Apache软件基金会的一个开源项目,它提供API和工具来处理PDF文档。

    • pdfbox是Apache PDFBox的Java版本,它提供了一个类库,用于读取,写入,转换和创建PDF文档。

    • pdfbox支持处理各种PDF特性,如文本,字体,图像,表单字段,注释,书签,页面布局等。

    • pdfbox还提供了对加密和数字签名PDF文档的支持,以及对PDF文档的提取和合并。

    • pdfbox还提供了对PDF文档的验证,签名验证,加密验证和数字签名的支持。

    • PDFBox是一个用于处理PDF文档的Java库。它提供了一组功能强大的API,可以用于创建、修改和提取PDF文档的内容。PDFBox可以用于各种用途,包括生成PDF文档、提取文本和图像、合并和拆分PDF文件、添加水印和书签等。

    • PDFBox支持处理各种PDF特性,如文本、字体、图像、表单字段、注释、书签、页面布局等。它还提供了对加密和数字签名PDF文档的支持,以及对PDF文档的高级操作,如提取文本位置信息、提取图像和字体等。

3. maven加载包

      pdfbox有三个大的版本,每个版本差异较大,这个时候如果要引入的时候,要注意对应的版本了,否则demo就有可能跑不起来。
      Java实战:高效提取PDF文件指定坐标的文本内容,web开发,编程艺术,并发编程,java,pdf,批量PDF文本提取,pdfbox
      pdfbox最新的大版本是3.0。作为新时代的青年,肯定要与时俱进。3.0肯定是要用上的。

3. 先验证下第三方库是否可行

下载jar包后,直接用java代码跑下demo。 demo读取pdf文档内容并输出文本数据到控制台

    import org.apache.pdfbox.pdmodel.PDDocument;
    import org.apache.pdfbox.text.PDFTextStripper;

    import java.io.File;
    import java.io.IOException;
    public class PDFBoxDemo {
        public static void main(String[] args) throws IOException {
            PDDocument document = PDDocument.load(new File("D:\\pdf\\test.pdf"));
            PDFTextStripper stripper = new PDFTextStripper();
            String text = stripper.getText(document);
            System.out.println(text);
            document.close();
        }
    }

发现demo跑起来后,报错。
原因是因为demo是2.0的版本,而当前的jar包是3.0的版本。PDDocument.load这个修改为Loader.load就OK了。

接下来,就是如何获取到指定坐标位置的文本内容。

4. 确认文本在PDF文档中的坐标位置。

确认PDF文本坐标一般有两种方案。

1. 代码校验(最精准)

先用demo跑下,看下是否可以读取到指定坐标位置的文本内容。

 /**
    * 获取文档坐标
    * @param  file PDF文件对象
    * @param sourceTex 匹配的字符
    * @return 坐标
    */
   public static Point getPoint(File file,String sourceTex) {
       Point point = new Point();
       //获取文档坐标
      try {
        PDDocument document =  Loader.loadPDF(file);
        PDFTextStripper textStripper = new PDFTextStripper() {
            @Override
            protected void writeString(String text, List<TextPosition> textPositions) throws IOException {
                if (text.contains(targetText)) {
                    TextPosition textPositionStart = textPositions.get(0);
                    TextPosition textPositionEnd = textPositions.get(textPositions.size()-1);
                    point.setX(textPositionStart.getX());
                    point.setY(textPositionStart.getY()); 
                }
            }
        };

        textStripper.setSortByPosition(true);
        textStripper.setStartPage(1);
        textStripper.setEndPage(document.getNumberOfPages());

        textStripper.getText(document);

        document.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
        return point;
    }

跑完demo后,发现可以读取到指定坐标位置的文本内容。
这里会有个小问题,就是返回的坐标点有的会有小数。因为当前返回类型float,所以需要转换成int。

2. 最直接粗暴的方法。

  1. 福昕PDF文档工具。
  2. 直接用福昕PDF文档定位工具定位坐标。
  说实话,开发比较少用这种方式,因为感觉有点lower(其实是自己不太会用)

5. 整个demo先验证第三方库是否可行。

拿1个文件试试水

 public static void main(String[] args) {
        String filePath = "D:\\test\\test.pdf";
         try {
            PDDocument document = Loader.loadPDF(file);
            PDFTextStripperByArea  textStripper = new PDFTextStripperByArea ();
            Rectangle rectangle = new Rectangle(80,120, 250,10);
            String regionName = "regionName";
            textStripper.addRegion(regionName, rectangle);
            PDPage page = document.getPage(0);
            textStripper.extractRegions(page);
            String text = textStripper.getTextForRegion(regionName);
  
            System.out.println(text);
          
            textStripper.setSortByPosition(true);
            textStripper.setStartPage(1);
            textStripper.setEndPage(document.getNumberOfPages());
            textStripper.getText(document);
            document.close();
        }catch (IOException e) {
            e.printStackTrace();
        }
      
    }

结果能够正常输出对应的文本内容。

6. 整活上代码。

奉上全部demo代码

package com.example.demo;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.fastjson2.JSON;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.text.PDFTextStripper;
import org.apache.pdfbox.text.PDFTextStripperByArea;
import org.apache.pdfbox.text.TextPosition;
import org.springframework.boot.test.autoconfigure.data.cassandra.DataCassandraTest;


import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Desc: 验证pdfbox的可行性
 *
 * @author admin
 * @date since 2023/8/8 18:44
 */

public class PdfDemo {
	//要匹配的位置内容点
    private  static final String[] target= {"name", "address"};
    public static void main(String[] args) {
       ExcelWriter excelWriter= ExcelUtil.getWriter("D:\\test\\pdf\\test.xls");
       String folderPath = "D:\\test\\pdf";
       File folder = new File(folderPath);
       if (folder.exists() && folder.isDirectory()) {
           List<Map<String,Object>>  mps =  listPdfFiles(folder);
           excelWriter.write(mps, true);
       } else {
           System.out.println("Invalid folder path.");
       }
       excelWriter.close();
    }
	/**
     * 获取pdf文件列表
     *
     * @param folder 文件夹
     * @return {@code List<Map<String,Object>>}
     */
    private static  List<Map<String,Object>>  listPdfFiles(File folder) {
        List<Map<String,Object>> mps = new ArrayList<>();
        File[] files = folder.listFiles();
        if (files != null) {
            for (File file : files) {
                if (file.isDirectory()) {
                    listPdfFiles(file); // 递归调用,处理子文件夹
                } else {
                    String fileName = file.getName();
                    if (fileName.toLowerCase().endsWith(".pdf")) {
                        mps.add(getLineData(file));
                    }
                }
            }
        }
        return mps;
    }
    /**
     * 行数据
     *
     * @param file 文件
     * @return {@code Map<String,Object>}
     */
    public static Map<String,Object> getLineData(File file){
        Map<String,Object> lineData = new HashMap<>(target.length+2);
        List<Point> pointList =  getPoint(file);
        String[]  arr=  getPointValue(file, pointList.stream().map(s -> new Rectangle(s.getX(), s.getY(), 260, 10)).toArray(Rectangle[]::new));
        if(arr.length>=target.length) {
        for(int i=0;i<target.length;i++)
        {
            lineData.put(target[i], arr[i]);
        }
            lineData.put("fileName", file.getName().toLowerCase().replace(".pdf", ""));
        }
      return lineData;
    }
 	/**
     * 获得PDF指定坐标点文本值
     *
     * @param file       文件
     * @param rectangles 矩形坐标
     * @return {@code String[]}
     */
    public  static String[] getPointValue( File file,Rectangle... rectangles){
        String[] textArr = new String[rectangles.length];
       // String text="";
        try {
            PDDocument document = Loader.loadPDF(file);
            PDFTextStripperByArea  textStripper = new PDFTextStripperByArea ();

            for(int i = 0; i < rectangles.length;i++   ) {
                Rectangle rectangle =rectangles[i];
                String regionName = "regionName"+rectangle.getX()+rectangle.getY();
                textStripper.addRegion(regionName, rectangle);
                PDPage page = document.getPage(0);
                textStripper.extractRegions(page);
                // 获取区域的text
                String text = textStripper.getTextForRegion(regionName);
                text = text.replace("\u0000","-").replace(" ","");
                System.out.println(">>text"+text);
                textArr[i]=text;
            }

            textStripper.setSortByPosition(true);
            textStripper.setStartPage(1);
            textStripper.setEndPage(document.getNumberOfPages());

            textStripper.getText(document);

            document.close();
        }catch (IOException e) {
            e.printStackTrace();
        }

        return  textArr;
    }

    public  static List<Point> getPoint( File file){
        List<Point> pointList=new ArrayList<>();
        try {
        PDDocument document =  Loader.loadPDF(file);
        PDFTextStripper textStripper = new PDFTextStripper() {
            @Override
            protected void writeString(String text, List<TextPosition> textPositions) throws IOException {
                for(String target:target){
                    if (text.contains(target)) {
                        Point point = new Point();
                        TextPosition textPositionEnd = textPositions.get(textPositions.size() - 1);
                        point.setX((int) textPositionEnd.getEndX());
                        point.setY((int) textPositionEnd.getY());
                        pointList.add(point);
                    }
                }
            }
        };

        textStripper.setSortByPosition(true);
        textStripper.setStartPage(1);
        textStripper.setEndPage(document.getNumberOfPages());
        textStripper.getText(document);
        document.close();

        } catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println(">>>>>pointList" + JSON.toJSONString(pointList));
        return pointList;
    }
} 

7. 验证代码可行性

整理出来的excel,检查里面有些空格没有处理,就让业务自己批量替换一下。
因为代码只是一次性用的,就没有怎么进行封装了。总体来讲业务同事比较满意。文章来源地址https://www.toymoban.com/news/detail-641369.html

结论

  1. 第三方库pdfbox可以操作PDF文档。3.0版本之后和历史版本相差比较大,最好先阅读下源码。
  2. 坐标定位的话,可以用第三方也可以代码定位
  3. 如果代码后续想复用的话,最好抽离出公共方法
  4. 文件比较多的情况下,建议增加多线程处理。

到了这里,关于Java实战:高效提取PDF文件指定坐标的文本内容的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Python3,9行批量提取PDF文件的指定内容,这种操作,保证人见人爱....

    小屌丝 :鱼哥, 你有没有什么办法,提取PDF文档的内容。 小鱼 :这个还问我?? 小屌丝 :哎呀,这个不是被难住了嘛 。 小鱼 :有啥难得?提示你一下, 小屌丝 :嗯,可以可以。 小鱼 :去我的博文找,没记错的话,有两种方法提取pdf的文字。 小屌丝 :好嘞, 我这就去

    2024年02月04日
    浏览(25)
  • opencv C++ 读取视频中的光斑是否在移动(图片存储在指定文件见下,光斑坐标存在TXT文本中)

    读取视频中的光斑是否在移动(图片存储在指定文件见下,光斑坐标存在TXT文本中)

    2024年02月12日
    浏览(34)
  • Python从图像中提取文本及其坐标

    Python从图像中提取文本及其坐标 在数字化时代,文本数据已经成为人们生活和工作中重要的数据形式。有时候我们需要从图片中提取文字信息,这就要用到Python编程语言中OCR技术的应用了。本文将介绍如何使用Python从图片中提取文字,同时提供完整的源代码。 首先,我们需

    2024年02月14日
    浏览(19)
  • 第八篇【传奇开心果系列】Python自动化办公库技术点案例示例:深度解读使用Python库清洗处理从PDF文件提取的文本

    在使用pyPDF4或任何其他Python的PDF解析库提取PDF文件的文本后,进行清洗处理是非常重要的。这是因为PDF文件通常包含了各种格式化元素,如页眉、页脚、页码、图表、图片等,这些元素可能会干扰到你提取的文本内容。清洗处理的目标是去除这些干扰元素,仅提取出你真正需

    2024年03月22日
    浏览(35)
  • Python 提取PDF文本和图片

    从PDF中提取内容能帮助我们获取文件中的信息,以便进行进一步的分析和处理。此外,在遇到类似项目时,提取出来的文本或图片也能再次利用。要在Python中通过代码 提取PDF文件中的文本和图片 ,可以使用 Spire.PDF for Python 这个第三方库。具体操作方法查阅下文。 Python 提取

    2024年02月08日
    浏览(25)
  • Excel:通过Lookup函数提取指定文本关键词

    函数公式 :=LOOKUP(9^9,FIND($G 2 : 2: 2 : G 6 , C 2 ) , 6,C2), 6 , C 2 ) , G 2 : 2: 2 : G$6) 公式解释 : lookup第一参数为9^9:代表的是一个极大值的数据,查询位置里面最接近这一个值的数据; lookup第二参数用find函数代替,目的就是查询我们的在对应文本找那个的位置; lookup第三参数

    2024年02月11日
    浏览(33)
  • 用python提取PDF中各类文本内容的方法

    从PDF文档中提取信息,是很多类似RAG这样的应用第一步要处理的事情,这里需要做好三件事: 提取出来的文本要保持信息完整性,也就是准确性 提出的结果需要有附加信息,也就是要保存元数据 提取过程要完成自动化,也就是流程化 然而,在我们开始之前,我们需要指定目

    2024年02月01日
    浏览(18)
  • Java将获取的参数,图片以及pdf文件放入到word文档指定位置

    首先引入的依赖 接下面的是template.docx文档,参数是以{{paramName}}格式的,为什么要以这种格式,是因为下面的方法,在替换参数的时候需要 但是从数据库获取的参数跟模板中的参数一一对应上即可,格式如下(我是json形式展示的): {     \\\"countQuota\\\": \\\"1\\\",     \\\"noEmission\\\": \\\"1\\\",  

    2024年02月15日
    浏览(26)
  • 一步步指南:从指定时长中提取需求的帧图片,高效剪辑视频

    在现代多媒体时代,视频已经成生活中不可或缺的一部分。从视频中提取某一帧图片,或者对视频进行剪辑,都是常见的需求。下面一起来看云炫AI智剪如何从指定时长中提取需求的帧图片,如何高效地剪辑视频。 按指定时长提取视频某帧图片的缩略图。 批量提取视频图片的

    2024年01月22日
    浏览(28)
  • JAVA读取(DOC、DOCX、PDF、PPT、PPTX)文件文本内容及图片

    温馨提示:有很多方法均可以解析这些常见的文件,以下内容使用的是apache-poi + apache-pdfbox实现的。         关于文档解析,在网上搜索了很久,无奈内容太过繁杂,找不到合适的代码,一大半都是只支持文本。没办法,只能自己在网上一点一点CV了,最终提取了这些代码

    2024年02月03日
    浏览(27)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包