如何用脚本修改epub文件中的某些文本?

1 投票
4 回答
2575 浏览
提问于 2025-04-17 13:11

我最近买了一个Nook Simple Touch电子书阅读器。我用Calibre来管理我的电子书,并把它们传输到Nook上。

由于B&N(Barnes & Noble)在实现epub标准时不太标准,Nook ST在从很多来源导入电子书时,封面图片无法显示。这个问题在这里有详细描述:http://john.nachtimwald.com/2011/08/21/nook-covers-not-showing-up/。简单来说,Nook ST要求封面的XML属性格式是:

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

但很多电子书制作工具生成的格式是这样的:

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

结果Nook ST就完全忽略了封面图片。

我一直在手动编辑我的电子书文件中的content.opf文件。到目前为止,所有的文件都有图片元数据,但总是以“错误”的方式存在(对Nook来说是错误的)。

最近我在玩REGEX,主要是想自动清理那些从PDF文件转换过来的epub文件。对于REGEX我还是个初学者。

我想知道如何自动交换'名称'和'内容'这两个属性。我觉得可以通过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实现问题)。我想到可以在Calibre论坛和mobileread论坛上发布,因为这两个论坛我比较熟悉,也看到过有人讨论手动修复这个问题。

有没有人能教我如何创建这样的脚本?理想情况下,我希望能真正学会如何创建这个脚本,这样随着时间的推移,我可以开始自己解决这些问题(尤其是REGEX部分,因为我越来越意识到它的用处)。

谢谢。

Jonathan

@Haldean: 添加了这个内容来说明我在评论中提到的,让他的脚本能够递归地处理所有子文件夹中的所有content.opf文件。

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

4 个回答

0

我个人觉得用正则表达式来做这个事情不太合适,这不是对的工具。你可以考虑用XSLT吗?


编辑:

这里有一个演示。
http://www.xsltcake.com/slices/nvLRJ6

有很多适用于Python的XSLT库


编辑:

如果你坚持要用正则表达式来做,你可以用这样的模式:
<meta content="([^"]+)" name="([^"]+)" \/>

我这样说是因为这不是对的工具,而且有一些特殊情况会让这个方法不太可靠,所以我不推荐这样做。

http://regexr.com?301uq

1

我建议你使用sed来处理解压后的文件,可以做一些类似这样的操作:

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

请注意,这个版本可以处理多余的空格、缺失的空格或者斜杠。

你可能还想用一个xml处理工具(我建议用一个python脚本,使用lxml)来检查一下你的修改是否没有导致无效的标记。

使用任何类型的XML工具来进行操作其实并不太好,因为一个完全合规的XML处理器可能会做一些合法的更改,这样反而可能会引发你其他地方的问题。而使用sed可以让你只编辑你想要的文档部分。

2

如果你愿意使用一个脚本(我觉得这是个更好的选择),那么你可以用一行命令来处理,叫做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)

撰写回答