是派小星呀 2024-04-25 10:20 采纳率: 65.1%
浏览 13
已结题

java如何提取出pdf里的文字?

我现在想使用java来实现提取PDF内的文字,
目前使用了apache的pdfbox,但是很多文件都识别不出来,比如一些拍照后的扫描件,
然后还试过将pdf每一页转换成图片,然后使用tess4j的Tesseract来识别图片,这个又太慢,太占资源了,
现在有没有比较好的方案?

  • 写回答

20条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-04-25 10:20
    关注

    引自免费微信小程序:皆我百晓生

    在Java中提取PDF中的文字,您可以尝试以下几种方法来优化现有方案或采用新的技术路径。为确保高效、准确地处理各类PDF文档(包括扫描件),我会为您提供详尽的步骤、代码示例以及可能遇到的问题及解决策略。

    1. 优化Apache PDFBox使用

      • 更新版本:确保您使用的是最新版的Apache PDFBox库(当前最新版本为2.0.27),因为新版本通常包含对复杂PDF解析和图像识别的改进。

      • 配置参数:针对扫描件,调整PDFTextStripper的参数设置,例如启用分栏检测(setShouldSeparateByBeads(true))和字间距检测(setAverageCharTolerance(1.0f)),以适应不规则布局和低质量文本。

      • 处理图像内容:对于含有图像文字的PDF,PDFBox本身并不直接支持OCR。您可以结合第三方OCR服务或库(如Google Cloud Vision API、Tesseract等)对PDF中的图像进行单独识别。以下是一个简单的示例:

        import org.apache.pdfbox.pdmodel.PDDocument;
        import org.apache.pdfbox.text.PDFTextStripper;
        
        public class PdfTextExtractor {
            public static void main(String[] args) throws Exception {
                PDDocument document = PDDocument.load(new File("path_to_your_pdf"));
                PDFTextStripper pdfStripper = new PDFTextStripper();
                pdfStripper.setShouldSeparateByBeads(true);
                pdfStripper.setAverageCharTolerance(1.0f);
        
                String text = pdfStripper.getText(document);
                System.out.println(text);
        
                document.close();
            }
        }
        
    2. 使用OCR4J替代Tesseract

      • OCR4J是一个基于Java的OCR框架,集成了多种OCR引擎(包括Tesseract),并提供了更高级的图像预处理和后处理功能。相较于直接使用Tesseract,OCR4J可以更高效地处理PDF中的图像,并减少资源消耗。

        安装与依赖

        <dependencies>
            <dependency>
                <groupId>com.github.jai-imageio</groupId>
                <artifactId>jai-imageio-core</artifactId>
                <version>1.4.0</version>
            </dependency>
            <dependency>
                <groupId>org.ocr4j</groupId>
                <artifactId>ocr4j</artifactId>
                <version>1.5.6</version>
            </dependency>
            <dependency>
                <groupId>net.sourceforge.tess4j</groupId>
                <artifactId>tess4j</artifactId>
                <version>5.3.2</version>
            </dependency>
        </dependencies>
        
      • 使用OCR4J提取PDF文字

        import com.github.ocr4j.Ocr4jRunner;
        import com.github.ocr4j.config.ConfigurableOcrEngine;
        import com.github.ocr4j.config.OCRConfiguration;
        import com.github.ocr4j.config.provider.properties.PropertiesOCRConfigurationProvider;
        import com.github.ocr4j.model.TextBlock;
        import com.github.ocr4j.model.TextLine;
        import com.github.ocr4j.model.Word;
        import com.github.ocr4j.output.JSONOutputConverter;
        import com.github.ocr4j.preprocess.ResizePreprocessor;
        import net.sourceforge.tess4j.util.ImageIOHelper;
        
        public class Ocr4jPdfExtractor {
            public static void main(String[] args) throws Exception {
                // Load OCR configuration from properties file (e.g., tessdata/configs/tesseract-ocr4j.properties)
                PropertiesOCRConfigurationProvider provider = new PropertiesOCRConfigurationProvider("path/to/ocr-config.properties");
                OCRConfiguration ocrConfig = provider.getOCRConfiguration();
        
                // Configure OCR engine with Tesseract and enable image resizing for better performance
                ConfigurableOcrEngine ocrEngine = new ConfigurableOcrEngine(ocrConfig);
                ocrEngine.addPreprocessor(new ResizePreprocessor(1024, 800));
        
                // Extract text from PDF
                Ocr4jRunner runner = new Ocr4jRunner(ocrEngine);
                String jsonOutput = runner.run("path_to_your_pdf", JSONOutputConverter.class);
        
                // Parse JSON output and retrieve recognized text
                JSONObject jsonObject = new JSONObject(jsonOutput);
                JSONArray pages = jsonObject.getJSONArray("pages");
                for (int i = 0; i < pages.length(); i++) {
                    JSONArray blocks = pages.getJSONObject(i).getJSONArray("blocks");
                    for (int j = 0; j < blocks.length(); j++) {
                        TextBlock block = new TextBlock(blocks.getJSONObject(j));
                        for (TextLine line : block.getTextLines()) {
                            for (Word word : line.getWords()) {
                                System.out.print(word.getText());
                            }
                            System.out.println();
                        }
                    }
                }
            }
        }
        
    3. 利用云服务进行OCR

      • 如果本地处理性能不足或希望减轻服务器负担,可以考虑使用云服务进行OCR,如Google Cloud Vision API、Amazon Textract、Microsoft Azure Computer Vision等。这些服务提供REST API接口,您可以轻松集成到Java应用程序中。以下是使用Google Cloud Vision API的一个简单示例:

        添加依赖

        <dependencies>
            <dependency>
                <groupId>com.google.cloud</groupId>
                <artifactId>google-cloud-vision</artifactId>
                <version>2.9.½</version>
            </dependency>
        </dependencies>
        

        使用Google Cloud Vision API

        import com.google.auth.oauth2.GoogleCredentials;
        import com.google.cloud.vision.v1.AnnotateFileRequest;
        import com.google.cloud.vision.v1.AnnotateFileResponse;
        import com.google.cloud.vision.v1.Document;
        import com.google.cloud.vision.v1.Feature;
        import com.google.cloud.vision.v1.Feature.Type;
        import com.google.cloud.vision.v1.ImageAnnotatorClient;
        import com.google.cloud.vision.v1.Page;
        import com.google.cloud.vision.v1.TextAnnotation;
        import com.google.common.collect.Lists;
        
        public class GoogleCloudVisionPdfExtractor {
            public static void main(String[] args) throws Exception {
                // Load Google Cloud credentials from JSON file
                GoogleCredentials credentials = GoogleCredentials.fromStream(new FileInputStream("path/to/credentials.json"))
                        .createScoped(Lists.newArrayList("https://www.googleapis.com/auth/cloud-platform"));
        
                try (ImageAnnotatorClient client = ImageAnnotatorClient.create(credentials)) {
                    // Prepare request to extract text from PDF
                    Document document = Document.newBuilder().setContent(ByteString.readFrom(new FileInputStream("path_to_your_pdf"))).setType(Document.Type.PDF).build();
                    Feature feature = Feature.newBuilder().setType(Type.DOCUMENT_TEXT_DETECTION).build();
                    AnnotateFileRequest request = AnnotateFileRequest.newBuilder().addFeatures(feature).setInputDocument(document).build();
        
                    // Send request and receive response
                    AnnotateFileResponse response = client.annotateFile(request);
        
                    // Extract recognized text from response
                    List<TextAnnotation> annotations = response.getResponsesList().stream()
                            .map(AnnotateImageResponse::getTextAnnotations)
                            .flatMap(Collection::stream)
                            .collect(Collectors.toList());
        
                    for (TextAnnotation annotation : annotations) {
                        for (Page page : annotation.getPagesList()) {
                            System.out.println(page.getBlocksList().stream()
                                    .flatMap(block -> block.getParagraphsList().stream())
                                    .flatMap(paragraph -> paragraph.getWordsList().stream())
                                    .flatMap(word -> word.getSymbolsList().stream())
                                    .map(symbol -> symbol.getText())
                                    .collect(Collectors.joining()));
                        }
                    }
                }
            }
        }
        

    总结起来,优化Apache PDFBox配置、使用OCR4J替代Tesseract、或利用云服务(如Google Cloud Vision API)进行OCR,都是提高Java环境下PDF文字提取效果和效率的有效途径。根据您的项目需求、资源条件和对准确度、速度的权衡,选择最适合您的方案。提供的代码示例仅供参考,实际使用时请根据具体情况进行调整。

    评论 编辑记录

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 4月27日
  • 创建了问题 4月25日

悬赏问题

  • ¥15 如何用Labview在myRIO上做LCD显示?(语言-开发语言)
  • ¥15 Vue3地图和异步函数使用
  • ¥15 C++ yoloV5改写遇到的问题
  • ¥20 win11修改中文用户名路径
  • ¥15 win2012磁盘空间不足,c盘正常,d盘无法写入
  • ¥15 用土力学知识进行土坡稳定性分析与挡土墙设计
  • ¥70 PlayWright在Java上连接CDP关联本地Chrome启动失败,貌似是Windows端口转发问题
  • ¥15 帮我写一个c++工程
  • ¥30 Eclipse官网打不开,官网首页进不去,显示无法访问此页面,求解决方法
  • ¥15 关于smbclient 库的使用