Доброго всем дня. Недавно у меня появился электронный ридер — Kobo Touch, и настал вопрос о том, откуда брать книги. Небезызвестная Флибуста конечно хорошая вещь и многие книгу я беру оттуда, но все-таки тянуло меня к lib.ru Да и ради интереса хотелось написать конвертер. Ненавистникам копро-кода стоит подумать о том. чтобы читать этот текст. Ибо код действительно неимоверно жестокий.
Проанализировав каталог библиотеки сразу стало ясно, что большинство книг имеют одну и туже схему, а именно:
[Автор].[Названия]
[Тех данные]
[#Глава]
[Текст главы]
[#Глава]
[Текст главы]
Ну и так далее. Повстречал я и другие формы, но не стал усложнять. Стоит отметить, что [Автор][Название] и[#Глава] находятся между определенными тэгами — "" и ""( это разные знаки, формат Ascii ).
Дело осталось за малым, написать простой парсер для страницы. Я воспользовался Java. Для начала встал вопрос, в какой кодировке считывать данные, ибо по моим наблюдениям — на каждой странице кодировка варируется. Для этого прибег к сторонней библиотеке juniversalchardet Так я узнаю кодировку и записываю его в строку.
Далее читаю страницу с помощью BufferedReader.
Для удобного парсингазаменяю знак на и добавлю новый знак в конец файла.
В конце концов предстоит узнать сколько же всего глав в книге (как уже упомянуто, главы находятся между тэгами и ). Отнимаю также одну главу, ибо я сам добавил её.
Дело подходит к концу. Осталось разделить весь контент на главы, описания и автора с названием.
Конечно можно было вытащить всё это регулярками, но что первое пришло в голову, то и написал.
Теперь имя всё для создания документа я воспользовался библиотекой EPUBGen для создания конечного документа. Благо примеры весьма информативные и это заняло буквально пару минут. Для начала создаю документ и вписываю метаданные.
Далее необходимо сохранить изображение в каталог OPS/images и сделать на него линк в документе cover.xhtml
Последнее действие это добавление таблицы контента с последующим рекурсивным добавлением самого контента.
Конечный результат вышел таковой:

Интерфейс на Swing, зато дешево и сердито.
Так как больших усилий для понимания всей библиотеки я не предпринимал, работает лишь с книгами старой модели (простая текстовая модель), таких, как эта.
Кто не умер после прочтения такого обилия говно-кода, прошу на bitbucket Бинарник можно взять отсюда
Проанализировав каталог библиотеки сразу стало ясно, что большинство книг имеют одну и туже схему, а именно:
[Автор].[Названия]
[Тех данные]
[#Глава]
[Текст главы]
[#Глава]
[Текст главы]
Ну и так далее. Повстречал я и другие формы, но не стал усложнять. Стоит отметить, что [Автор][Название] и[#Глава] находятся между определенными тэгами — "" и ""( это разные знаки, формат Ascii ).
Дело осталось за малым, написать простой парсер для страницы. Я воспользовался Java. Для начала встал вопрос, в какой кодировке считывать данные, ибо по моим наблюдениям — на каждой странице кодировка варируется. Для этого прибег к сторонней библиотеке juniversalchardet Так я узнаю кодировку и записываю его в строку.
URLConnection con = url.openConnection(); con.connect(); InputStream urlfs; urlfs = con.getInputStream(); byte[] buf = new byte[4096]; UniversalDetector detector = new UniversalDetector(null); int nread; while ((nread = urlfs.read(buf)) > 0 && !detector.isDone()) { detector.handleData(buf, 0, nread); } detector.dataEnd(); String encoding = detector.getDetectedCharset(); detector.reset();
Далее читаю страницу с помощью BufferedReader.
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream(), encoding)); String str; while ((str = in.readLine()) != null) { string = string + str; } in.close();
Для удобного парсингазаменяю знак на и добавлю новый знак в конец файла.
string = string.replace("", ""); /* Т.к в конце страницы нету знаков, то я их доабавляю для легкого парсинга. */ string = string + " ";
В конце концов предстоит узнать сколько же всего глав в книге (как уже упомянуто, главы находятся между тэгами и ). Отнимаю также одну главу, ибо я сам добавил её.
int count = 0; for (char c : string.toCharArray()) if (c == '') count++; loop = (count-1);
Дело подходит к концу. Осталось разделить весь контент на главы, описания и автора с названием.
/* Третья ячейка масива содержит строку вида "Автор. Название". Разделяю её. */ String[] authorandtitle = parsedstring[2].split("\\."); AUTHOR = authorandtitle[0]; TITLE = authorandtitle[1]; /* Начинаю добавлять главы, т.к они на четном месте массива. И текст на нечетных. Вырвиглазно, согласен */ for(int i = 4; i <= loop; i++){ if((i % 2) ==0 ){ CHAPTER[i] = parsedstring[i]; HEADER[i] = parsedstring[i]; }else{ PARAG[i] = parsedstring[i]; } }
Теперь имя всё для создания документа я воспользовался библиотекой EPUBGen для создания конечного документа. Благо примеры весьма информативные и это заняло буквально пару минут. Для начала создаю документ и вписываю метаданные.
Publication epub = new Publication(); epub.addDCMetadata("title", TITLE); epub.addDCMetadata("creator", AUTHOR); epub.addDCMetadata("language", "ru-RU");
Далее необходимо сохранить изображение в каталог OPS/images и сделать на него линк в документе cover.xhtml
DataSource dataSource = new FileDataSource(new File(cover)); BitmapImageResource imageResource = epub.createBitmapImageResource( "OPS/images/cover.jpg", "image/jpeg", dataSource); DataSource coverdata = new StringDataSource("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<title>Cover</title>\n<style type=\"text/css\"> img { max-width: 100%; } </style>\n</head>\n<body>\n<div id=\"cover-image\">\n<img src=\"images/cover.jpg\" alt=\"Title\"/>\n</div>\n</body>\n</html>"); Resource coverres = epub.createResource("OPS/cover.xhtml", "xhtml", coverdata); epub.addToSpine(coverres);
Последнее действие это добавление таблицы контента с последующим рекурсивным добавлением самого контента.
NCXResource toc = epub.getTOC(); TOCEntry rootTOCEntry = toc.getRootTOCEntry(); for(int i = 4; i <= loop; i++){ if((i % 2) ==0 ){ /* Создаю главу.*/ OPSResource main = epub.createOPSResource("OPS/"+i+".html"); epub.addToSpine(main); /* Открываю файл глав. */ mainDoc = main.getDocument(); /* Добавляю главу в таблицу контента.*/ TOCEntry mainTOCEntry = toc.createTOCEntry(CHAPTER[i], mainDoc .getRootXRef()); rootTOCEntry.add(mainTOCEntry); body = mainDoc.getBody(); /* Добавляю тайтл. */ Element h1 = mainDoc.createElement("h1"); h1.add(HEADER[i]); body.add(h1); }else{ /* Добавляю основной текст. */ Element paragraph = mainDoc.createElement("p"); paragraph.add(PARAG[i]); body.add(paragraph); } }
Сохраняю конечный документ OCFContainerWriter writer = new OCFContainerWriter( new FileOutputStream(output)); epub.serialize(writer);
Конечный результат вышел таковой:

Интерфейс на Swing, зато дешево и сердито.
Так как больших усилий для понимания всей библиотеки я не предпринимал, работает лишь с книгами старой модели (простая текстовая модель), таких, как эта.
Кто не умер после прочтения такого обилия говно-кода, прошу на bitbucket Бинарник можно взять отсюда