JavaScript или Java. Как извлечь текст и координаты текста из PDF-файла?

Вопрос или проблема

Я ищу аналог pdfminer для js или java. Мне нужно разобрать pdf-файл в текст и получить координаты каждого предложения (x, y, ширина, высота). Было бы неплохо, если бы это могло работать не только с текстом, но и с изображениями.

Лучшее, что я смог найти, это pdf2json, но он дает координаты странным образом, неясно, как с ними работать.

Библиотека PDF4Java может извлекать необходимую информацию из pdf-файла.
Пример кода ниже показывает, как извлечь позиции текстовых строк, глифов и изображений.

import com.o2sol.pdf4java.PDFFixedDocument;
import com.o2sol.pdf4java.content.PDFContentExtractor;
import com.o2sol.pdf4java.content.images.PDFVisualImage;
import com.o2sol.pdf4java.content.images.PDFVisualImageCollection;
import com.o2sol.pdf4java.content.text.PDFTextRun;
import com.o2sol.pdf4java.content.text.PDFTextRunCollection;
import com.o2sol.pdf4java.core.exceptions.PDFException;
import com.o2sol.pdf4java.graphics.*;
import com.o2sol.pdf4java.graphics.colors.PDFRgbColor;
import com.o2sol.pdf4java.graphics.fonts.*;

import java.util.Random;

public class ContentExtraction {
    public static void main(String[] args) {
        try {
            // Загрузить входной файл.
            PDFFixedDocument document = new PDFFixedDocument("..\\..\\SupportFiles\\content.pdf");

            extractTextAndHighlight(document);

            extractTextAndHighlightGlyphs(document);

            extractImagesAndHighlight(document);

            // Сжать графическое содержимое страницы.
            for (int i = 0; i < document.getPages().size(); i++)
            {
                document.getPage(i).getCanvas().compressAndClose();
            }

            document.save("ContentExtraction.pdf");

            System.out.println("PDF документ успешно сохранен");
        }
        catch (PDFException ex) {
            System.out.println("Ошибка при создании PDF файла");
            System.out.println(ex.getMessage());
        }
    }

    private static void extractTextAndHighlight(PDFFixedDocument document) {
        PDFRgbColor penColor = new PDFRgbColor();
        PDFPen pen = new PDFPen(penColor, 0.5);
        Random rnd = new Random();

        PDFContentExtractor ce = new PDFContentExtractor(document.getPage(0));
        PDFTextRunCollection trc = ce.extractTextRuns();
        for (int i = 0; i < trc.size(); i++) {
            penColor.setR(rnd.nextInt(256));
            penColor.setG(rnd.nextInt(256));
            penColor.setB(rnd.nextInt(256));

            PDFPath boundingPath = new PDFPath();
            PDFPoint[] textRunCorners = trc.get(i).getCorners();
            boundingPath.startSubpath(textRunCorners[0].getX(), textRunCorners[0].getY());
            boundingPath.addLineTo(textRunCorners[1].getX(), textRunCorners[1].getY());
            boundingPath.addLineTo(textRunCorners[2].getX(), textRunCorners[2].getY());
            boundingPath.addLineTo(textRunCorners[3].getX(), textRunCorners[3].getY());
            boundingPath.closeSubpath();

            document.getPage(0).getCanvas().drawPath(pen, boundingPath);
        }
    }

    private static void extractTextAndHighlightGlyphs(PDFFixedDocument document) {
        PDFRgbColor penColor = new PDFRgbColor();
        PDFPen pen = new PDFPen(penColor, 0.5);
        Random rnd = new Random();

        PDFContentExtractor ce = new PDFContentExtractor(document.getPage(1));
        PDFTextRunCollection trc = ce.extractTextRuns();
        PDFTextRun tr = trc.get(1);
        for (int i = 0; i < tr.getGlyphs().size(); i++) {
            penColor.setR(rnd.nextInt(256));
            penColor.setG(rnd.nextInt(256));
            penColor.setB(rnd.nextInt(256));

            PDFPath boundingPath = new PDFPath();
            PDFPoint[] glyphCorners = tr.getGlyph(i).getGlyphCorners();
            boundingPath.startSubpath(glyphCorners[0].getX(), glyphCorners[0].getY());
            boundingPath.addLineTo(glyphCorners[1].getX(), glyphCorners[1].getY());
            boundingPath.addLineTo(glyphCorners[2].getX(), glyphCorners[2].getY());
            boundingPath.addLineTo(glyphCorners[3].getX(), glyphCorners[3].getY());
            boundingPath.closeSubpath();

            document.getPage(1).getCanvas().drawPath(pen, boundingPath);
        }
    }

    private static void extractImagesAndHighlight(PDFFixedDocument document) {
        PDFPen pen = new PDFPen(new PDFRgbColor(255, 0, 192), 0.5);
        PDFBrush brush = new PDFBrush(new PDFRgbColor(0, 0, 0));
        PDFStandardFont helvetica = new PDFStandardFont(PDFStandardFontFace.HELVETICA, 8);
        PDFStringAppearanceOptions sao = new PDFStringAppearanceOptions();
        sao.setBrush(brush);
        sao.setFont(helvetica);
        PDFStringLayoutOptions slo = new PDFStringLayoutOptions();
        slo.setWidth(1000);

        PDFContentExtractor ce = new PDFContentExtractor(document.getPage(2));
        PDFVisualImageCollection vic = ce.extractImages(false);
        for (int i = 0; i < vic.size(); i++) {
            PDFVisualImage vi = vic.get(i);

            PDFPoint[] imageCorners = vi.getImageCorners();
            PDFPath boundingPath = new PDFPath();
            boundingPath.startSubpath(imageCorners[0].getX(), imageCorners[0].getY());
            boundingPath.addLineTo(imageCorners[1].getX(), imageCorners[1].getY());
            boundingPath.addLineTo(imageCorners[2].getX(), imageCorners[2].getY());
            boundingPath.addLineTo(imageCorners[3].getX(), imageCorners[3].getY());
            boundingPath.closeSubpath();

            document.getPage(2).getCanvas().drawPath(pen, boundingPath);

            slo.setX(imageCorners[3].getX() + 1);
            slo.setY(imageCorners[3].getY() + 1);
            String imageProperties = String.format("ID изображения: %s\nШирина в пикселях: %d пикселей\nВысота в пикселях: %d пикселей\n" +
                            "Ширина отображения: %f пунктов\nВысота отображения: %f пунктов\nГоризонтальное разрешение: %f dpi\nВертикальное разрешение: %f dpi",
                    vi.getImageID(), vi.getWidth(), vi.getHeight(), vi.getDisplayWidth(), vi.getDisplayHeight(), vi.getDpiX(), vi.getDpiY());
            document.getPage(2).getCanvas().drawString(imageProperties, sao, slo);
        }
    }
}

Это вывод метода extractTextAndHighlight:
извлечение текстовых строк и выделение

Это вывод метода extractTextAndHighlightGlyphs:
извлечение текста и выделение глифов

Это вывод метода extractImagesAndHighlight:
извлечение изображений и выделение

Класс PDFContentExtractor также поддерживает извлечение текста страницы в виде строки, извлечение слов или извлечение строк текста.
Примечание по извлечению текстовых строк: текстовая строка представляет собой вывод оператора showText PDF. В этом конкретном тестовом PDF-файле текстовая строка соответствует строке текста (поэтому текст выделяется построчно), но текстовая строка может быть буквой, словом, частичным словом, фразой или частичной фразой (это зависит от библиотеки, которая сгенерировала PDF-файл).

Отказ от ответственности: я работаю в компании, разрабатывающей библиотеку PDF4Java.

Ответ или решение

JavaScript или Java: Как извлечь текст и координаты текста из PDF файла?

Когда речь идет о парсинге PDF-файлов, выбор между Java и JavaScript может зависеть от контекста использования, требуемых библиотек и специфики проекта. В данной статье мы рассмотрим, как извлекать текст и координаты текста из PDF-файлов, используя подходящие библиотеки на обеих платформах.

Java: Использование библиотеки PDF4Java

PDF4Java — это мощная библиотека для работы с PDF-документами на языке Java. Она позволяет извлекать текст, получать координаты текста и работать с изображениями. Рассмотрим пример кода, который демонстрирует, как можно извлечь текст и его координаты, а также изображения из PDF-файла.

import com.o2sol.pdf4java.PDFFixedDocument;
import com.o2sol.pdf4java.content.PDFContentExtractor;
import com.o2sol.pdf4java.content.images.PDFVisualImage;
import com.o2sol.pdf4java.content.images.PDFVisualImageCollection;
import com.o2sol.pdf4java.content.text.PDFTextRun;
import com.o2sol.pdf4java.content.text.PDFTextRunCollection;
import com.o2sol.pdf4java.core.exceptions.PDFException;
import com.o2sol.pdf4java.graphics.PDFPath;
import com.o2sol.pdf4java.graphics.PDFPoint;
import com.o2sol.pdf4java.graphics.colors.PDFRgbColor;
import com.o2sol.pdf4java.graphics.PDFPen;

import java.util.Random;

public class ContentExtraction {
    public static void main(String[] args) {
        try {
            PDFFixedDocument document = new PDFFixedDocument("path/to/your/file.pdf");

            extractTextAndHighlight(document);
            extractImagesAndHighlight(document);

            System.out.println("PDF документ успешно создан");
        } catch (PDFException ex) {
            System.out.println("Ошибка при создании PDF файла");
            System.out.println(ex.getMessage());
        }
    }

    private static void extractTextAndHighlight(PDFFixedDocument document) {
        PDFContentExtractor extractor = new PDFContentExtractor(document.getPage(0));
        PDFTextRunCollection textRuns = extractor.extractTextRuns();

        for (PDFTextRun textRun : textRuns) {
            PDFPoint[] corners = textRun.getCorners();
            highlightText(document, corners);
        }
    }

    private static void highlightText(PDFFixedDocument document, PDFPoint[] corners) {
        PDFRgbColor color = new PDFRgbColor(0, 0, 255); // Синий цвет для подсветки
        PDFPen pen = new PDFPen(color, 0.5);
        PDFPath path = new PDFPath();

        path.startSubpath(corners[0].getX(), corners[0].getY());
        path.addLineTo(corners[1].getX(), corners[1].getY());
        path.addLineTo(corners[2].getX(), corners[2].getY());
        path.addLineTo(corners[3].getX(), corners[3].getY());
        path.closeSubpath();

        document.getPage(0).getCanvas().drawPath(pen, path);
    }

    private static void extractImagesAndHighlight(PDFFixedDocument document) {
        PDFContentExtractor extractor = new PDFContentExtractor(document.getPage(1));
        PDFVisualImageCollection images = extractor.extractImages(false);

        for (PDFVisualImage image : images) {
            PDFPoint[] imageCorners = image.getImageCorners();
            highlightImage(document, imageCorners);
        }
    }

    private static void highlightImage(PDFFixedDocument document, PDFPoint[] corners) {
        // Логика подсветки изображения аналогична тексту
        PDFRgbColor color = new PDFRgbColor(255, 0, 0); // Красный цвет для подсветки
        PDFPen pen = new PDFPen(color, 0.5);
        PDFPath path = new PDFPath();

        path.startSubpath(corners[0].getX(), corners[0].getY());
        path.addLineTo(corners[1].getX(), corners[1].getY());
        path.addLineTo(corners[2].getX(), corners[2].getY());
        path.addLineTo(corners[3].getX(), corners[3].getY());
        path.closeSubpath();

        document.getPage(1).getCanvas().drawPath(pen, path);
    }
}

JavaScript: Аналоги для работы с PDF

Для работы с PDF в JavaScript подходит библиотека pdf-lib или PDF.js. Однако они не всегда позволяют извлекать координаты текста так же удобно, как это делает PDF4Java. Например, с использованием PDF.js можно извлечь текст, но доступ к координатам будет более сложным и требует дополнительной логики.

const { PDFDocument } = require('pdf-lib');
const fs = require('fs');

(async () => {
    const existingPdfBytes = fs.readFileSync('path/to/your/file.pdf');
    const pdfDoc = await PDFDocument.load(existingPdfBytes);

    const pages = pdfDoc.getPages();
    for (const page of pages) {
        const textContent = await page.getTextContent();
        console.log(textContent);
        // Здесь вы должны реализовать логику для получения координат текста
    }
})();

Сравнительная таблица: Java против JavaScript

Параметр Java JavaScript
Библиотеки PDF4Java pdf-lib, PDF.js
Извлечение текста Удобно и объемно Совершенно возможно
Извлечение координат Легко осуществимо Необходимо реализовать логику
Работа с изображениями Редактирование доступно Ограниченные возможности
Производительность Высокая Зависит от среды выполнения

Заключение

Оба языка могут быть использованы для извлечения текста и координат из PDF-файлов, но для более сложных задач Java с библиотекой PDF4Java предоставляет больше возможностей и легкость в использовании. JavaScript может быть хорошим выбором для веб-приложений, но его возможности ограничены по сравнению с Java, особенно в плане обработки координат и работы с изображениями.

Каждый выбор имеет свои плюсы и минусы, и конечный выбор будет зависеть от конкретных требований вашего проекта, опыта команды и контекста применения.

Оцените материал
Добавить комментарий

Капча загружается...