Как я могу использовать скрипт для изменения текста в файле epub? - PullRequest
1 голос
/ 17 февраля 2012

Я недавно купил Nook Simple Touch. Я использую Caliber, чтобы управлять своими электронными книгами и передавать их в Nook.

Из-за нестандартной реализации спецификации epub со стороны B & N, Nook ST не отображает обложки, когда они получены из многих источников. Проблема описана здесь: http://john.nachtimwald.com/2011/08/21/nook-covers-not-showing-up/ В основном Nook ST требует, чтобы атрибут XML для обложки был в формате:

<meta name="cover" content="id5" />

Но у многих создателей epub они есть так:

<meta content="id5" name="cover" />

И тогда Nook ST полностью игнорирует изображение обложки.

Я вручную редактировал файл content.opf в моих файлах epub. До сих пор у всех были мета-образы, но они всегда были вокруг «неправильного» пути (неправильного, согласно Nook).

Недавно я поигрался с REGEX, в основном, чтобы попытаться автоматизировать очистку epubs, конвертируемых Caliber, из файлов PDF. Я все еще очень начинающий с REGEX.

Что мне было интересно, так это то, как я могу автоматизировать замену атрибутов 'name' и 'content'? Я полагаю, что это можно сделать с помощью комбинации REGEX и сценариев. Я знаю, что некоторые другие скрипты, связанные с epub, у меня есть на Python. Я на Mac (OS X), и они, кажется, работают нормально. AppleScript также может быть хорошим вариантом, хотя мне бы хотелось, чтобы люди могли работать на любой платформе, так как я уверен, что другие люди сочтут это полезным.

Вот шаги, которые я предвижу:

~ Извлечь файл epub

~ Используйте REGEX для поиска:

<meta content="???" name="cover">

~ Если найдено, используйте REGEX, чтобы изменить его на:

<meta name="cover" content="???">

~ Заархивируйте извлеченные файлы обратно в epub, используя правильный процесс архивирования.

Я нашел здесь информацию: http://www.mobileread.com/forums/showthread.php?t=55681, объясняющую, как правильно заархивировать файл epub. В основном это требует этих двух команд:

zip -X0 "full path to new epub file" mimetype
zip -rDX9 "full path to new epub file" * -x "*.DS_Store" -x mimetype

Я бы хотел опубликовать полученный скрипт онлайн, где бы он ни был найден и использован (до тех пор, пока B & N не разрешит свою плохую реализацию epub / XML). На ум приходит его публикация на форумах Caliber и на мобильных форумах (с тех пор, как я познакомился с двумя из них, я видел, как люди исправляли эту проблему в руководстве по обсуждению).

Есть ли кто-нибудь, кто может рассказать мне, как создать такой сценарий? В идеале я хотел бы знать, как на самом деле создать сценарий, чтобы со временем я сам начал разбираться с подобными вещами (особенно с частью REGEX, поскольку я все больше и больше вижу, насколько она полезна).

Спасибо.

Jonathan

@ Haldean: ДОБАВЛЕНО, чтобы проиллюстрировать, что я имею в виду в комментарии к Haldean о том, как заставить его скрипт рекурсивно работать со всеми файлами content.opf во всех подпапках.

> My_expanded_epubs
- -> epub_one_expanded
- - - -> content.opf
- -> epub_two_expanded
- - - -> content.opf
- -> epub_three_expanded
- - - -> content.opf
etc.

Ответы [ 4 ]

2 голосов
/ 17 февраля 2012

Если вы готовы использовать сценарий оболочки (который я считаю более подходящим вариантом), вы можете использовать однострочник sed:

sed 's/<meta content="\(.*\)" name="cover" \/>/<meta name="cover" content="\1" \/>/' [your-file]

Это должно заменить все мета-строки, где атрибут content стоит первым, с атрибутом правильного порядка. Эквивалентный перевод Python этого будет:

import re
import sys
with open(sys.argv[1]) as f:
  for line in f:
    # Match this line to the wrong-way-around meta tag, put the content in group 1
    m = re.match(r'<meta content="(.*)" name="cover" />', line)
    if not m:
      print line
    else:
      print '<meta name="cover" content="%s" />' % m.group(1)
1 голос
/ 17 февраля 2012

Я бы посоветовал вам использовать sed для работы с распакованным файлом и сделать что-то вроде:

sed -e 's/<[ ]*meta[ ]*content[ ]*=[ ]*"\(.*\)"[ ]*name[ ]*=[ ]*"cover"[ ]*\/*[ ]*>/<meta name="cover" content="\1" \/>/g'

Обратите внимание, что эта версия будет справляться с лишним или недостающим пробелом или косой чертой.

Возможно, вы захотите впоследствии использовать xml-процессор (я бы предложил сценарий python, использующий lxml), чтобы убедиться, что в вашем редакторе нет созданной недопустимой разметки.

Использование любого вида инструмента XML для выполнения манипуляций крайне непривлекательно, потому что полностью совместимый процессор XML может вносить другие изменения, которые являются абсолютно законными, а также вызывать другие ошибки в вашем уголке. Использование sed позволяет редактировать только те части документа, которые вы хотите.

0 голосов
/ 17 февраля 2012

Я согласен с ответом zapthedingbat : это проблема XML, поэтому давайте использовать инструменты, специально предназначенные для XML, а именно XSLT.

Поскольку вы новичок в XSLT, вынужен XSLT процессор, чтобы попробовать это решение.Если вы используете * nix, xsltproc является процессором командной строки и почти наверняка установлен по умолчанию, и вы можете использовать это решение по номинальной стоимости.Если нет, вам нужно проверить, есть ли у вашего языка выбора API для выполнения XSL-преобразований.

Вот очень простое общее решение для изменения порядка атрибутов:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:template match="@*|node()">
  <!-- copy everything as is -->
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="meta">
    <!-- except for the <meta/> element, reverse the attribute order -->
    <meta name="{@name}" content="{@content}"/>
  </xsl:template>
</xsl:stylesheet>

Вот вашпример:

<root>
  <meta content="id5" name="cover" />
</root>

Запуск XSLT с xsltproc:

$ xsltproc so.xsl so.xml

и результат:

<root>
  <meta name="cover" content="id5"/>
</root>
0 голосов
/ 17 февраля 2012

Лично я бы не стал делать это с регулярным выражением ( это неправильный инструмент ). Не могли бы вы использовать XSLT?


EDIT:

Вот демо. http://www.xsltcake.com/slices/nvLRJ6

Существует ряд библиотек XSLT для python .


EDIT:

Если вы настаиваете на том, чтобы делать это с помощью регулярных выражений, вам понадобится такой шаблон:
<meta content="([^"]+)" name="([^"]+)" \/>

Я говорю это с оговоркой , что это неправильный инструмент , и есть крайние случаи, которые делают это ненадежным, и я не рекомендую его.

http://regexr.com? 301uq

...