Newer
Older
udk-pdf-scanner / src / main / java / ru / mcs / udk / PdfScanner.java
package ru.mcs.udk;

import net.sourceforge.tess4j.TesseractException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.apache.pdfbox.text.PDFTextStripper;

import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class PdfScanner {
    public static void main(String[] args) throws FileNotFoundException {
        if (args.length == 0) {
            System.out.println("Пожалуйста, укажите путь к папке.");
            return;
        }

        String directoryPath = args[0];
        Path startDir = Paths.get(directoryPath);

        if (!Files.exists(startDir) || !Files.isDirectory(startDir)) {
            System.out.println("Указанный путь не существует или не является папкой.");
            return;
        }

        System.setOut(new PrintStream(new FileOutputStream("book-list.csv"), true, StandardCharsets.UTF_8));
        try {
            Files.walkFileTree(startDir, new SimpleFileVisitor<>() {
                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
                    if (file.toAbsolutePath().toString().matches(".*\\.pdf$")) {
                        // Выводим путь и имя файла
                        getUdk(file.toAbsolutePath());
                    }
                    return FileVisitResult.CONTINUE;
                }

                @Override
                public FileVisitResult visitFileFailed(Path file, IOException exc) {
                    // Обрабатываем ошибки доступа к файлам
                    System.err.println("Ошибка доступа к файлу: " + file.toAbsolutePath() + " - " + exc.getMessage());
                    return FileVisitResult.CONTINUE;
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void getUdk(Path filePath) {
        File file = filePath.toFile();
        String languageBook = "";
        try (PDDocument document = PDDocument.load(file)) {
            PDFTextStripper stripper = new PDFTextStripper();
            // Устанавливаем диапазон страниц для анализа (первые три страницы)
            stripper.setStartPage(1);
            stripper.setEndPage(Math.min(3, document.getNumberOfPages()));
            String text = stripper.getText(document);
            String udk = findUDK(text);

            languageBook = isCyrillic(String.valueOf(filePath.getFileName())) ? "ru" : "en";

            if ((udk == null || udk.isBlank()) && languageBook.equals("ru")) {
                udk = getUdkByImage(document);
            }

            System.out.printf("%s;%s;%s;%s\n", filePath.toAbsolutePath(), Objects.requireNonNullElse(udk, ""), languageBook, "");
        } catch (IOException e) {
            System.out.printf("%s;%s;%s;%s\n", filePath.toAbsolutePath(), Objects.requireNonNullElse("", ""), languageBook, e.getMessage());
        } catch (TesseractException e) {
            e.printStackTrace();
        }
    }

    private static String getUdkByImage(PDDocument document) throws IOException, TesseractException {
        PDFRenderer renderer = new PDFRenderer(document);

        for (int pageIndex = 0; pageIndex < 5; pageIndex++) {
            BufferedImage image = renderer.renderImageWithDPI(pageIndex, 300);
            String text = OCRUtils.getText(image);
            String udk = findUDK(text);
            if (udk != null) {
                return udk;
            }
        }
        return "";
    }

    public static String findUDK(String text) {
        // Регулярное выражение для поиска УДК
        Pattern pattern = Pattern.compile("[Уу]\\s*[Дд]\\s*[Кк]\\s*([0-9.]+)");
        Matcher matcher = pattern.matcher(text);

        if (matcher.find()) {
            return matcher.group(1);
        }
        return null;
    }

    public static boolean isCyrillic(String fileName) {
        String regex = ".*[\\p{IsCyrillic}]{3,}.*";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(fileName);
        return matcher.matches();
    }
}