Парсим сайт для получения УДК иерархии

23e64e7c1d631f4b819da41028d15372

Последнее редактирование — 12 марта 2025 года.

Предыстория:

У меня на домашнем ПК скопилось некоторое количество книг в электронном формате. Это в основной массе техническая литература. И мне хотелось всё это систематизировать. Придумывать не хочется, когда в книгах есть УДК, ББК классификаторы. Мне данная классификация в УДК очень даже подходит. А найти программу которая:

  1. получит структуру УДК в виде иерархии

  2. просканирует файлы pdf, и получит УДК коды

  3. создаст по УДК кодам папки

  4. переместит файлы в нужные папки

Этого всего я не нашел. Это лишь самое простое и базовое, что хотелось видеть. А еще хочется поиграться с названиями папок. Например после создания УДК структуры в каждой папке, создавать папку по расширению файла. Например PDF, DJVU. Или добавлять папку с годом книги и туда класть файлы. В общем вариантов много. И решил, что я буду писать небольшие консольные утилиты, которые сделают все это за меня.

Почему не все сразу? Все просто, вопрос во времени. Его как всегда нет, семья, работа, дети. А небольшие утилиты я могу попросить сгенерировать нейросеть, и быстенько проверить, что мне подходит.

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

Готовых таблиц я не нашел. Вероятно это связанно с авторскими правами. Поэтому будем получать таблицу сами.

Для частного использования полные таблицы не нужны. Мне нужны категории по IT, часть по разделам математики ну и пару разделов по философии и психологи.

Создаем maven проект

mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-simple -DarchetypeVersion=1.5

Вам будет предложено ввести groupId, artifactId, version, package

Define value for property 'groupId': ru.mcs.udk
Define value for property 'artifactId': udk-site-parser
Define value for property 'version' 1.0-SNAPSHOT: 1
Define value for property 'package' ru.mcs.udk: ru.mcs.udk
Confirm properties configuration:
groupId: ru.mcs.udk
artifactId: udk-site-parser
version: 1
package: jar
 Y: Y

Будет создан проект, который вы уже можете менять.

Добавляем зависимости pom.xml

Для получения данных с сайта я буду использовать jsoup.


    org.jsoup
    jsoup
    1.15.3

Все лишнее можно удалить. У меня получилось так:



    4.0.0

    ru.mcs.udk
    udk-site-parser
    1.0
    jar

    
        21
        21
        UTF-8
        udk-site-parser
    

    
        
            org.jsoup
            jsoup
            1.15.3
        
    

    
        
            
                maven-assembly-plugin
                3.7.1
                
                    
                        jar-with-dependencies
                    
                    ${project.basedir}/jar
                    ${jar.finalName}
                    
                        
                            true
                            ru.mcs.udk.UdkSiteParser
                        
                    
                
                
                    
                        assemble-all
                        package
                        
                            single
                        
                    
                
            
        
    

Плагин maven-assembly-plugin добавлен чтобы сгенерироть jar файл с jsoup в одной jar-ке.

Пишем код парсера

package ru.mcs.udk;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.charset.StandardCharsets;

public class UdkSiteParser {

    public static final String HTTPS_WWW_TEACODE_COM_ONLINE_UDC = "https://www.teacode.com/online/udc";

    public static void main(String[] args) throws IOException {
        System.setOut(new PrintStream(new FileOutputStream("udk.txt"), true, StandardCharsets.UTF_8));

        getHierarchy(HTTPS_WWW_TEACODE_COM_ONLINE_UDC, 0, 15);
    }

    public static void getHierarchy(String url, int level, int stopLevel) {
        try {
            var document = Jsoup.connect(url)
                    .timeout(5000)
                    .followRedirects(true)
                    .userAgent("Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/25.0")
                    .execute().parse();

            Elements rows = document.select("table tr[bgcolor=#eaeaea]");

            // тут создаем новую переменную которую будем передавать в метод
            int nextLevel = level + 1;
            for (Element row : rows) {
                Elements udkNumber = row.select("td:eq(0)");
                Elements udkTitle = row.select("td:eq(1)[align=left]");
                System.out.printf("%s%s\t%s%n", "\t".repeat(Math.max(0, level)), udkNumber.text(), udkTitle.text());

                String pageUrl = udkNumber.select("a").attr("href");
                if (!pageUrl.isEmpty() && level < stopLevel - 1) {
                    String subUrl = getUrl(url, pageUrl);

                    getHierarchy(subUrl, nextLevel, stopLevel);
                }
            }
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
    }

    private static String getUrl(String url, String subUrl) {
        if (subUrl.startsWith(".")) {
            return String.format("%s%s", HTTPS_WWW_TEACODE_COM_ONLINE_UDC, subUrl.replaceFirst(".", ""));
        } else {
            return String.format("%s%s", url.replaceAll("/[^/]+\\.html$", "/"), subUrl);
        }
    }
}

В строчке 17 мы переопределяем стандартный вывод в консоль на нужный нам файл.

Строчки 24–28 это получение странички. Таймаут 5 секунд. Можно увеличить если будут ошибки с таймаутами.

Строчка 30 это получение интересующих нас элементов в таблице. Определяется опытным путем.

Строчки 34–45 это сама логика получения уже нужных данных.

Метод getUrl используется для получения пути на подстраницу. Определяется опытным путем. Есть разница в путях на первой странице, поэтому такие условия.

Добавил параметр stopLevel, для того чтобы не получать всю иерархию. А только до определенного уровня. Это больше для тестирования. Выставил в 15 так как там, по моему, больше 10 уровня и нет.

Результат для 2 уровня вложенности получим примерно такой:

00	Наука в целом (информационные технологии - 004)
	001	Наука в целом. Науковедение. Организация умственного труда
	002	Печать в целом. Документация. Научно-техническая информация (НТИ)
	003	Системы письма и письменности. Знаки и символы. Семиотика в целом. Коды. Графическое представление мысли
	004	Информационные технологии. Компьютерные технологии. Теория вычислительных машин и систем
	005	Изучение проблемы организации: методология, анализ, синтез, классификация и таксономия (теория, основы), систематизация в целом
	006	Стандартизация и стандарты
	007	Деятельность и организация. Общая теория информации, связи и управления (кибернетика), включая деятельность человека
	008	Цивилизация. Культура. Прогресс
	009	Гуманитарные науки в целом
1	Философия. Психология
	101	Сущность и задачи философии
	11	Метафизика
	122	Причинность (каузальность). Первопричинность. Принципы. Causa efficiens. Условие. Действие. Побуждение
	...........
	
9	География. Биография. История
	902	Архелогия
	903	Предыстория. Доисторические остатки, орудия труда, древности. Интерпретация и синтез материальных остатков древнего человека, его культур и цивилизаций
	904	Археологические памятники исторических времен. Древности античного, средневекового и нового времени
	908	Краеведение
	91	География. Географические исследования Земли и отдельных стран. Путешествия. Региональная география
	929	Биографические и подобные исследования
	93	История. Теоретические вопросы
	94	Всеобщая история

Программа будет выполняться примерно пол часа. Можно открыть файл udk.txt и посмотреть заполняемость файла.

Собираем проект

mvn clean package

Запускаем проект

java -jar .\jar\udk-site-parser-jar-with-dependencies.jar

На этом все. Можно приступать к следующим шагам. Можно теперь парсить pdf и получать УДК. Создавать папки. При создании папок будут конечно проблемы, нужно будет убирать специальные символы. Но это уже другая история и в другой программе.

Код доступен тут: udk-site-parser

© Habrahabr.ru