TL; DR:
- PandOC ожидает, что заголовки главы должны быть размещены непосредственно внутри
тело
узел. Нетобертки разрешены.
- Pandoc устанавливает название книги после прошлой
Тег, который он видит (например, последний файл в командной строке).
Прошло долгое время, так как я в последний раз должен был преобразовать электронную книгу HTML в EPUB. В прошлый раз я сделал, я не мог сделать калибр поставить главы в правильном порядке 1 и так злился, что пытался передать файл с Баш и куча Regexen . Это было, безусловно, интересный эксперимент, и я многому научился о внутренних ценах в процессе. Я также узнал, что пока Это нормально для анализа ограниченного, известного набора HTML с Regex , гораздо удобнее использовать фактический анализатор HTML.
С тех пор я влюбился в Pandoc и использовали его широко для различных проектов 2 Отказ Так когда я недавно хотел прочитать F # Программирование Wikibook На мойку я знал, что буду использовать Pandoc для преобразования.
Мой энтузиазм несколько упал, когда я изучил полученный файл и обнаружил, что сгенерированная оглавление состояла из одной записи, названной в честь последней главы книги. И это была не только проблема сломанной навигации.
Файл EPUB – это, по сути, архив ZIP с главами, хранящимися в отдельных файлах HTML. Благодаря этому, читатели электронных книг могут откройте их один за другим, что означает более быструю загрузку и нижнюю часть памяти. Поскольку Pandoc не знал, как разделить книгу в главы, она поместила их все в один файл, чтобы мой читатель должен был подсказать и отформатировать весь текст, прежде чем отображать что-либо – измельчать его, чтобы остановиться на минуту каждый раз, когда книга была открыл.
Для HTML-ввода Pandoc должен автоматически генерировать TOC из ,
…
разметки. После некоторых экспериментов оказалось, что Pandoc ожидает, что заголовки глада будут размещены непосредственно внутри
тело
узел . Хотя это имеет смысл для документов, написанных для единственной цели быть упакованным в качестве EPUB, это редко бывает в случае с HTML-страницами в Интернете, где вы часто найдете фактический контент, завернутый в несколько слоев Div
S (или таблицы, если вы неудачно бродить такими опасными, бого-забытыми местами).
Вот тестовый случай. Скажем, у нас есть книга под названием Книга , который состоит из четырех глав:
seq 1 4 | while read idx; do > "ch$idx.html" <Chapter $idx - The Book EOF doneChapter $idx
Lorem ipsum, dolor sit amet.
Когда мы кормите их в Pandoc, мы получаем сломанный TOC с титульной страницей и одной главой, охватывая все входные файлы:
pandoc -o the_book.epub ch*.html
Чтобы исправить оглавление, мы должны немного помочь Pandoc и переместить S до дерева, пока они не являются детьми
тело
. Вот как мы можем сделать это с Python и Красивый суп :
fix.py:
import bs4 filenames = [ 'ch1.html', 'ch2.html', 'ch3.html', 'ch4.html' ] for filename in filenames: with open(filename, 'r') as f: soup = bs4.BeautifulSoup(f, 'lxml') current = soup.find(id='content') while current.name != 'body': parent = current.parent current.unwrap() current = parent out_filename = filename.replace('.', '-flat.') with open(out_filename, 'w') as f: f.write(soup.prettify())
Для каждого указанного файла скрипт создает DOM и находит узел с фактическим контентом – в этом случае, тот, с помощью Содержание
ID (если у вашего DIV нет назначенного идентификатора, но у него есть определенный класс, вы можете получить его с SUP.find (Class _ = '...')
вместо). Призыв к развернуть
Метод заменяет узел своими детьми, и мы перемещаемся вверх по дереву на родитель удаленного узла. Код повторяется до тех пор, пока Тело
Узел достигнут. Наконец, DOM сохраняется в файл с -FLAT
прилагается к его названию.
python fix.py pandoc \ -o the_book.epub \ ch1-flat.html \ ch2-flat.html \ ch3-flat.html \ ch4-flat.html
Так-то лучше. Главы были обнаружены и разделить правильно, но топ-две записи, которые должны быть названным книгой, неверно подписаны Глава 4 – книга . Возможно, вы заметили, что это текст в <название>
последнего файла в командной строке.
Pandoc устанавливает название книги после содержания <название>
узел. При вызове с несколькими входными файлами и есть более одного <название>
Тег, Pandoc использует последний увиденный. Но для электронных книг охватывает несколько HTML-документов, <название>
S обычно обозначает названия главы и не должно влиять на название книги.
Чтобы исправить это, мы должны погружаться в HTML еще раз 3 убедитесь, что есть только один <название>
Тег на наших входных файлах, и это установлено на нужное название книги:
actual_title = 'The Book' title_node = soup.find('title') if filename == filenames[0]: title_node.string = actual_title else: title_node.extract()
Наконец, оглавление выглядит как ожидалось:
pandoc \ -o the_book.epub \ ch1-flat.html \ ch2-flat.html \ ch3-flat.html \ ch4-flat.html
Это было предположительно контролировалось Внутренний переключатель первого порядка в предпочтениях → Плагины → HTML к плагину ZIP Но настроить его, казалось, вообще не влиял. ↩
Мой тезис является очевидным, но и статическим поколением сайта – и этот блог, так и ninjastyles.tznvy.eu Бегите на Pandoc и немного питона. ↩
Это на самом деле звучит как хорошее использование для регеляции. Или $ Редактор
Если есть только несколько файлов. Но давайте сделаем это в Python, просто чтобы быть последовательным. ↩
Этот пост был первоначально опубликован на blog.tznvy.eu
Оригинал: “https://dev.to/brthanmathwoag/helping-pandoc-generate-a-correct-table-of-contents-from-html-input-27im”