如何用脚本修改epub文件中的某些文本?
我最近买了一个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 个回答
我个人觉得用正则表达式来做这个事情不太合适,这不是对的工具。你可以考虑用XSLT吗?
编辑:
这里有一个演示。
http://www.xsltcake.com/slices/nvLRJ6
有很多适用于Python的XSLT库。
编辑:
如果你坚持要用正则表达式来做,你可以用这样的模式:
<meta content="([^"]+)" name="([^"]+)" \/>
我这样说是因为这不是对的工具,而且有一些特殊情况会让这个方法不太可靠,所以我不推荐这样做。
我建议你使用sed来处理解压后的文件,可以做一些类似这样的操作:
sed -e 's/<[ ]*meta[ ]*content[ ]*=[ ]*"\(.*\)"[ ]*name[ ]*=[ ]*"cover"[ ]*\/*[ ]*>/<meta name="cover" content="\1" \/>/g'
请注意,这个版本可以处理多余的空格、缺失的空格或者斜杠。
你可能还想用一个xml处理工具(我建议用一个python脚本,使用lxml
)来检查一下你的修改是否没有导致无效的标记。
使用任何类型的XML工具来进行操作其实并不太好,因为一个完全合规的XML处理器可能会做一些合法的更改,这样反而可能会引发你其他地方的问题。而使用sed
可以让你只编辑你想要的文档部分。
如果你愿意使用一个脚本(我觉得这是个更好的选择),那么你可以用一行命令来处理,叫做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)