Найти тему
Pythonic Channel

«Чтение - всему голова!» Переводим электронные книги формата .EPUB с помощью Python.

Разберёмся что “под капотом” формата EPUB и как перевести текст, но не переводить код в книге.

Познакомимся с библиотекой Ebook Lib, а также узнаем для чего нам понадобиться библиотека Beautiful Soup.

Занимаясь программированием, в русскоязычном сегменте интернета, столкнулся с тем, что много литературы на интересующие меня темы на английском языке. Либо есть перевод, но специфика отрасли такая, что все очень быстро меняется и если заграничные авторы книг исправно выпускают обновление, то перевод зачастую отстает на 2-3 года, что достаточно критично. Прекрасно понимаю, что такие книги и документацию необходимо уметь читать на английском языке, над чем я собственно усердно работаю. С другой стороны читая монументальную литературу на языке оригинала, все еще хочется открыть перевод в соседнем окне и свериться правильно ли ты уловил мысль автора.

Кажется, в чем проблема? Закинул PDF в любой переводчик, а то и в самом браузере перевод автоматический подтягивается, только такие переводчики в основном не распознают код в тексте. Тут возникает основная проблема, которая и сподвигла меня на поиск решения и автоматизации всего процесса. А для этого есть язык программирования Python.

Чем переводить?

Создадим класс TranslateEpub и добавим метод __translation_func для перевода текста, используем библиотеку Googletrans.

-2

Так мы подходим к предмету нашего изучения, коим является один из самых популярных форматов электронных книг - EPUB. Все дело в том, что PDF не содержит никакой информации о параметров текста который хранит. А вот EPUB включает в себя набор XHTML- или HTML-страниц, что существенно облегчает перевод текста по нужным нам параметрам.

Чтобы посмотреть структуру электронной книги я воспользовался программой Sigil - EPUB Editor.

-3

Тут можно определить на какие части делится документ, его форматы (XHTML, HTML или PDF), а главное посмотреть разметку в каких тегах у нас содержиться код и по каким признакам его можно будет исключить из перевода.

Вот пример тегов:

tag_exeption = ['code', 'a', 'strong', 'pre', 'span', 'html',

'div', 'body', 'head']

Добавим конструктор класса с атрибутами epub_path - путь до файла книги, language - язык перевода текста.

-4

Теперь, воспользуемся библиотекой Ebook Lib, примеры ее использования можно посмотреть здесь.

С помощью функции ebooklib.epub.read_epub() читаем файл и получаем экземпляр класса ebooklib.epub.EpubBook.

Все ресурсы в электронной книге (таблицы стилей, изображения, видео, звуки, скрипты и HTML-файлы) являются элементами. Их можно извлечь по типу с помощью функции ebooklib.epub.EpubBook.get_items_of_type().

Вот список элементов которые можно использовать:

  • ITEM_UNKNOWN = 0
  • ITEM_IMAGE = 1
  • ITEM_STYLE = 2
  • ITEM_SCRIPT = 3
  • ITEM_NAVIGATION = 4
  • ITEM_VECTOR = 5
  • ITEM_FONT = 6
  • ITEM_VIDEO = 7
  • ITEM_AUDIO = 8
  • ITEM_DOCUMENT = 9
  • ITEM_COVER = 10

Мы воспользуемся методом book.get_items() который позволяет получать нам итератор по всем элементам книги - объекты ebooklib.epub.EpubItem. Для перевода нам нужны элементы навигации ITEM_NAVIGATION = 4 и главы книги которые содержатся в элементах ITEM_DOCUMENT = 9, чтобы их получить по типу используйте метод item.get_type().

Также мы можем получить имя элемента item.get_name(), уникальный идентификатор для этого элемента item.get_id() и его содержимое item.get_content().

Для этого напишем метод get_items где получим список нужных нам элементов.

-5

Получив главы в формате XHTML, осталось отделить мух от котлет для этого нам поможет библиотека Beautiful Soup. Приготовим soup:

-6

Для этого напишем метод cook_soup, и передадим его методу __child_translate для перевода элементов.

Теперь нам нужно пробежаться по всем элементам внутри этого объекта, для этого будем использовать атрибут .descendants. Он хорош тем, что в отличии от атрибутов .contents и .children которые учитывают только прямых потомков, позволяет рекурсивно перебирать все дочернии элементы прямых дочерних элементов. Что из себя представляют такие элементы можно посмотреть используя атрибуты: .name - имя тега, .attrs - атрибуты тега (class, id) в формате словаря.

Атрибут .descendants перебирает все отдельные элементы, которые содержит soup, в том числе и строки между тегов и пустые теги. Через условие отбираем нам нужные элементы, исключая tag_exeption, голый текст (child.name) и теги которые напрямую не содержащие текст (child.string). Полученный атрибутом .string текст переводим функцией translation_func() и потом присваиваем переведенный текст нашему дочернему элементу тем же атрибутом .string .

Теги которые не содержат на прямую текст отдельно прогоняем через атрибут .contents, исключая имена тегов (not content.name), пробелы и переносы ['\n', ' '].

-7

Beautiful Soup использует для хранения фрагментов текста класс NavigableString, переведенный текст делаем объектами этого класса, очищаем содержимое нашего потомка (child.clear()), добавляем эти объекты в содержимое потомка используя child.extend(new_contents).

Осталось элементу book присвоить новый контент в виде нашего объекта soup, используя метод .set_content(), не забывая перекодировать.

item.set_content(soup.encode())

Дополнительно, мне понравилось использовать просмотр контента элементов book в браузере с помощью метода .open_in_browser(contents) библиотеки lxml, для этого нужно предварительно перекодировать наш контент воспользовавшись утилитой из библиотеки Ebook Lib - utils.parse_string(item.get_content()).

-8

И последнее что нам нужно - это сохранить переведенную книгу.

epub.write_epub('new_book.epub', book, {})

Весь код по ссылке на Github

В дополнение еще нужно отметить про файлы CSS, в книги их можно прочитать в файлах типа ITEM_STYLE = 2 или посмотреть в программе Sigil - EPUB Editor в заголовках элементов книги,

а находятся они в папке Styles.

<head>

<title>Example book</title>

<link href="../Styles/epub.css" rel="stylesheet" type="text/css"/>

<link href="../Styles/syntax-highlighting.css" rel="stylesheet" type="text/css"/>

</head>

После перезаписи элементов книги ссылки на CSS в заголовке пропадают их можно вернуть с помощью программы Sigil - EPUB Editor, нужно выбрать все элементы книги в папке text и правой кнопкой в контекстном меню выбрать “Связать с таблицей стилей…”.

Это все! Наша книга готова!

В заключении хочется сказать, что автоматизировать процессы - интересно, повышает общую эрудицию, учит работать с разными библиотеками что называется залезть под “под капот”, да и просто разнообразить рутину.