Вопрос или проблема
Я ищу аналог 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, особенно в плане обработки координат и работы с изображениями.
Каждый выбор имеет свои плюсы и минусы, и конечный выбор будет зависеть от конкретных требований вашего проекта, опыта команды и контекста применения.