pdf2epub
Конвертация PDF, собранного из электронной книги (Producer: calibre), в EPUB/AZW3 для Kindle с сохранением форматирования: курсив, полужирный, заголовки глав, врезки, иллюстрации, склейка абзацев через границы страниц.
Зачем не ebook-convert напрямую
Прямая конвертация ebook-convert book.pdf book.epub теряет курсив: poppler
определяет начертание по имени шрифта и не опознаёт сокращённые имена вроде
MinionPro-It (без подстроки Italic). На «The Unicorn Project» получилось
435 курсивных фрагментов в PDF против 1 тега <i> в EPUB. Плюс calibre
размечает основной текст как <h2> (2817 штук), потому что определяет заголовки
по кеглю относительно самого частого.
pdf2html.py извлекает текст через PyMuPDF, где начертание берётся из
свойств span'а, и сам раскладывает блоки по семантике.
Что делает скрипт
- курсив/полужирный — по имени шрифта span'а (
-It,Italic,Bold,Semibold); - заголовки — по кеглю:
>= 28или декоративный шрифт —h1.title,>= 24—h1(главы и части),>= 17—h2(подзаголовок с датой); - врезки (дневник, чаты, слайды) — отдельный шрифт семейства →
p.note; - абзац = блок PDF; блок без красной строки в начале страницы приклеивается к абзацу с предыдущей страницы;
- переносы на конце строки снимаются, соседние
</i><i>схлопываются; - иллюстрации выгружаются в
images/, обложка рендерится со страницы 1 в 150 dpi; - позиционирование не сохраняется намеренно — текст должен течь под любой размер шрифта на читалке.
Требования
PyMuPDF и calibre:
python3 -m venv ~/.venvs/pdf2epub
~/.venvs/pdf2epub/bin/pip install pymupdf
sudo dnf install calibre # если ebook-convert ещё нет
Использование
Разведка — какие в PDF шрифты и кегли (пороги в скрипте подобраны под вёрстку 15pt/letter, для другой книги их правят по этому выводу):
~/.venvs/pdf2epub/bin/python pdf2html.py --fonts book.pdf
Конвертация:
~/.venvs/pdf2epub/bin/python pdf2html.py book.pdf out/book.html
ebook-convert out/book.html "Название.epub" \
--title="Название" \
--authors="Автор" \
--language=en \
--cover=out/images/cover.jpg \
--level1-toc='//h:h1' --level2-toc='//h:h2' \
--page-breaks-before='//h:h1' \
--no-default-epub-cover
ebook-convert "Название.epub" "Название.azw3"
--level1-toc/--level2-toc обязательны: без них calibre строит оглавление
своей эвристикой и ломает разбивку по главам.
Куда класть на Kindle
.epub— через Send to Kindle (веб или почта), Amazon конвертирует на своей стороне;.azw3— по USB прямо вdocuments/на устройстве.
Проверка результата
python3 - <<'EOF'
import re
t = open('out/book.html').read()
print('курсив:', t.count('<i>'), 'полужирный:', t.count('<b>'))
print('заголовки:', len(re.findall(r'<h1', t)))
print('двойные пробелы:', re.sub('<[^>]+>', '', t).count(' '))
EOF
Двойных пробелов должно быть единицы, курсива — сотни. Ноль курсива означает,
что имена шрифтов в PDF не попали под правило в style().
Ограничения
- рассчитан на PDF с текстовым слоем; сканы требуют OCR и сюда не годятся;
- пороги кеглей и семейство шрифта для врезок — константы под конкретную вёрстку,
правятся руками по выводу
--fonts; - колонтитулы и номера страниц не вырезаются: в PDF от calibre их нет.
Для типографского PDF понадобится отбрасывать блоки по координате
y.
Проверено на
The Unicorn Project (Gene Kim), 399 страниц: 40 заголовков, оглавление на
62 пункта, 430 курсивных фрагментов, 178 врезок, 5 иллюстраций, ~733 тыс. знаков.