Доброго всем дня. Недавно у меня появился электронный ридер — 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 Бинарник можно взять отсюда