Regex 希望从ePubs中提取文本,但删除目录。这可能吗?
对于我正在创建的应用程序,我希望从开源ePub中提取文本,并对文本进行操作。但是,我不想要目录。我只想从第一章或序言开始 以古腾堡项目的汤姆·索耶为例: ePubs几乎只是一个包含大量HTML文档的ZIP文件。因此,在解压ePub之后,我在上面的链接中打开了第一个HTML文件,我得到了第一章以及一堆我不想要的目录 这就是我好奇的地方。是否可以通过我丢失的元数据或Regex删除目录/检测它Regex 希望从ePubs中提取文本,但删除目录。这可能吗?,regex,parsing,language-agnostic,extract,epub,Regex,Parsing,Language Agnostic,Extract,Epub,对于我正在创建的应用程序,我希望从开源ePub中提取文本,并对文本进行操作。但是,我不想要目录。我只想从第一章或序言开始 以古腾堡项目的汤姆·索耶为例: ePubs几乎只是一个包含大量HTML文档的ZIP文件。因此,在解压ePub之后,我在上面的链接中打开了第一个HTML文件,我得到了第一章以及一堆我不想要的目录 这就是我好奇的地方。是否可以通过我丢失的元数据或Regex删除目录/检测它 说清楚一点,我是以编程的方式讲的。使用sed怎么样:sed'2,/preference/d'fileName
说清楚一点,我是以编程的方式讲的。使用sed怎么样:
sed'2,/preference/d'fileName>newFile
或者如果您想保持“序言”的完整性sed'2,/preforce/{/preforce/n;d}'inputFile>new file
或者更好的是
sed'/CONTENTS/,/preforce/{/preforce/n;d}'fileName>newFile
好吧,我想你可以尝试像拉出preforce
之类的东西,然后再把它全部取出来:
~.*\KPREFACE\n(.*)$~ms
此表达式匹配到前言
的所有内容,然后将其忘记。然后它匹配前言
,然后是换行符和其后的任何内容,一直到结尾
不过,我有一种感觉,你可能也想把这些东西放在目录之前。在这种情况下,您可以这样做,以便在比赛前后抓取部件:
~(.*)(?:CONTENTS\n.*?\n{3,})(.*)~ms
这将捕获内容之前的所有内容
,并将其存储到\1
中。之后的所有内容都将存储在\2
中
在PHP中,我会使用preg_replace
将目录前后的部分放在一起
<?php
$string = preg_replace('~(.*)(?:CONTENTS\n.*?\n{3,})(.*)~ms', '$1$2', $string);
print $string;
在epub2中,有一个目录文件。首先,从container.xml开始。在ePub中,它总是在同一个地方,使用相同的名称
$unzip -p /Users/mwu/Downloads/9781434705211.epub META-INF/container.xml
<?xml version="1.0"?>
<container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container">
<rootfiles>
<rootfile full-path="OPS/package.opf" media-type="application/oebps-package+xml"/>
</rootfiles>
</container>
$unzip-p/Users/mwu/Downloads/9781434705211.epub META-INF/container.xml
这表明ePub包元数据位于OPS/package.opf中。包元数据指定ePub中的所有文件都有一个清单,并有一个spine项列表定义它们在书中的顺序。spine标记还使用toc属性定义目录的位置。此外,书脊中列出的项目表示构成书籍本身的文件。列出的任何内容linear=“no”都是辅助内容,而不是主要内容。规范规定,第一个linear=“yes”(默认值)开始主阅读顺序,但可以包含(本书中的情况)目录作为本书本身的一部分
<manifest>
...
<item id="ncx" href="toc.ncx" media-type="application/x-dtbncx+xml"/>
...
</manifest>
<spine toc="ncx">
<itemref idref="my-html-cover" linear="no"/>
<itemref idref="title"/>
<itemref idref="f1"/>
<itemref idref="ded"/>
<itemref idref="contents"/>
<itemref idref="ack"/>
<itemref idref="f2"/>
<itemref idref="chapter1"/>
<itemref idref="chapter2"/>
<itemref idref="chapter3"/>
<itemref idref="chapter4"/>
<itemref idref="chapter5"/>
<itemref idref="chapter6"/>
<itemref idref="chapter7"/>
<itemref idref="b1"/>
<itemref idref="b2"/>
<itemref idref="b3"/>
<itemref idref="b4"/>
<itemref idref="copyright"/>
</spine>
...
...
这表明目录由引用toc.ncx文件的清单中的ncx项标识。请注意,路径是相对于package.opf文件的,因此可以在OPS/toc.ncx中找到它
toc.ncx文件包含一个navMap标记,其中列出了定义书籍不同部分的navPoint标记以及对它们的引用
在package.opf文件中的标记和toc.ncx文件中,您都可以获得该书各部分的列表以及它们的顺序。它们还都列出了contents.html,我认为这是您想要排除的内容。在书脊目录中并没有一致的东西可以识别,也不能保证它甚至存在于一本书中。您可以尝试扫描spine标记以及每个spine项目文件的内容,以查找通常标识目录的单词或引用书籍中其他spine项目的一系列链接,但这可能无法100%捕获所有内容
一般来说,这样的文件被认为是本书的一部分,删除它们被认为是不正确的(可访问性是更大的原因之一)
另外,请注意,ePub 2文件规范可在中找到。ePub 3规范位于虽然我个人不建议在任何时候使用基于DOM的方法,但我认为在这种情况下不可能使用基于DOM的方法 我能够在两行JavaScript代码中实现所需的结果,您可以在浏览器控制台中测试这些代码
var dbody = document.body;
dbody.innerHTML = "<h2>" + dbody.innerHTML.substring(dbody.innerHTML.indexOf("PREFACE"));
var dbody=document.body;
dbody.innerHTML=“”+dbody.innerHTML.substring(dbody.innerHTML.indexOf(“前言”);
此代码应在前言之前删除文档正文中的所有内容。您是否尝试过Calibre?@sbumb他们是否有API?我是以编程的方式说的。再想想这个,我想我应该解析脊椎项目中的html,并查找引用其他脊椎项目的锚定标记。其中一系列可能会标识一个目录。在ncx文件中,它引用HTMLDOM中目录的#id。这是eht的最佳选择吗?看起来在本例中,它确实在ncx中列出了TOC(opf文件指南部分中的参考也指出了TOC:)。我认为ePubs不需要提供这些参考资料,因此在某些ePubs中寻找这些参考资料是可行的,而在其他ePubs中则不然。这是一个很好的起点,但您必须有一种回退方法来检测书籍内容中的目录。我想说,在书籍内容中查找toc的一个相当可靠的算法是:1:检查ncx(epub 2)或toc xhtml文件(epub 3)中是否有名为contents的条目(不区分大小写比较)。2:检查OPF文件中指南中是否有type=“toc”引用的条目。3:返回到使用正则表达式搜索脊椎项目,类似于此处其他答案所建议的正则表达式。还要注意的是,并非所有的epub都会包含内容内toc——它们可能依赖于epub特定的toc文件。我认为这并不像您希望的那样简单,但我希望它能有所帮助。