Парсим сайт для получения УДК иерархии
Последнее редактирование — 12 марта 2025 года.
Предыстория:
У меня на домашнем ПК скопилось некоторое количество книг в электронном формате. Это в основной массе техническая литература. И мне хотелось всё это систематизировать. Придумывать не хочется, когда в книгах есть УДК, ББК классификаторы. Мне данная классификация в УДК очень даже подходит. А найти программу которая:
получит структуру УДК в виде иерархии
просканирует файлы pdf, и получит УДК коды
создаст по УДК кодам папки
переместит файлы в нужные папки
Этого всего я не нашел. Это лишь самое простое и базовое, что хотелось видеть. А еще хочется поиграться с названиями папок. Например после создания УДК структуры в каждой папке, создавать папку по расширению файла. Например 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