kindle manager

This commit is contained in:
douboer
2024-04-03 15:08:22 +08:00
parent 6b3c0f3b6b
commit 6df3ce42a3
459 changed files with 164651 additions and 4690 deletions

BIN
design/.DS_Store vendored Normal file

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

View File

@@ -1,87 +0,0 @@
# -*- coding: utf-8 -*-
import shutil
from loguru import logger
import tempfile
from os.path import basename, splitext, exists, join
from mobi.kindleunpack import unpackBook
def extract(infile):
"""Extract mobi file and return path to epub file"""
tempdir = tempfile.mkdtemp(prefix="mobiex")
if hasattr(infile, "fileno"):
tempname = next(tempfile._get_candidate_names()) + ".mobi"
pos = infile.tell()
infile.seek(0)
with open(join(tempdir, tempname), "wb") as outfile:
shutil.copyfileobj(infile, outfile)
infile.seek(pos)
infile = join(tempdir, tempname)
logger.debug("file: %s" % infile)
fname_in = basename(infile)
base, ext = splitext(fname_in)
fname_out_epub = base + ".epub"
fname_out_html = "book.html"
fname_out_pdf = base + ".001.pdf"
unpackBook(infile, tempdir, epubver="A")
epub_filepath = join(tempdir, "mobi8", fname_out_epub)
html_filepath = join(tempdir, "mobi7", fname_out_html)
pdf_filepath = join(tempdir, fname_out_pdf)
if exists(epub_filepath):
return tempdir, epub_filepath
elif exists(html_filepath):
return tempdir, html_filepath
elif exists(pdf_filepath):
return tempdir, pdf_filepath
raise ValueError("Coud not extract from %s" % infile)
def extracttest(infile):
"""Extract mobi file and return path to epub file"""
tempdir = './t/'
if hasattr(infile, "fileno"):
tempname = next(tempfile._get_candidate_names()) + ".mobi"
pos = infile.tell()
infile.seek(0)
with open(join(tempdir, tempname), "wb") as outfile:
shutil.copyfileobj(infile, outfile)
infile.seek(pos)
infile = join(tempdir, tempname)
# tempname 8x2vf7yv.mobi pos 0 infile ./t/8x2vf7yv.mobi
print('tempname {} pos {} infile {}'.format(tempname,pos,infile))
logger.debug("file: %s" % infile)
fname_in = basename(infile)
base, ext = splitext(fname_in)
fname_out_epub = base + ".epub"
fname_out_html = "book.html"
fname_out_pdf = base + ".001.pdf"
# infile ./t/8x2vf7yv.mobi
unpackBook(infile, tempdir, epubver="A")
epub_filepath = join(tempdir, "mobi8", fname_out_epub)
html_filepath = join(tempdir, "mobi7", fname_out_html)
pdf_filepath = join(tempdir, fname_out_pdf)
# CGDBG
#epub_filepath ./t/mobi8/p302tbwb.epub html_filepath ./t/mobi7/book.html pdf_filepath ./t/p302tbwb.001.pdf
print('epub_filepath {} html_filepath {} pdf_filepath {}'.format( epub_filepath, html_filepath, pdf_filepath))
if exists(epub_filepath):
return tempdir, epub_filepath
elif exists(html_filepath):
return tempdir, html_filepath
elif exists(pdf_filepath):
return tempdir, pdf_filepath
raise ValueError("Coud not extract from %s" % infile)
if __name__ == "__main__":
#print(extracttest("../tests/demo.mobi"))
pass

View File

@@ -1,286 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
from __future__ import unicode_literals, division, absolute_import, print_function
import os
from .unipath import pathof
from loguru import logger
import re
# note: re requites the pattern to be the exact same type as the data to be searched in python3
# but u"" is not allowed for the pattern itself only b""
'''
NCX (Navigation Control for XML applications) is a generalized navigation definition DTD for application
to Digital Talking Books, eBooks, and general web content models.
This DTD is an XML application that layers navigation functionality on top of SMIL 2.0 content.
The NCX defines a navigation path/model that may be applied upon existing publications,
without modification of the existing publication source, so long as the navigation targets within
the source publication can be directly referenced via a URI.
http://www.daisy.org/z3986/2005/ncx-2005-1.dtd
'''
from .mobi_utils import toBase32
from .mobi_index import MobiIndex
DEBUG_NCX = True
class ncxExtract:
def __init__(self, mh):
self.mh = mh
self.sect = self.mh.sect
self.isNCX = False
self.mi = MobiIndex(self.sect)
self.ncxidx = self.mh.ncxidx
self.indx_data = None
def parseNCX(self):
indx_data = []
tag_fieldname_map = {
1: ["pos", 0],
2: ["len", 0],
3: ["noffs", 0],
4: ["hlvl", 0],
5: ["koffs", 0],
6: ["pos_fid", 0],
21: ["parent", 0],
22: ["child1", 0],
23: ["childn", 0],
}
if self.ncxidx != 0xFFFFFFFF:
outtbl, ctoc_text = self.mi.getIndexData(self.ncxidx, "NCX")
if DEBUG_NCX:
logger.debug("ctoc_text {}".format(ctoc_text))
logger.debug("outtbl {}".format(outtbl))
num = 0
for [text, tagMap] in outtbl:
tmp = {
"name": text.decode("utf-8"),
"pos": -1,
"len": 0,
"noffs": -1,
"text": "Unknown Text",
"hlvl": -1,
"kind": "Unknown Kind",
"pos_fid": None,
"parent": -1,
"child1": -1,
"childn": -1,
"num": num,
}
for tag in tag_fieldname_map:
[fieldname, i] = tag_fieldname_map[tag]
if tag in tagMap:
fieldvalue = tagMap[tag][i]
if tag == 6:
pos_fid = toBase32(fieldvalue, 4).decode("utf-8")
fieldvalue2 = tagMap[tag][i + 1]
pos_off = toBase32(fieldvalue2, 10).decode("utf-8")
fieldvalue = "kindle:pos:fid:%s:off:%s" % (pos_fid, pos_off)
tmp[fieldname] = fieldvalue
if tag == 3:
toctext = ctoc_text.get(fieldvalue, "Unknown Text")
toctext = toctext.decode(self.mh.codec)
tmp["text"] = toctext
if tag == 5:
kindtext = ctoc_text.get(fieldvalue, "Unknown Kind")
kindtext = kindtext.decode(self.mh.codec)
tmp["kind"] = kindtext
indx_data.append(tmp)
# CGDBG
'''
record number: 3
name: 03
position 461377 length: 465358 => position/150 = real page number
text: 第二章 青铜时代­——单机游戏
kind: Unknown Kind
heading level: 0 => level of section
parent: -1 => record number of previous level of section
first child: 15 last child: 26 => range of record number of next level section
pos_fid is kindle:pos:fid:0023:off:0000000000
'''
if DEBUG_NCX:
print("record number: ", num)
print(
"name: ", tmp["name"],
)
print("position", tmp["pos"], " length: ", tmp["len"])
print("text: ", tmp["text"])
print("kind: ", tmp["kind"])
print("heading level: ", tmp["hlvl"])
print("parent:", tmp["parent"])
print(
"first child: ", tmp["child1"], " last child: ", tmp["childn"]
)
print("pos_fid is ", tmp["pos_fid"])
print("\n\n")
num += 1
self.indx_data = indx_data
# {'name': '00', 'pos': 167, 'len': 24798, 'noffs': 0, 'text': '版权信息', 'hlvl': 0, 'kind': 'Unknown Kind', 'pos_fid': None, 'parent': -1, 'child1': -1, 'childn': -1, 'num': 0}
# {'name': '0B', 'pos': 67932, 'len': 3274, 'noffs': 236, 'text': '8.希罗多德', 'hlvl': 0, 'kind': 'Unknown Kind', 'pos_fid': None, 'parent': -1, 'child1': -1, 'childn': -1, 'num': 11}
print(indx_data)
return indx_data
def writeNCX(self, metadata):
# build the xml
self.isNCX = True
logger.debug("Write ncx")
# write the ncx file
# build the xml
xml = self.buildNCX(
metadata["Title"][0],
metadata["UniqueID"][0],
metadata.get("Language")[0],
)
# write the ncx file
# ncxname = os.path.join(self.files.mobi7dir, self.files.getInputFileBasename() + '.ncx')
ncxname = os.path.join(self.files.mobi7dir, "toc.ncx")
with open(pathof(ncxname), "wb") as f:
f.write(xml.encode("utf-8"))
def buildNCX(self):
indx_data = self.indx_data
# recursive part
def recursINDX(max_lvl=0, num=0, lvl=0, start=-1, end=-1):
if start > len(indx_data) or end > len(indx_data):
print("Warning: missing INDX child entries", start, end, len(indx_data))
return ""
if DEBUG_NCX:
logger.debug("recursINDX lvl %d from %d to %d" % (lvl, start, end))
xml = ""
if start <= 0:
start = 0
if end <= 0:
end = len(indx_data)
if lvl > max_lvl:
max_lvl = lvl
indent = " " * (2 + lvl)
for i in range(start, end):
e = indx_data[i]
if not e["hlvl"] == lvl:
continue
# open entry
num += 1
link = "%s#filepos%d" % (htmlfile, e["pos"])
tagid = "np_%d" % num
entry = ncx_entry % (tagid, num, e["text"], link)
entry = re.sub(re.compile("^", re.M), indent, entry, 0)
xml += entry + "\n"
# recurs
if e["child1"] >= 0:
xmlrec, max_lvl, num = recursINDX(
max_lvl, num, lvl + 1, e["child1"], e["childn"] + 1
)
xml += xmlrec
# close entry
xml += indent + "</navPoint>\n"
return xml, max_lvl, num
body, max_lvl, num = recursINDX()
header = ncx_header % (lang, ident, max_lvl + 1, title)
ncx = header + body + ncx_footer
if not len(indx_data) == num:
print("Warning: different number of entries in NCX", len(indx_data), num)
return ncx
def buildK8NCX(self, indx_data, title, ident, lang):
ncx_header = """<?xml version='1.0' encoding='utf-8'?>
<ncx xmlns="http://www.daisy.org/z3986/2005/ncx/" version="2005-1" xml:lang="%s">
<head>
<meta content="%s" name="dtb:uid"/>
<meta content="%d" name="dtb:depth"/>
<meta content="mobiunpack.py" name="dtb:generator"/>
<meta content="0" name="dtb:totalPageCount"/>
<meta content="0" name="dtb:maxPageNumber"/>
</head>
<docTitle>
<text>%s</text>
</docTitle>
<navMap>
"""
ncx_footer = """ </navMap>
</ncx>
"""
ncx_entry = """<navPoint id="%s" playOrder="%d">
<navLabel>
<text>%s</text>
</navLabel>
<content src="%s"/>"""
# recursive part
def recursINDX(max_lvl=0, num=0, lvl=0, start=-1, end=-1):
if start > len(indx_data) or end > len(indx_data):
print("Warning: missing INDX child entries", start, end, len(indx_data))
return ""
if DEBUG_NCX:
logger.debug("recursINDX lvl %d from %d to %d" % (lvl, start, end))
xml = ""
if start <= 0:
start = 0
if end <= 0:
end = len(indx_data)
if lvl > max_lvl:
max_lvl = lvl
indent = " " * (2 + lvl)
for i in range(start, end):
e = indx_data[i]
htmlfile = e["filename"]
desttag = e["idtag"]
if not e["hlvl"] == lvl:
continue
# open entry
num += 1
if desttag == "":
link = "Text/%s" % htmlfile
else:
link = "Text/%s#%s" % (htmlfile, desttag)
tagid = "np_%d" % num
entry = ncx_entry % (tagid, num, e["text"], link)
entry = re.sub(re.compile("^", re.M), indent, entry, 0)
xml += entry + "\n"
# recurs
if e["child1"] >= 0:
xmlrec, max_lvl, num = recursINDX(
max_lvl, num, lvl + 1, e["child1"], e["childn"] + 1
)
xml += xmlrec
# close entry
xml += indent + "</navPoint>\n"
return xml, max_lvl, num
body, max_lvl, num = recursINDX()
header = ncx_header % (lang, ident, max_lvl + 1, title)
ncx = header + body + ncx_footer
if not len(indx_data) == num:
print("Warning: different number of entries in NCX", len(indx_data), num)
return ncx
def writeK8NCX(self, ncx_data, metadata):
# build the xml
self.isNCX = True
logger.debug("Write K8 ncx")
xml = self.buildK8NCX(
ncx_data,
metadata["Title"][0],
metadata["UniqueID"][0],
metadata.get("Language")[0],
)
ncxname = os.path.join('./', 'k8toc.ncx.json')
with open(pathof(ncxname), "wb") as f:
f.write(xml.encode("utf-8"))

View File

@@ -1,315 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
from __future__ import unicode_literals, division, absolute_import, print_function
import os
from .unipath import pathof
from loguru import logger
import re
# note: re requites the pattern to be the exact same type as the data to be searched in python3
# but u"" is not allowed for the pattern itself only b""
'''
NCX (Navigation Control for XML applications) is a generalized navigation definition DTD for application
to Digital Talking Books, eBooks, and general web content models.
This DTD is an XML application that layers navigation functionality on top of SMIL 2.0 content.
The NCX defines a navigation path/model that may be applied upon existing publications,
without modification of the existing publication source, so long as the navigation targets within
the source publication can be directly referenced via a URI.
http://www.daisy.org/z3986/2005/ncx-2005-1.dtd
'''
from .mobi_utils import toBase32
from .mobi_index import MobiIndex
DEBUG_NCX = True
class ncxExtract:
def __init__(self, mh, files):
self.mh = mh
self.sect = self.mh.sect
self.files = files
self.isNCX = False
self.mi = MobiIndex(self.sect)
self.ncxidx = self.mh.ncxidx
self.indx_data = None
def parseNCX(self):
indx_data = []
tag_fieldname_map = {
1: ["pos", 0],
2: ["len", 0],
3: ["noffs", 0],
4: ["hlvl", 0],
5: ["koffs", 0],
6: ["pos_fid", 0],
21: ["parent", 0],
22: ["child1", 0],
23: ["childn", 0],
}
if self.ncxidx != 0xFFFFFFFF:
outtbl, ctoc_text = self.mi.getIndexData(self.ncxidx, "NCX")
if DEBUG_NCX:
logger.debug("ctoc_text {}".format(ctoc_text))
logger.debug("outtbl {}".format(outtbl))
num = 0
for [text, tagMap] in outtbl:
tmp = {
"name": text.decode("utf-8"),
"pos": -1,
"len": 0,
"noffs": -1,
"text": "Unknown Text",
"hlvl": -1,
"kind": "Unknown Kind",
"pos_fid": None,
"parent": -1,
"child1": -1,
"childn": -1,
"num": num,
}
for tag in tag_fieldname_map:
[fieldname, i] = tag_fieldname_map[tag]
if tag in tagMap:
fieldvalue = tagMap[tag][i]
if tag == 6:
pos_fid = toBase32(fieldvalue, 4).decode("utf-8")
fieldvalue2 = tagMap[tag][i + 1]
pos_off = toBase32(fieldvalue2, 10).decode("utf-8")
fieldvalue = "kindle:pos:fid:%s:off:%s" % (pos_fid, pos_off)
tmp[fieldname] = fieldvalue
if tag == 3:
toctext = ctoc_text.get(fieldvalue, "Unknown Text")
toctext = toctext.decode(self.mh.codec)
tmp["text"] = toctext
if tag == 5:
kindtext = ctoc_text.get(fieldvalue, "Unknown Kind")
kindtext = kindtext.decode(self.mh.codec)
tmp["kind"] = kindtext
indx_data.append(tmp)
# CGDBG
'''
record number: 3
name: 03
position 461377 length: 465358 => position/150 = real page number
text: 第二章 青铜时代­——单机游戏
kind: Unknown Kind
heading level: 0 => level of section
parent: -1 => record number of previous level of section
first child: 15 last child: 26 => range of record number of next level section
pos_fid is kindle:pos:fid:0023:off:0000000000
'''
if DEBUG_NCX:
print("record number: ", num)
print(
"name: ", tmp["name"],
)
print("position", tmp["pos"], " length: ", tmp["len"])
print("text: ", tmp["text"])
print("kind: ", tmp["kind"])
print("heading level: ", tmp["hlvl"])
print("parent:", tmp["parent"])
print(
"first child: ", tmp["child1"], " last child: ", tmp["childn"]
)
print("pos_fid is ", tmp["pos_fid"])
print("\n\n")
num += 1
self.indx_data = indx_data
# {'name': '00', 'pos': 167, 'len': 24798, 'noffs': 0, 'text': '版权信息', 'hlvl': 0, 'kind': 'Unknown Kind', 'pos_fid': None, 'parent': -1, 'child1': -1, 'childn': -1, 'num': 0}
# {'name': '0B', 'pos': 67932, 'len': 3274, 'noffs': 236, 'text': '8.希罗多德', 'hlvl': 0, 'kind': 'Unknown Kind', 'pos_fid': None, 'parent': -1, 'child1': -1, 'childn': -1, 'num': 11}
print(indx_data)
return indx_data
def buildNCX(self, htmlfile, title, ident, lang):
indx_data = self.indx_data
ncx_header = """<?xml version='1.0' encoding='utf-8'?>
<ncx xmlns="http://www.daisy.org/z3986/2005/ncx/" version="2005-1" xml:lang="%s">
<head>
<meta content="%s" name="dtb:uid"/>
<meta content="%d" name="dtb:depth"/>
<meta content="mobiunpack.py" name="dtb:generator"/>
<meta content="0" name="dtb:totalPageCount"/>
<meta content="0" name="dtb:maxPageNumber"/>
</head>
<docTitle>
<text>%s</text>
</docTitle>
<navMap>
"""
ncx_footer = """ </navMap>
</ncx>
"""
ncx_entry = """<navPoint id="%s" playOrder="%d">
<navLabel>
<text>%s</text>
</navLabel>
<content src="%s"/>"""
# recursive part
def recursINDX(max_lvl=0, num=0, lvl=0, start=-1, end=-1):
if start > len(indx_data) or end > len(indx_data):
print("Warning: missing INDX child entries", start, end, len(indx_data))
return ""
if DEBUG_NCX:
logger.debug("recursINDX lvl %d from %d to %d" % (lvl, start, end))
xml = ""
if start <= 0:
start = 0
if end <= 0:
end = len(indx_data)
if lvl > max_lvl:
max_lvl = lvl
indent = " " * (2 + lvl)
for i in range(start, end):
e = indx_data[i]
if not e["hlvl"] == lvl:
continue
# open entry
num += 1
link = "%s#filepos%d" % (htmlfile, e["pos"])
print ( 'link {} '.format(link))
tagid = "np_%d" % num
entry = ncx_entry % (tagid, num, e["text"], link)
entry = re.sub(re.compile("^", re.M), indent, entry, 0)
xml += entry + "\n"
# recurs
if e["child1"] >= 0:
xmlrec, max_lvl, num = recursINDX(
max_lvl, num, lvl + 1, e["child1"], e["childn"] + 1
)
xml += xmlrec
# close entry
xml += indent + "</navPoint>\n"
return xml, max_lvl, num
body, max_lvl, num = recursINDX()
header = ncx_header % (lang, ident, max_lvl + 1, title)
ncx = header + body + ncx_footer
if not len(indx_data) == num:
print("Warning: different number of entries in NCX", len(indx_data), num)
return ncx
def writeNCX(self, metadata):
# build the xml
self.isNCX = True
logger.debug("Write ncx")
# htmlname = os.path.basename(self.files.outbase)
# htmlname += '.html'
htmlname = "book1.html"
xml = self.buildNCX(
htmlname,
metadata["Title"][0],
metadata["UniqueID"][0],
metadata.get("Language")[0],
)
# write the ncx file
# ncxname = os.path.join(self.files.mobi7dir, self.files.getInputFileBasename() + '.ncx')
ncxname = os.path.join(self.files.mobi7dir, "toc.ncx")
with open(pathof(ncxname), "wb") as f:
f.write(xml.encode("utf-8"))
def buildK8NCX(self, indx_data, title, ident, lang):
ncx_header = """<?xml version='1.0' encoding='utf-8'?>
<ncx xmlns="http://www.daisy.org/z3986/2005/ncx/" version="2005-1" xml:lang="%s">
<head>
<meta content="%s" name="dtb:uid"/>
<meta content="%d" name="dtb:depth"/>
<meta content="mobiunpack.py" name="dtb:generator"/>
<meta content="0" name="dtb:totalPageCount"/>
<meta content="0" name="dtb:maxPageNumber"/>
</head>
<docTitle>
<text>%s</text>
</docTitle>
<navMap>
"""
ncx_footer = """ </navMap>
</ncx>
"""
ncx_entry = """<navPoint id="%s" playOrder="%d">
<navLabel>
<text>%s</text>
</navLabel>
<content src="%s"/>"""
# recursive part
def recursINDX(max_lvl=0, num=0, lvl=0, start=-1, end=-1):
if start > len(indx_data) or end > len(indx_data):
print("Warning: missing INDX child entries", start, end, len(indx_data))
return ""
if DEBUG_NCX:
logger.debug("recursINDX lvl %d from %d to %d" % (lvl, start, end))
xml = ""
if start <= 0:
start = 0
if end <= 0:
end = len(indx_data)
if lvl > max_lvl:
max_lvl = lvl
indent = " " * (2 + lvl)
for i in range(start, end):
e = indx_data[i]
htmlfile = e["filename"]
desttag = e["idtag"]
if not e["hlvl"] == lvl:
continue
# open entry
num += 1
if desttag == "":
link = "Text/%s" % htmlfile
else:
link = "Text/%s#%s" % (htmlfile, desttag)
tagid = "np_%d" % num
entry = ncx_entry % (tagid, num, e["text"], link)
entry = re.sub(re.compile("^", re.M), indent, entry, 0)
xml += entry + "\n"
# recurs
if e["child1"] >= 0:
xmlrec, max_lvl, num = recursINDX(
max_lvl, num, lvl + 1, e["child1"], e["childn"] + 1
)
xml += xmlrec
# close entry
xml += indent + "</navPoint>\n"
return xml, max_lvl, num
body, max_lvl, num = recursINDX()
header = ncx_header % (lang, ident, max_lvl + 1, title)
ncx = header + body + ncx_footer
if not len(indx_data) == num:
print("Warning: different number of entries in NCX", len(indx_data), num)
return ncx
def writeK8NCX(self, ncx_data, metadata):
# build the xml
self.isNCX = True
logger.debug("Write K8 ncx")
xml = self.buildK8NCX(
ncx_data,
metadata["Title"][0],
metadata["UniqueID"][0],
metadata.get("Language")[0],
)
bname = "toc.ncx"
ncxname = os.path.join(self.files.k8oebps, bname)
with open(pathof(ncxname), "wb") as f:
f.write(xml.encode("utf-8"))

View File

@@ -1 +0,0 @@
]0;IPython: mobimaster/mobi

View File

@@ -1,615 +0,0 @@
<?xml version='1.0' encoding='utf-8'?>
<ncx xmlns="http://www.daisy.org/z3986/2005/ncx/" version="2005-1" xml:lang="zh">
<head>
<meta content="3212343210" name="dtb:uid"/>
<meta content="1" name="dtb:depth"/>
<meta content="mobiunpack.py" name="dtb:generator"/>
<meta content="0" name="dtb:totalPageCount"/>
<meta content="0" name="dtb:maxPageNumber"/>
</head>
<docTitle>
<text>中国游戏风云</text>
</docTitle>
<navMap>
<navPoint id="np_1" playOrder="1">
<navLabel>
<text>编辑手记</text>
</navLabel>
<content src="book1.html#filepos242"/>
</navPoint>
<navPoint id="np_2" playOrder="2">
<navLabel>
<text>引言</text>
</navLabel>
<content src="book1.html#filepos5101"/>
</navPoint>
<navPoint id="np_3" playOrder="3">
<navLabel>
<text>第一章 黑铁时代——早期游戏市场</text>
</navLabel>
<content src="book1.html#filepos7670"/>
</navPoint>
<navPoint id="np_4" playOrder="4">
<navLabel>
<text>一、一切的开始</text>
</navLabel>
<content src="book1.html#filepos7910"/>
</navPoint>
<navPoint id="np_5" playOrder="5">
<navLabel>
<text>二、雅达利冲击</text>
</navLabel>
<content src="book1.html#filepos41949"/>
</navPoint>
<navPoint id="np_6" playOrder="6">
<navLabel>
<text>三、任天堂</text>
</navLabel>
<content src="book1.html#filepos64891"/>
</navPoint>
<navPoint id="np_7" playOrder="7">
<navLabel>
<text>四、世嘉、索尼和微软</text>
</navLabel>
<content src="book1.html#filepos107544"/>
</navPoint>
<navPoint id="np_8" playOrder="8">
<navLabel>
<text>(一)世嘉</text>
</navLabel>
<content src="book1.html#filepos107650"/>
</navPoint>
<navPoint id="np_9" playOrder="9">
<navLabel>
<text>索尼SONY</text>
</navLabel>
<content src="book1.html#filepos122683"/>
</navPoint>
<navPoint id="np_10" playOrder="10">
<navLabel>
<text>(三)微软</text>
</navLabel>
<content src="book1.html#filepos140088"/>
</navPoint>
<navPoint id="np_11" playOrder="11">
<navLabel>
<text>五、中国早期游戏机市场</text>
</navLabel>
<content src="book1.html#filepos159131"/>
</navPoint>
<navPoint id="np_12" playOrder="12">
<navLabel>
<text>六、游戏媒体</text>
</navLabel>
<content src="book1.html#filepos213488"/>
</navPoint>
<navPoint id="np_13" playOrder="13">
<navLabel>
<text>七、电子海洛因、道德与政策</text>
</navLabel>
<content src="book1.html#filepos295572"/>
</navPoint>
<navPoint id="np_14" playOrder="14">
<navLabel>
<text>第二章 青铜时代­——单机游戏</text>
</navLabel>
<content src="book1.html#filepos434517"/>
</navPoint>
<navPoint id="np_15" playOrder="15">
<navLabel>
<text>一、电脑游戏</text>
</navLabel>
<content src="book1.html#filepos434751"/>
</navPoint>
<navPoint id="np_16" playOrder="16">
<navLabel>
<text>二、游戏的开发成本和盗版</text>
</navLabel>
<content src="book1.html#filepos452055"/>
</navPoint>
<navPoint id="np_17" playOrder="17">
<navLabel>
<text>三、从金算盘到前导软件</text>
</navLabel>
<content src="book1.html#filepos637224"/>
</navPoint>
<navPoint id="np_18" playOrder="18">
<navLabel>
<text>四、目标和像素</text>
</navLabel>
<content src="book1.html#filepos637233"/>
</navPoint>
<navPoint id="np_19" playOrder="19">
<navLabel>
<text>七,《仙剑奇侠转》</text>
</navLabel>
<content src="book1.html#filepos637267"/>
</navPoint>
<navPoint id="np_20" playOrder="20">
<navLabel>
<text>八、《轩辕剑》</text>
</navLabel>
<content src="book1.html#filepos701576"/>
</navPoint>
<navPoint id="np_21" playOrder="21">
<navLabel>
<text>九、《剑侠情缘》和西山居</text>
</navLabel>
<content src="book1.html#filepos723358"/>
</navPoint>
<navPoint id="np_22" playOrder="22">
<navLabel>
<text>十、从2D到3D</text>
</navLabel>
<content src="book1.html#filepos755747"/>
</navPoint>
<navPoint id="np_23" playOrder="23">
<navLabel>
<text>十一、中国的符号</text>
</navLabel>
<content src="book1.html#filepos768848"/>
</navPoint>
<navPoint id="np_24" playOrder="24">
<navLabel>
<text>十二、海外游戏公司和育碧中国</text>
</navLabel>
<content src="book1.html#filepos801854"/>
</navPoint>
<navPoint id="np_25" playOrder="25">
<navLabel>
<text>第三章 白银时代­——网络游戏</text>
</navLabel>
<content src="book1.html#filepos857121"/>
</navPoint>
<navPoint id="np_26" playOrder="26">
<navLabel>
<text>一、早期互联网和MUD</text>
</navLabel>
<content src="book1.html#filepos857355"/>
</navPoint>
<navPoint id="np_27" playOrder="27">
<navLabel>
<text>(一)从互联网到网络游戏</text>
</navLabel>
<content src="book1.html#filepos857547"/>
</navPoint>
<navPoint id="np_28" playOrder="28">
<navLabel>
<text>(二)玩泥巴的年代</text>
</navLabel>
<content src="book1.html#filepos869514"/>
</navPoint>
<navPoint id="np_29" playOrder="29">
<navLabel>
<text>(三)图形化的网络游戏</text>
</navLabel>
<content src="book1.html#filepos882446"/>
</navPoint>
<navPoint id="np_30" playOrder="30">
<navLabel>
<text>二、韩国网游</text>
</navLabel>
<content src="book1.html#filepos907645"/>
</navPoint>
<navPoint id="np_31" playOrder="31">
<navLabel>
<text>三、《传奇》和盛大</text>
</navLabel>
<content src="book1.html#filepos931356"/>
</navPoint>
<navPoint id="np_32" playOrder="32">
<navLabel>
<text>四、网吧</text>
</navLabel>
<content src="book1.html#filepos1033086"/>
</navPoint>
<navPoint id="np_33" playOrder="33">
<navLabel>
<text>(一)早期网吧</text>
</navLabel>
<content src="book1.html#filepos1033174"/>
</navPoint>
<navPoint id="np_34" playOrder="34">
<navLabel>
<text>(二)蓝极速</text>
</navLabel>
<content src="book1.html#filepos1045888"/>
</navPoint>
<navPoint id="np_35" playOrder="35">
<navLabel>
<text>五、《石器时代》《魔力宝贝》和《仙境传说》</text>
</navLabel>
<content src="book1.html#filepos1068828"/>
</navPoint>
<navPoint id="np_36" playOrder="36">
<navLabel>
<text>(一)《石器时代》</text>
</navLabel>
<content src="book1.html#filepos1068967"/>
</navPoint>
<navPoint id="np_37" playOrder="37">
<navLabel>
<text>(二)《魔力宝贝》</text>
</navLabel>
<content src="book1.html#filepos1077621"/>
</navPoint>
<navPoint id="np_38" playOrder="38">
<navLabel>
<text>(三)《仙境传说》</text>
</navLabel>
<content src="book1.html#filepos1087882"/>
</navPoint>
<navPoint id="np_39" playOrder="39">
<navLabel>
<text>六、从网易到梦幻西游</text>
</navLabel>
<content src="book1.html#filepos1093194"/>
</navPoint>
<navPoint id="np_40" playOrder="40">
<navLabel>
<text>七、《魔兽世界》和九城</text>
</navLabel>
<content src="book1.html#filepos1136281"/>
</navPoint>
<navPoint id="np_41" playOrder="41">
<navLabel>
<text>八、《征途》和巨人</text>
</navLabel>
<content src="book1.html#filepos1177189"/>
</navPoint>
<navPoint id="np_42" playOrder="42">
<navLabel>
<text>九、新浪与搜狐</text>
</navLabel>
<content src="book1.html#filepos1226969"/>
</navPoint>
<navPoint id="np_43" playOrder="43">
<navLabel>
<text>(一)新浪</text>
</navLabel>
<content src="book1.html#filepos1227082"/>
</navPoint>
<navPoint id="np_44" playOrder="44">
<navLabel>
<text>(二)搜狐</text>
</navLabel>
<content src="book1.html#filepos1256583"/>
</navPoint>
<navPoint id="np_45" playOrder="45">
<navLabel>
<text>十、休闲网游</text>
</navLabel>
<content src="book1.html#filepos1278786"/>
</navPoint>
<navPoint id="np_46" playOrder="46">
<navLabel>
<text>(一)《泡泡堂》《跑跑卡丁车》和世纪天成</text>
</navLabel>
<content src="book1.html#filepos1278880"/>
</navPoint>
<navPoint id="np_47" playOrder="47">
<navLabel>
<text>(二)劲舞团和非主流文化</text>
</navLabel>
<content src="book1.html#filepos1290187"/>
</navPoint>
<navPoint id="np_48" playOrder="48">
<navLabel>
<text>十一、《剑侠情缘网络版》</text>
</navLabel>
<content src="book1.html#filepos1304128"/>
</navPoint>
<navPoint id="np_49" playOrder="49">
<navLabel>
<text>十二、《完美世界》</text>
</navLabel>
<content src="book1.html#filepos1339791"/>
</navPoint>
<navPoint id="np_50" playOrder="50">
<navLabel>
<text>十三、崛起的腾讯</text>
</navLabel>
<content src="book1.html#filepos1358659"/>
</navPoint>
<navPoint id="np_51" playOrder="51">
<navLabel>
<text>十四、《地下城与勇士》《穿越火线》</text>
</navLabel>
<content src="book1.html#filepos1408813"/>
</navPoint>
<navPoint id="np_52" playOrder="52">
<navLabel>
<text>(一)《穿越火线》</text>
</navLabel>
<content src="book1.html#filepos1408956"/>
</navPoint>
<navPoint id="np_53" playOrder="53">
<navLabel>
<text>(二)《地下城与勇士》</text>
</navLabel>
<content src="book1.html#filepos1413533"/>
</navPoint>
<navPoint id="np_54" playOrder="54">
<navLabel>
<text>十五、《英雄联盟》</text>
</navLabel>
<content src="book1.html#filepos1421189"/>
</navPoint>
<navPoint id="np_55" playOrder="55">
<navLabel>
<text>十六、ChinaJoy和游戏展会</text>
</navLabel>
<content src="book1.html#filepos1437839"/>
</navPoint>
<navPoint id="np_56" playOrder="56">
<navLabel>
<text>十七、盗号、外挂、私服和游戏内的法制</text>
</navLabel>
<content src="book1.html#filepos1473271"/>
</navPoint>
<navPoint id="np_57" playOrder="57">
<navLabel>
<text>(一)盗号</text>
</navLabel>
<content src="book1.html#filepos1474282"/>
</navPoint>
<navPoint id="np_58" playOrder="58">
<navLabel>
<text>(二)私服</text>
</navLabel>
<content src="book1.html#filepos1482598"/>
</navPoint>
<navPoint id="np_59" playOrder="59">
<navLabel>
<text>(三)外挂</text>
</navLabel>
<content src="book1.html#filepos1498037"/>
</navPoint>
<navPoint id="np_60" playOrder="60">
<navLabel>
<text>十八、游戏公会和工作室</text>
</navLabel>
<content src="book1.html#filepos1517059"/>
</navPoint>
<navPoint id="np_61" playOrder="61">
<navLabel>
<text>第四章 黄金时代——网页游戏和手机游戏</text>
</navLabel>
<content src="book1.html#filepos1564823"/>
</navPoint>
<navPoint id="np_62" playOrder="62">
<navLabel>
<text>一、网页游戏</text>
</navLabel>
<content src="book1.html#filepos1565072"/>
</navPoint>
<navPoint id="np_63" playOrder="63">
<navLabel>
<text>二、手机游戏</text>
</navLabel>
<content src="book1.html#filepos1598448"/>
</navPoint>
<navPoint id="np_64" playOrder="64">
<navLabel>
<text>三、iPhone的新智能手机时代</text>
</navLabel>
<content src="book1.html#filepos1610120"/>
</navPoint>
<navPoint id="np_65" playOrder="65">
<navLabel>
<text>四、安卓的冲击</text>
</navLabel>
<content src="book1.html#filepos1620952"/>
</navPoint>
<navPoint id="np_66" playOrder="66">
<navLabel>
<text>五、其他早期成功者们</text>
</navLabel>
<content src="book1.html#filepos1627255"/>
</navPoint>
<navPoint id="np_67" playOrder="67">
<navLabel>
<text>六.刷榜和不稳定的市场</text>
</navLabel>
<content src="book1.html#filepos1633064"/>
</navPoint>
<navPoint id="np_68" playOrder="68">
<navLabel>
<text>七、CocoaChina和触控</text>
</navLabel>
<content src="book1.html#filepos1646293"/>
</navPoint>
<navPoint id="np_69" playOrder="69">
<navLabel>
<text>八、从卓越到莉莉丝</text>
</navLabel>
<content src="book1.html#filepos1666739"/>
</navPoint>
<navPoint id="np_70" playOrder="70">
<navLabel>
<text>《我叫MT</text>
</navLabel>
<content src="book1.html#filepos1666842"/>
</navPoint>
<navPoint id="np_71" playOrder="71">
<navLabel>
<text>(二)《刀塔传奇》</text>
</navLabel>
<content src="book1.html#filepos1681746"/>
</navPoint>
<navPoint id="np_72" playOrder="72">
<navLabel>
<text>九、棋牌游戏</text>
</navLabel>
<content src="book1.html#filepos1697749"/>
</navPoint>
<navPoint id="np_73" playOrder="73">
<navLabel>
<text>从联众到QQ游戏</text>
</navLabel>
<content src="book1.html#filepos1697843"/>
</navPoint>
<navPoint id="np_74" playOrder="74">
<navLabel>
<text>(二)大棋牌游戏市场</text>
</navLabel>
<content src="book1.html#filepos1707452"/>
</navPoint>
<navPoint id="np_75" playOrder="75">
<navLabel>
<text>十、《阴阳师》</text>
</navLabel>
<content src="book1.html#filepos1715631"/>
</navPoint>
<navPoint id="np_76" playOrder="76">
<navLabel>
<text>十一、微信游戏和《王者荣耀》</text>
</navLabel>
<content src="book1.html#filepos1728191"/>
</navPoint>
<navPoint id="np_77" playOrder="77">
<navLabel>
<text>(一)微信</text>
</navLabel>
<content src="book1.html#filepos1728309"/>
</navPoint>
<navPoint id="np_78" playOrder="78">
<navLabel>
<text>(二)微信游戏和《王者荣耀》</text>
</navLabel>
<content src="book1.html#filepos1735031"/>
</navPoint>
<navPoint id="np_79" playOrder="79">
<navLabel>
<text>十二、"吃鸡"游戏</text>
</navLabel>
<content src="book1.html#filepos1754265"/>
</navPoint>
<navPoint id="np_80" playOrder="80">
<navLabel>
<text>第五章 未来世界</text>
</navLabel>
<content src="book1.html#filepos1777521"/>
</navPoint>
<navPoint id="np_81" playOrder="81">
<navLabel>
<text>一、游戏出海</text>
</navLabel>
<content src="book1.html#filepos1777737"/>
</navPoint>
<navPoint id="np_82" playOrder="82">
<navLabel>
<text>二、电子竞技</text>
</navLabel>
<content src="book1.html#filepos1802026"/>
</navPoint>
<navPoint id="np_83" playOrder="83">
<navLabel>
<text>(一)黎明之前</text>
</navLabel>
<content src="book1.html#filepos1802121"/>
</navPoint>
<navPoint id="np_84" playOrder="84">
<navLabel>
<text>三、进入中国</text>
</navLabel>
<content src="book1.html#filepos1818699"/>
</navPoint>
<navPoint id="np_85" playOrder="85">
<navLabel>
<text>四、DotA和LOL的大时代</text>
</navLabel>
<content src="book1.html#filepos1862190"/>
</navPoint>
<navPoint id="np_86" playOrder="86">
<navLabel>
<text>五、电子竞技的未来</text>
</navLabel>
<content src="book1.html#filepos1868817"/>
</navPoint>
<navPoint id="np_87" playOrder="87">
<navLabel>
<text>六、游戏直播</text>
</navLabel>
<content src="book1.html#filepos1881557"/>
</navPoint>
<navPoint id="np_88" playOrder="88">
<navLabel>
<text>七、中国主机游戏市场</text>
</navLabel>
<content src="book1.html#filepos1913489"/>
</navPoint>
<navPoint id="np_89" playOrder="89">
<navLabel>
<text>八、资本在游戏行业扮演着什么样的角色</text>
</navLabel>
<content src="book1.html#filepos1944247"/>
</navPoint>
<navPoint id="np_90" playOrder="90">
<navLabel>
<text>(一)什么是风险投资?</text>
</navLabel>
<content src="book1.html#filepos1944377"/>
</navPoint>
<navPoint id="np_91" playOrder="91">
<navLabel>
<text>(二)什么是上市?</text>
</navLabel>
<content src="book1.html#filepos1953838"/>
</navPoint>
<navPoint id="np_92" playOrder="92">
<navLabel>
<text>九、中国游戏业的未来在哪里</text>
</navLabel>
<content src="book1.html#filepos1963997"/>
</navPoint>
<navPoint id="np_93" playOrder="93">
<navLabel>
<text>(一)中国游戏产业取得了什么成绩?</text>
</navLabel>
<content src="book1.html#filepos1964112"/>
</navPoint>
<navPoint id="np_94" playOrder="94">
<navLabel>
<text>(二)做什么游戏?</text>
</navLabel>
<content src="book1.html#filepos1977747"/>
</navPoint>
<navPoint id="np_95" playOrder="95">
<navLabel>
<text>(三)付费模式</text>
</navLabel>
<content src="book1.html#filepos1979680"/>
</navPoint>
<navPoint id="np_96" playOrder="96">
<navLabel>
<text>独立游戏和3A游戏</text>
</navLabel>
<content src="book1.html#filepos1981760"/>
</navPoint>
<navPoint id="np_97" playOrder="97">
<navLabel>
<text>VR和AR市场</text>
</navLabel>
<content src="book1.html#filepos1987064"/>
</navPoint>
<navPoint id="np_98" playOrder="98">
<navLabel>
<text>(六)会有雅达利危机吗?</text>
</navLabel>
<content src="book1.html#filepos1995037"/>
</navPoint>
<navPoint id="np_99" playOrder="99">
<navLabel>
<text>十、我们做错了什么</text>
</navLabel>
<content src="book1.html#filepos1999686"/>
</navPoint>
<navPoint id="np_100" playOrder="100">
<navLabel>
<text>后记</text>
</navLabel>
<content src="book1.html#filepos2039983"/>
</navPoint>
</navMap>
</ncx>

View File

@@ -1,627 +0,0 @@
<?xml version='1.0' encoding='utf-8'?>
<ncx xmlns="http://www.daisy.org/z3986/2005/ncx/" version="2005-1" xml:lang="zh">
<head>
<meta content="3212343210" name="dtb:uid"/>
<meta content="3" name="dtb:depth"/>
<meta content="mobiunpack.py" name="dtb:generator"/>
<meta content="0" name="dtb:totalPageCount"/>
<meta content="0" name="dtb:maxPageNumber"/>
</head>
<docTitle>
<text>中国游戏风云</text>
</docTitle>
<navMap>
<navPoint id="np_1" playOrder="1">
<navLabel>
<text>编辑手记</text>
</navLabel>
<content src="Text/part0001.xhtml#calibre_pb_0"/>
</navPoint>
<navPoint id="np_2" playOrder="2">
<navLabel>
<text>引言</text>
</navLabel>
<content src="Text/part0002.xhtml#calibre_pb_0"/>
</navPoint>
<navPoint id="np_3" playOrder="3">
<navLabel>
<text>第一章 黑铁时代——早期游戏市场</text>
</navLabel>
<content src="Text/part0003.xhtml#calibre_pb_0"/>
<navPoint id="np_4" playOrder="4">
<navLabel>
<text>一、一切的开始</text>
</navLabel>
<content src="Text/part0004.xhtml#aid-3Q281"/>
</navPoint>
<navPoint id="np_5" playOrder="5">
<navLabel>
<text>二、雅达利冲击</text>
</navLabel>
<content src="Text/part0004.xhtml#sigil_toc_id_1"/>
</navPoint>
<navPoint id="np_6" playOrder="6">
<navLabel>
<text>三、任天堂</text>
</navLabel>
<content src="Text/part0004.xhtml#sigil_toc_id_2"/>
</navPoint>
<navPoint id="np_7" playOrder="7">
<navLabel>
<text>四、世嘉、索尼和微软</text>
</navLabel>
<content src="Text/part0004.xhtml#sigil_toc_id_3"/>
<navPoint id="np_8" playOrder="8">
<navLabel>
<text>(一)世嘉</text>
</navLabel>
<content src="Text/part0004.xhtml#sigil_toc_id_4"/>
</navPoint>
<navPoint id="np_9" playOrder="9">
<navLabel>
<text>索尼SONY</text>
</navLabel>
<content src="Text/part0005.xhtml#sigil_toc_id_5"/>
</navPoint>
<navPoint id="np_10" playOrder="10">
<navLabel>
<text>(三)微软</text>
</navLabel>
<content src="Text/part0005.xhtml#sigil_toc_id_6"/>
</navPoint>
</navPoint>
<navPoint id="np_11" playOrder="11">
<navLabel>
<text>五、中国早期游戏机市场</text>
</navLabel>
<content src="Text/part0005.xhtml#sigil_toc_id_7"/>
</navPoint>
<navPoint id="np_12" playOrder="12">
<navLabel>
<text>六、游戏媒体</text>
</navLabel>
<content src="Text/part0006.xhtml#sigil_toc_id_8"/>
</navPoint>
<navPoint id="np_13" playOrder="13">
<navLabel>
<text>七、电子海洛因、道德与政策</text>
</navLabel>
<content src="Text/part0006.xhtml#bookmark91"/>
</navPoint>
</navPoint>
<navPoint id="np_14" playOrder="14">
<navLabel>
<text>第二章 青铜时代­——单机游戏</text>
</navLabel>
<content src="Text/part0007.xhtml#calibre_pb_0"/>
<navPoint id="np_15" playOrder="15">
<navLabel>
<text>一、电脑游戏</text>
</navLabel>
<content src="Text/part0008.xhtml#aid-7K4G1"/>
</navPoint>
<navPoint id="np_16" playOrder="16">
<navLabel>
<text>二、游戏的开发成本和盗版</text>
</navLabel>
<content src="Text/part0008.xhtml#sigil_toc_id_9"/>
</navPoint>
<navPoint id="np_17" playOrder="17">
<navLabel>
<text>三、从金算盘到前导软件</text>
</navLabel>
<content src="Text/part0008.xhtml#sigil_toc_id_10"/>
</navPoint>
<navPoint id="np_18" playOrder="18">
<navLabel>
<text>四、目标和像素</text>
</navLabel>
<content src="Text/part0008.xhtml#sigil_toc_id_11"/>
</navPoint>
<navPoint id="np_19" playOrder="19">
<navLabel>
<text>五、一些不容忽视的国产单机游戏公司</text>
</navLabel>
<content src="Text/part0008.xhtml#sigil_toc_id_12"/>
</navPoint>
<navPoint id="np_20" playOrder="20">
<navLabel>
<text>六、来自宝岛的游戏</text>
</navLabel>
<content src="Text/part0008.xhtml#sigil_toc_id_13"/>
</navPoint>
<navPoint id="np_21" playOrder="21">
<navLabel>
<text>七,《仙剑奇侠转》</text>
</navLabel>
<content src="Text/part0009.xhtml#bookmark192"/>
</navPoint>
<navPoint id="np_22" playOrder="22">
<navLabel>
<text>八、《轩辕剑》</text>
</navLabel>
<content src="Text/part0009.xhtml#bookmark194"/>
</navPoint>
<navPoint id="np_23" playOrder="23">
<navLabel>
<text>九、《剑侠情缘》和西山居</text>
</navLabel>
<content src="Text/part0009.xhtml#sigil_toc_id_14"/>
</navPoint>
<navPoint id="np_24" playOrder="24">
<navLabel>
<text>十、从2D到3D</text>
</navLabel>
<content src="Text/part0009.xhtml#sigil_toc_id_15"/>
</navPoint>
<navPoint id="np_25" playOrder="25">
<navLabel>
<text>十一、中国的符号</text>
</navLabel>
<content src="Text/part0009.xhtml#bookmark203"/>
</navPoint>
<navPoint id="np_26" playOrder="26">
<navLabel>
<text>十二、海外游戏公司和育碧中国</text>
</navLabel>
<content src="Text/part0009.xhtml#sigil_toc_id_16"/>
</navPoint>
</navPoint>
<navPoint id="np_27" playOrder="27">
<navLabel>
<text>第三章 白银时代­——网络游戏</text>
</navLabel>
<content src="Text/part0010.xhtml#calibre_pb_0"/>
<navPoint id="np_28" playOrder="28">
<navLabel>
<text>一、早期互联网和MUD</text>
</navLabel>
<content src="Text/part0011.xhtml#aid-AFM61"/>
<navPoint id="np_29" playOrder="29">
<navLabel>
<text>(一)从互联网到网络游戏</text>
</navLabel>
<content src="Text/part0011.xhtml#sigil_toc_id_17"/>
</navPoint>
<navPoint id="np_30" playOrder="30">
<navLabel>
<text>(二)玩泥巴的年代</text>
</navLabel>
<content src="Text/part0011.xhtml#sigil_toc_id_18"/>
</navPoint>
<navPoint id="np_31" playOrder="31">
<navLabel>
<text>(三)图形化的网络游戏</text>
</navLabel>
<content src="Text/part0011.xhtml#sigil_toc_id_19"/>
</navPoint>
</navPoint>
<navPoint id="np_32" playOrder="32">
<navLabel>
<text>二、韩国网游</text>
</navLabel>
<content src="Text/part0011.xhtml#sigil_toc_id_20"/>
</navPoint>
<navPoint id="np_33" playOrder="33">
<navLabel>
<text>三、《传奇》和盛大</text>
</navLabel>
<content src="Text/part0011.xhtml#sigil_toc_id_21"/>
</navPoint>
<navPoint id="np_34" playOrder="34">
<navLabel>
<text>四、网吧</text>
</navLabel>
<content src="Text/part0011.xhtml#sigil_toc_id_22"/>
<navPoint id="np_35" playOrder="35">
<navLabel>
<text>(一)早期网吧</text>
</navLabel>
<content src="Text/part0011.xhtml#sigil_toc_id_23"/>
</navPoint>
<navPoint id="np_36" playOrder="36">
<navLabel>
<text>(二)蓝极速</text>
</navLabel>
<content src="Text/part0012.xhtml#sigil_toc_id_24"/>
</navPoint>
</navPoint>
<navPoint id="np_37" playOrder="37">
<navLabel>
<text>五、《石器时代》《魔力宝贝》和《仙境传说》</text>
</navLabel>
<content src="Text/part0012.xhtml#sigil_toc_id_25"/>
<navPoint id="np_38" playOrder="38">
<navLabel>
<text>(一)《石器时代》</text>
</navLabel>
<content src="Text/part0012.xhtml#sigil_toc_id_26"/>
</navPoint>
<navPoint id="np_39" playOrder="39">
<navLabel>
<text>(二)《魔力宝贝》</text>
</navLabel>
<content src="Text/part0012.xhtml#sigil_toc_id_27"/>
</navPoint>
<navPoint id="np_40" playOrder="40">
<navLabel>
<text>(三)《仙境传说》</text>
</navLabel>
<content src="Text/part0012.xhtml#sigil_toc_id_28"/>
</navPoint>
</navPoint>
<navPoint id="np_41" playOrder="41">
<navLabel>
<text>六、从网易到梦幻西游</text>
</navLabel>
<content src="Text/part0012.xhtml#sigil_toc_id_29"/>
</navPoint>
<navPoint id="np_42" playOrder="42">
<navLabel>
<text>七、《魔兽世界》和九城</text>
</navLabel>
<content src="Text/part0012.xhtml#sigil_toc_id_30"/>
</navPoint>
<navPoint id="np_43" playOrder="43">
<navLabel>
<text>八、《征途》和巨人</text>
</navLabel>
<content src="Text/part0012.xhtml#sigil_toc_id_31"/>
</navPoint>
<navPoint id="np_44" playOrder="44">
<navLabel>
<text>九、新浪与搜狐</text>
</navLabel>
<content src="Text/part0012.xhtml#sigil_toc_id_32"/>
<navPoint id="np_45" playOrder="45">
<navLabel>
<text>(一)新浪</text>
</navLabel>
<content src="Text/part0013.xhtml#sigil_toc_id_33"/>
</navPoint>
<navPoint id="np_46" playOrder="46">
<navLabel>
<text>(二)搜狐</text>
</navLabel>
<content src="Text/part0013.xhtml#sigil_toc_id_34"/>
</navPoint>
</navPoint>
<navPoint id="np_47" playOrder="47">
<navLabel>
<text>十、休闲网游</text>
</navLabel>
<content src="Text/part0013.xhtml#bookmark328"/>
<navPoint id="np_48" playOrder="48">
<navLabel>
<text>(一)《泡泡堂》《跑跑卡丁车》和世纪天成</text>
</navLabel>
<content src="Text/part0013.xhtml#sigil_toc_id_35"/>
</navPoint>
<navPoint id="np_49" playOrder="49">
<navLabel>
<text>(二)劲舞团和非主流文化</text>
</navLabel>
<content src="Text/part0013.xhtml#sigil_toc_id_36"/>
</navPoint>
</navPoint>
<navPoint id="np_50" playOrder="50">
<navLabel>
<text>十一、《剑侠情缘网络版》</text>
</navLabel>
<content src="Text/part0013.xhtml#sigil_toc_id_37"/>
</navPoint>
<navPoint id="np_51" playOrder="51">
<navLabel>
<text>十二、《完美世界》</text>
</navLabel>
<content src="Text/part0013.xhtml#bookmark333"/>
</navPoint>
<navPoint id="np_52" playOrder="52">
<navLabel>
<text>十三、崛起的腾讯</text>
</navLabel>
<content src="Text/part0013.xhtml#sigil_toc_id_38"/>
</navPoint>
<navPoint id="np_53" playOrder="53">
<navLabel>
<text>十四、《地下城与勇士》《穿越火线》</text>
</navLabel>
<content src="Text/part0013.xhtml#sigil_toc_id_39"/>
<navPoint id="np_54" playOrder="54">
<navLabel>
<text>(一)《穿越火线》</text>
</navLabel>
<content src="Text/part0014.xhtml#sigil_toc_id_40"/>
</navPoint>
<navPoint id="np_55" playOrder="55">
<navLabel>
<text>(二)《地下城与勇士》</text>
</navLabel>
<content src="Text/part0014.xhtml#sigil_toc_id_41"/>
</navPoint>
</navPoint>
<navPoint id="np_56" playOrder="56">
<navLabel>
<text>十五、《英雄联盟》</text>
</navLabel>
<content src="Text/part0014.xhtml#bookmark343"/>
</navPoint>
<navPoint id="np_57" playOrder="57">
<navLabel>
<text>十六、ChinaJoy和游戏展会</text>
</navLabel>
<content src="Text/part0014.xhtml#sigil_toc_id_42"/>
</navPoint>
<navPoint id="np_58" playOrder="58">
<navLabel>
<text>十七、盗号、外挂、私服和游戏内的法制</text>
</navLabel>
<content src="Text/part0014.xhtml#sigil_toc_id_43"/>
<navPoint id="np_59" playOrder="59">
<navLabel>
<text>(一)盗号</text>
</navLabel>
<content src="Text/part0014.xhtml#sigil_toc_id_44"/>
</navPoint>
<navPoint id="np_60" playOrder="60">
<navLabel>
<text>(二)私服</text>
</navLabel>
<content src="Text/part0014.xhtml#sigil_toc_id_45"/>
</navPoint>
<navPoint id="np_61" playOrder="61">
<navLabel>
<text>(三)外挂</text>
</navLabel>
<content src="Text/part0014.xhtml#bookmark355"/>
</navPoint>
</navPoint>
<navPoint id="np_62" playOrder="62">
<navLabel>
<text>十八、游戏公会和工作室</text>
</navLabel>
<content src="Text/part0014.xhtml#sigil_toc_id_46"/>
</navPoint>
</navPoint>
<navPoint id="np_63" playOrder="63">
<navLabel>
<text>第四章 黄金时代——网页游戏和手机游戏</text>
</navLabel>
<content src="Text/part0015.xhtml#calibre_pb_0"/>
<navPoint id="np_64" playOrder="64">
<navLabel>
<text>一、网页游戏</text>
</navLabel>
<content src="Text/part0016.xhtml#aid-F8901"/>
</navPoint>
<navPoint id="np_65" playOrder="65">
<navLabel>
<text>二、手机游戏</text>
</navLabel>
<content src="Text/part0016.xhtml#sigil_toc_id_47"/>
</navPoint>
<navPoint id="np_66" playOrder="66">
<navLabel>
<text>三、iPhone的新智能手机时代</text>
</navLabel>
<content src="Text/part0016.xhtml#sigil_toc_id_48"/>
</navPoint>
<navPoint id="np_67" playOrder="67">
<navLabel>
<text>四、安卓的冲击</text>
</navLabel>
<content src="Text/part0016.xhtml#sigil_toc_id_49"/>
</navPoint>
<navPoint id="np_68" playOrder="68">
<navLabel>
<text>五、其他早期成功者们</text>
</navLabel>
<content src="Text/part0016.xhtml#sigil_toc_id_50"/>
</navPoint>
<navPoint id="np_69" playOrder="69">
<navLabel>
<text>六.刷榜和不稳定的市场</text>
</navLabel>
<content src="Text/part0016.xhtml#bookmark407"/>
</navPoint>
<navPoint id="np_70" playOrder="70">
<navLabel>
<text>七、CocoaChina和触控</text>
</navLabel>
<content src="Text/part0016.xhtml#sigil_toc_id_51"/>
</navPoint>
<navPoint id="np_71" playOrder="71">
<navLabel>
<text>八、从卓越到莉莉丝</text>
</navLabel>
<content src="Text/part0016.xhtml#sigil_toc_id_52"/>
<navPoint id="np_72" playOrder="72">
<navLabel>
<text>《我叫MT</text>
</navLabel>
<content src="Text/part0016.xhtml#sigil_toc_id_53"/>
</navPoint>
<navPoint id="np_73" playOrder="73">
<navLabel>
<text>(二)《刀塔传奇》</text>
</navLabel>
<content src="Text/part0016.xhtml#sigil_toc_id_54"/>
</navPoint>
</navPoint>
<navPoint id="np_74" playOrder="74">
<navLabel>
<text>九、棋牌游戏</text>
</navLabel>
<content src="Text/part0016.xhtml#sigil_toc_id_55"/>
<navPoint id="np_75" playOrder="75">
<navLabel>
<text>从联众到QQ游戏</text>
</navLabel>
<content src="Text/part0016.xhtml#sigil_toc_id_56"/>
</navPoint>
<navPoint id="np_76" playOrder="76">
<navLabel>
<text>(二)大棋牌游戏市场</text>
</navLabel>
<content src="Text/part0016.xhtml#sigil_toc_id_57"/>
</navPoint>
</navPoint>
<navPoint id="np_77" playOrder="77">
<navLabel>
<text>十、《阴阳师》</text>
</navLabel>
<content src="Text/part0016.xhtml#sigil_toc_id_58"/>
</navPoint>
<navPoint id="np_78" playOrder="78">
<navLabel>
<text>十一、微信游戏和《王者荣耀》</text>
</navLabel>
<content src="Text/part0016.xhtml#sigil_toc_id_59"/>
<navPoint id="np_79" playOrder="79">
<navLabel>
<text>(一)微信</text>
</navLabel>
<content src="Text/part0016.xhtml#sigil_toc_id_60"/>
</navPoint>
<navPoint id="np_80" playOrder="80">
<navLabel>
<text>(二)微信游戏和《王者荣耀》</text>
</navLabel>
<content src="Text/part0016.xhtml#sigil_toc_id_61"/>
</navPoint>
</navPoint>
<navPoint id="np_81" playOrder="81">
<navLabel>
<text>十二、"吃鸡"游戏</text>
</navLabel>
<content src="Text/part0016.xhtml#sigil_toc_id_62"/>
</navPoint>
</navPoint>
<navPoint id="np_82" playOrder="82">
<navLabel>
<text>第五章 未来世界</text>
</navLabel>
<content src="Text/part0017.xhtml#calibre_pb_0"/>
<navPoint id="np_83" playOrder="83">
<navLabel>
<text>一、游戏出海</text>
</navLabel>
<content src="Text/part0018.xhtml#aid-H5A41"/>
</navPoint>
<navPoint id="np_84" playOrder="84">
<navLabel>
<text>二、电子竞技</text>
</navLabel>
<content src="Text/part0018.xhtml#sigil_toc_id_63"/>
<navPoint id="np_85" playOrder="85">
<navLabel>
<text>(一)黎明之前</text>
</navLabel>
<content src="Text/part0018.xhtml#sigil_toc_id_64"/>
</navPoint>
</navPoint>
<navPoint id="np_86" playOrder="86">
<navLabel>
<text>三、进入中国</text>
</navLabel>
<content src="Text/part0018.xhtml#sigil_toc_id_65"/>
</navPoint>
<navPoint id="np_87" playOrder="87">
<navLabel>
<text>四、DotA和LOL的大时代</text>
</navLabel>
<content src="Text/part0018.xhtml#sigil_toc_id_66"/>
</navPoint>
<navPoint id="np_88" playOrder="88">
<navLabel>
<text>五、电子竞技的未来</text>
</navLabel>
<content src="Text/part0018.xhtml#sigil_toc_id_67"/>
</navPoint>
<navPoint id="np_89" playOrder="89">
<navLabel>
<text>六、游戏直播</text>
</navLabel>
<content src="Text/part0018.xhtml#sigil_toc_id_68"/>
</navPoint>
<navPoint id="np_90" playOrder="90">
<navLabel>
<text>七、中国主机游戏市场</text>
</navLabel>
<content src="Text/part0018.xhtml#sigil_toc_id_69"/>
</navPoint>
<navPoint id="np_91" playOrder="91">
<navLabel>
<text>八、资本在游戏行业扮演着什么样的角色</text>
</navLabel>
<content src="Text/part0018.xhtml#bookmark498"/>
<navPoint id="np_92" playOrder="92">
<navLabel>
<text>(一)什么是风险投资?</text>
</navLabel>
<content src="Text/part0018.xhtml#bookmark500"/>
</navPoint>
<navPoint id="np_93" playOrder="93">
<navLabel>
<text>(二)什么是上市?</text>
</navLabel>
<content src="Text/part0018.xhtml#bookmark501"/>
</navPoint>
</navPoint>
<navPoint id="np_94" playOrder="94">
<navLabel>
<text>九、中国游戏业的未来在哪里</text>
</navLabel>
<content src="Text/part0018.xhtml#bookmark504"/>
<navPoint id="np_95" playOrder="95">
<navLabel>
<text>(一)中国游戏产业取得了什么成绩?</text>
</navLabel>
<content src="Text/part0018.xhtml#sigil_toc_id_70"/>
</navPoint>
<navPoint id="np_96" playOrder="96">
<navLabel>
<text>(二)做什么游戏?</text>
</navLabel>
<content src="Text/part0018.xhtml#sigil_toc_id_71"/>
</navPoint>
<navPoint id="np_97" playOrder="97">
<navLabel>
<text>(三)付费模式</text>
</navLabel>
<content src="Text/part0018.xhtml#bookmark505"/>
</navPoint>
<navPoint id="np_98" playOrder="98">
<navLabel>
<text>独立游戏和3A游戏</text>
</navLabel>
<content src="Text/part0018.xhtml#bookmark506"/>
</navPoint>
<navPoint id="np_99" playOrder="99">
<navLabel>
<text>VR和AR市场</text>
</navLabel>
<content src="Text/part0018.xhtml#sigil_toc_id_72"/>
</navPoint>
<navPoint id="np_100" playOrder="100">
<navLabel>
<text>(六)会有雅达利危机吗?</text>
</navLabel>
<content src="Text/part0018.xhtml#sigil_toc_id_73"/>
</navPoint>
</navPoint>
<navPoint id="np_101" playOrder="101">
<navLabel>
<text>十、我们做错了什么</text>
</navLabel>
<content src="Text/part0018.xhtml#sigil_toc_id_74"/>
</navPoint>
</navPoint>
<navPoint id="np_102" playOrder="102">
<navLabel>
<text>后记</text>
</navLabel>
<content src="Text/part0019.xhtml#bookmark514"/>
</navPoint>
</navMap>
</ncx>

File diff suppressed because one or more lines are too long

218
mobiparse/mobi/extract.py Executable file
View File

@@ -0,0 +1,218 @@
# -*- coding: utf-8 -*-
import shutil
import json
import os
from loguru import logger
import tempfile
from os.path import basename, splitext, exists, join
from mobi.kindleunpack import unpackBook
from mobi.makencx import extractNcx
def extract(infile):
"""Extract mobi file and return path to epub file"""
tempdir = tempfile.mkdtemp(prefix="mobiex")
if hasattr(infile, "fileno"):
tempname = next(tempfile._get_candidate_names()) + ".mobi"
pos = infile.tell()
infile.seek(0)
with open(join(tempdir, tempname), "wb") as outfile:
shutil.copyfileobj(infile, outfile)
infile.seek(pos)
infile = join(tempdir, tempname)
logger.debug("file: %s" % infile)
fname_in = basename(infile)
base, ext = splitext(fname_in)
fname_out_epub = base + ".epub"
fname_out_html = "book.html"
fname_out_pdf = base + ".001.pdf"
unpackBook(infile, tempdir, epubver="A")
epub_filepath = join(tempdir, "mobi8", fname_out_epub)
html_filepath = join(tempdir, "mobi7", fname_out_html)
pdf_filepath = join(tempdir, fname_out_pdf)
if exists(epub_filepath):
return tempdir, epub_filepath
elif exists(html_filepath):
return tempdir, html_filepath
elif exists(pdf_filepath):
return tempdir, pdf_filepath
raise ValueError("Coud not extract from %s" % infile)
def extracttest(infile):
"""Extract mobi file and return path to epub file"""
tempdir = './t/'
if hasattr(infile, "fileno"):
tempname = next(tempfile._get_candidate_names()) + ".mobi"
pos = infile.tell()
infile.seek(0)
with open(join(tempdir, tempname), "wb") as outfile:
shutil.copyfileobj(infile, outfile)
infile.seek(pos)
infile = join(tempdir, tempname)
# tempname 8x2vf7yv.mobi pos 0 infile ./t/8x2vf7yv.mobi
print('tempname {} pos {} infile {}'.format(tempname,pos,infile))
logger.debug("file: %s" % infile)
fname_in = basename(infile)
base, ext = splitext(fname_in)
fname_out_epub = base + ".epub"
fname_out_html = "book.html"
fname_out_pdf = base + ".001.pdf"
# infile ./t/8x2vf7yv.mobi
unpackBook(infile, tempdir, epubver="A")
epub_filepath = join(tempdir, "mobi8", fname_out_epub)
html_filepath = join(tempdir, "mobi7", fname_out_html)
pdf_filepath = join(tempdir, fname_out_pdf)
# CGDBG
#epub_filepath ./t/mobi8/p302tbwb.epub html_filepath ./t/mobi7/book.html pdf_filepath ./t/p302tbwb.001.pdf
print('epub_filepath {} html_filepath {} pdf_filepath {}'.format( epub_filepath, html_filepath, pdf_filepath))
if exists(epub_filepath):
return tempdir, epub_filepath
elif exists(html_filepath):
return tempdir, html_filepath
elif exists(pdf_filepath):
return tempdir, pdf_filepath
raise ValueError("Coud not extract from %s" % infile)
## CG test extractNcx
def extract_ncx_test():
#infile = "./tests/youxi.mobi"
#infile = "./tests/xiaodao.mobi"
filelst = [
'youxi.mobi',
'xiaodao.mobi',
'laocan.azw3',
# 'shikong.kfx',
'shisu.azw',
'ETF全球投资指南一个账户投资全球。告诉你用美股ETF投什么、怎么投低门槛、低成本地进行全球化投资和配_JYT5RZBTKMUUJCV2XZ6RWZFNJWAS3KWP.azw3',
'正義_ 一場思辨之旅_SVQL2PQHADT6UEVYYMJLNLP3TNVZZ2PO.azw3',
'赘婿_IFYXK7EVMAJZU6SRDI4G3PF6KG5AA3CF.azw',
'熊逸·佛学50讲_MW5FG7LWUA3G5ZSRJHOI6YNS4E6EC3AP.azw',
'哲学·科学·常识_Q7IU43GSXSQ3TZULYN46U5DSTJBOSVTW.azw3',
'理想国2020年豆瓣高分文学作品集【理想国2020年度最受好评新书】_H5LB5WWKBT55NDVJ44TGWNP3YWUXMGAN.azw',
'大问题_ 简明哲学导论_3MGHFPCGYUPS5OX6PLI2U2ZN2D4QY6IP.azw',
'利维坦_BQNVQ3PLMU5NABEUEYPESXWK4KEVXH2V.azw',
#'马克斯·韦伯作品集套装6册【现代社会学奠基人余英时、苏国勋推荐译本 理想国出品】_LUVR3MEUTXTZLMGRQS7RBEDQ32QB2WDZ.azw',
'物种起源 (译林人文精选)_EFRUCMHSILFZ7IY75OF6KU3FXKG5DYQS.azw',
'公式之美 中国好书人类最美的23个公式_JWP4OH34GQTHTM4UB5KVTDDPMV5Q45XW.azw',
'經濟學人104個大解惑從紙鈔面額、廣告祕辛到航空公司如何節省成本的全面揭密_RSN23YIUQOGLI5XMNP4UUWZFFBKW7SWT.azw',
'快思慢想_6RD4VKANWTU2EIIS5ZQSW4H2WAVW6BKS.azw3',
'老残游记_GYDUNWUDXOSL6GX376HXF6Y5BZB4BYWK.azw3',
'美的历程_HRFLXR3SWA7YIMUHHBMOHKIFCXTKWDEN.azw',
'世俗时代_JAJCAPFHKMBTWHQC3Z3M23MQHVM4LD5H.azw',
'先知之後_OVMTC2SMQGT6WR5BEPB3NLIHPEXAPOZ2.azw',
'股市稳赚_TKUOH7HY4AFL6MHGDXOA2JTJMDQMJ2M2.azw',
'货币野史_TNDZWSPMBH3OU3GA4OONJOOS5N3RML46.azw',
'黄金时代_UECZKDFEYBBCXD7VEGKUF3JAIZCNQTLD.azw',
'哲学小引_ZIPCDHPBDNDXGPGFMHVMWTW2T43H4H33.azw',
'危险的关系(译文名著精选)_LCIX4CJDXKBN44DFWQC6BNQP5T4QUJGQ.azw3',
'生命是什么-活细胞的物理观_KHTK74YI2ZCNNLTDNO42O5TEUCFY4OAE.azw',
'时间的边缘_FTWBORVACPNFZEHJGDPP3F5G3ZTP2API.azw3',
'苏菲的世界_GY2VU27R6NLR5DYLSK2X3SGMDOS6OEHA.azw',
'责任的重负_IOEVP74VFX7HI7CZLHNVDYUSBR5SKWHP.azw',
'非常潜力股_RSO2TPJMR4Z5GRVVK27M6CZIOKXDOGFA.azw',
'超级聊天学_为中国人量身定制的口才实操指南会聊天瞬间提升你的魅力指数和任何人都能说上话和任何人_UJSIR4LXOYUXNN3VKNM2VEJAZWPWXIA5.azw3',
'世说新语精读 (汉语言文学原典精读系列)_EIQTMTBSOBUBAZTIO76QY3UE5DHG7QUX.azw',
'打开周濂的100堂西方哲学课一部有营养、有态度读得懂、读得动的西方哲学史_NBLLIRUDZVFARGUMVTO3IYM7RZFWAHF5.azw',
'中国游戏风云_45BZOYKQWCVIMPV5J5TUQB3A4WMSXG6Y.azw3',
'顾准历史笔记_664YSYONYO3WYLR7KN4EHLAVN5AZYJPJ.azw',
'克拉拉与太阳_AHT6ZF3TVFNTKQLLAZJHBPWVMXHXP6HC.azw',
'现代汉英词典_B00771V9HS.azw',
'现代汉语词典_B00AKJGTAQ.azw',
'香帅财富报告_US63WJUWKWW2Y7GPKCIDMRVUEYTQVOKM.azw',
'送你一颗子弹_YIFYW7SIWRQULQ5I7OHSFWW5GWJQPRXF.azw',
'从沸腾到癫狂_泡沫背后的中国房地产真相_Z67UZLBWFW7E7RXRCMSBQK2X2TQJMV54.azw',
'诸子百家闪耀时 (豆瓣“大神”林欣浩首部中国哲学史力作)_Z65JN5SBZKB5CXWP4QEJ5N36WBJK7LYG.azw',
'增广贤文(精)--中华经典名著全本全注全译 (中华书局)_55WRYKJTRRUSR3F7PUHSCT7VCYLNXAO5.azw',
'吃货的孤单心事_4TSS34PIM3LDOE7STPZLPVI5Z2NJ63ZA.azw3',
'专业团队的管理_CZQZGKOZ2O4B5657CBJX62YTDTHGFTHI.azw3',
'《新青年》文选_D63BJHTSQMXJOD3WZMITH5MCXPPX4TQO.azw3',
'中国改革三步走_YAIFAT7KHQG3FKXYDBGDAODOQB3IXREP.azw3',
'手把手教你读财报2——18节课看透银行业_N2ULAPFBPTYYROEZR6OXSFRZHWGVPP47.azw',
'伯罗奔尼撒战争史_7IG7PYJEFQCQZKJFADJQPB63WOJZ457K.azw',
'股市投资致富之道_DRFDHRKUZOGBOQANCZ7WCXQPO4IFXLZ3.azw',
'中国人的性格历程_F7WWWMHTDUNPAJPQKPMRQQBUVFVWVO2J.azw',
'股市投资致富之道_QE5QXSGVXZIU6YKQ37ILICN3Y4KMOHFB.azw',
'手把手教你读财报_财报是用来排除企业的_BIO354K2A7W6AKDRG672GCTOW256C7W3.azw',
'不可思议的自然对数 (探秘数学常数)_RXHNPMVRRSAJGPFS4EZMEW6YRIOAUJHL.azw',
'关键选择【帮助起底27个赚钱的逻辑经济下行趋势下的个人财富增长方案】_XX73ZPD6RPCZSB3XBKBTZZSC5RKQDXJO.azw',
'中国法律与中国社会_SH3O32FVYFABLOLPVCAQEG2YFWSLTZKY.azw',
'印度漂浮的次大陆_YGTGYKH3CAVXF5QZIORNOU4HY3JWUFT2.azw',
'关于那个人的备忘录_ZCIQC6KSVBPKAIOJJSASQ4T7CUSC23IO.azw',
'尼采哲学经典套装共5册 (李敖力荐台湾经典译本)_OQ6CLDRDV34ZPOF2ZLK6CJTMMDJMLVEW.azw',
'刘擎西方现代思想讲义_2X4PDLIAHHBVF2JV4WS6SSWMEU6WCC2W.azw3',
'故事是这个世界的解药_YIRJ7ONGJKHJF4VHEGAHXCRAZRUQWDC5.azw',
'哲学家们都干了些什么_2015年全新修订版_7YZCO42RPEELUVMTCWMXV7VAFJHNUBH3.azw',
'韩炳哲作品系列套装共9册_XQLLBYAIEHIDC6DDKPUSDUCXA5JJDV7E.azw3',
'異常流行幻象與群眾瘋狂_54WCNGW254RB2VX2QAQOQJCTOIS5UDVZ.azw',
'通胀来了你准备好了吗_6EY3XVPBUCU3S2Z6GASBJ3ZFIYG7XAPV.azw3',
'第二十二条军规纪念版_XHGD4NJJO7IJJLI6NZQVR7GWGIPZASKU.azw',
'反智:不願說理的人是偏執 不會說理的人是愚蠢 不敢說理的人是奴隸_FQGEEYA535SOIWBGTZMINNYUUUVOHGCO.azw',
'中国货币史校订版豆瓣9.5分好评如潮_5QDPZ4BJCNFCQEW6OOTFT5WGGFEKJVCM.azw',
'海洋与权力一部新文明史_DZARAFK3BF3JM2Y6G275TNEHS3YFIY63.azw',
'蘇東坡新傳上下合併冊_MQJ52QLZFG7GJIQXLGO6EOOEWDUPOTGC.azw',
'刷新重新发现商业与未来_SJJ2ZXTZYRIYOTA6PRLQNRBILPM6TN3O.azw',
'禅宗是什么胡适谈禅说佛_UV6UYZCLIBT7T5XOIZ3XEHLGYP524UUU.azw',
'可塑的我自我发展心理学的35堂必修课自我发展心理学的35堂必修课_LE5ZTKZITLXRBQVHN2GPNXODGRRZHE7C.azw3',
'诺贝尔奖经济学合集套装共5册经济学领域的集大成作品_TD4FJVAQB35P77SCIG3VGERLQZJKG27G.azw',
'费雪论成长股获利投资大师80年投资致富的选股方法 (深受普通投资者欢迎与推荐的投资经典巴菲特之师、“近_MXG3UMBD2MUQN3EEY7VC545U567VQC76.azw',
'阿含经校注全九册【豆瓣9.6高分推荐线装书局出品一套书读通佛教“根本佛法”阿含经专家、苏州西园_4Q3JWY3QBCLYZDBOUFU76KUYXNTXESBB.azw',
'伤花怒放摇滚的被缚与抗争_SGVGLBLRNURM5MCXKFKBRLUZS4HLAQOY.azw',
'区块链通往资产数字化之路_SHFSC7TLUVLQBYANOLNKJJTWNMHNNVZ5.azw',
'历史的轨迹——二千年教会史_ZIMUOQ5JGFYGF4SRKFPGX5MEWMC6DPX2.azw',
'深蓝帝国英国海军的兴衰全2册【《星期日泰晤士报》年度最佳畅销书】 (甲骨文系列)_JRZSCWPDFXTNZRTBCR7HQ6BMXKLJ7QYG.azw3',
'如何提升专注力手把手教你用7项改变打造10倍速效率人生_S3NJU6MR5WP3ECFWFQ4NYWHYEB6P5RSZ.azw',
'性欲和性行为一种批判理论的99条断想全2册【舞蹈家金星、社会学家李银河推荐继弗洛伊德、福柯之后的_UGCIUTVYKZYV6PDVDQPBM2JCDV7SX6VP.azw',
'后疫情时代的全球经济与世界秩序(傅莹、蔡昉、江小娟、李扬、余永定、郑永年、迟福林、赵汀阳等20位学者合力_75MHOUFWOONZQOP5CY7E7HMI4P5SZPLT.azw3',
'何为良好生活行之于途而应于心_A2ETZLWN3OSZAVWDJOJBB3LTDSFLMHBC.azw',
'万万没想到用理工科思维理解世界_57F2POLFMUHUIDHE7KH6Z2Q732VQ5UX3.azw3',
'徐远的投资课投资原则与实战方法_7ESQ4POTRSIH4JOOHBL7PSWQ6JT4PLEZ.azw',
'爆款短视频如何频繁产出刷屏视频_EWJQBSGVTM2OXQKC5M77MKLFNWGL25CT.azw3',
'思维的艺术如何像哲学家一样思考_PSNIXLNDMEXX7T7K5J5NWRDIOFXY3XPX.azw',
'牛津通识读本佛学概论中文版_TUEO6SWCHMURQIGO3JKQRMZT5DWSYNYP.azw',
'利益、制度与信息:国内政治与国际关系 (东方编译所译丛)_ESVTYWPTPGMVNMJJW7T5YP2LOQKFSHHY.azw',
'哲学的故事【让深奥的哲学立刻生动起来!上市首年连续再版22次迅速译成18种语言掀起全球哲学热潮】_QCOIVA3QQN2BMYFTZQIXLGD45E2CSUNC.azw',
'千年贸易战争史——贸易冲突与大国兴衰_ESA55ZHIJ6KVQY3OTCM3N5SB6BHDYKPC.azw3',
'投资至简从原点出发构建价值投资体系_GSKBIPYDNJJOAZUMNH4T3PZ2EHYYJPE4.azw3',
'新金融秩序如何应对不确定的金融风险2013年诺贝尔经济学奖得主罗伯特•希勒著作_YO7GZEODTNSUX4JJR5SRL7MOWP4PZFJ4.azw',
'超越“街角发言者”表达权的边缘与中心_P7SJECOJBQOYBJ5D4ZCSTPIFD2ZCMM6C.azw',
'米开朗琪罗与教皇的天花板甲骨文系列_RIR7YAXJJSRRSGEPUU47ULOHDCAKQW7M.azw',
'诗人十四个:十四位古代诗人和一位现代闯入者 一场始于1600年前的诗歌沙龙_UDDD6AF6HYA4V3SRY6KBN6M677757CCI.azw',
'叔本华心灵咒语:请优雅地拥抱这个苦难的世界(获得独立的人格做内心强大的自己孤独而伟大的哲学家道破_AZLKLSE2R3KAK5S6WXRYHPTPZLCX4RSO.azw',
'世界观现代人必须要懂的科学哲学和科学史原书第3版_WI6LHG2VGA6QITWLONOU4KOGNXKGB5EB.azw',
'野兽绅士单身男士必备撩妹宝典。坏男孩创始人、教父Tango终极力作汇集超人气恋爱社区「坏男孩」中超经典_UZKJVFNZXM2C5GHYLRDJABRLKTHZYBFH.azw',
'怪医笔记【薄世宁、李治中(菠萝)、姬十三、刘润、于莺 真诚力荐期待值100%的医学题材小说胸外科医生亲_FXMMP37MN4PRL2TAELQYDDMACRTECSZQ.azw',
'不拘一格网飞的自由与责任工作法网飞官方图书创始人兼CEO哈斯廷斯重磅作品。一家市值超2000亿美元全球_3XOUEBICN4XWPCC5FESAMRAQSALMLABE.azw',
'雅典帝国的覆亡耶鲁大学教授为你讲述伯罗奔尼撒战争的后十年_HU7HIAFMRETK2JTCDVWRDNY35GSHSQGI.azw',
'无规则游戏阿富汗屡被中断的历史本书获“美国北加州图书奖”提名_SXDQBXUOP5W36IAZFWHXOALY7VS7WCKG.azw',
'无限记忆力(如何在两周内记住更多知识,改善注意力,并培养出过目不忘的记忆力。 +附21种实用的记忆力提升_5HCR7CSSQ32XICMV3ZQ5UY4N7AMFDT3S.azw',
'我是谁,或什么:一部心与自我的辩证奇想集(关于“我”的终极哲学问题,嬉皮年代的思想群峰 本书可能烧掉你_C4HD4VEU4LC54IY4A7I43CK3PONLMNSJ.azw3',
'高效论证美国大学最实用的逻辑训练课全美大学批判性思维经典教材美国哲学学会重磅推荐_FDA4AB6DURIL5RT7OZEXM76I2PUW7YCP.azw',
'一把刀千个字茅盾文学奖获奖作家王安忆全新长篇登顶《收获》长篇小说榜人民文学出版社倾力打造_ALQY4IH3LLNYF4KDK7LVXJGOWTYBH4PP.azw',
'透明社会以哲学小品文的简练和犀利照察当今社会情状和人类心灵洞穿数字媒体时代的群体狂欢和孤独个体_2YTTCLR4QTNFVCWKXZ7GIHEDSNQL6THE.azw',
'不变与万变葛剑雄说国史中国当代历史学家、复旦大学教授葛剑雄重磅新作全面勾勒中国历史发展的源与流_IOMBENXF5TGWX7F3BJLL322UTV5FDQTZ.azw',
'下沉年代白宫之乱的根本原因是什么拜登上任后美国何去何从通俗版《美国陷阱》面对面访谈民主党前幕_KGL4UJC74AOO3HEMV6LRCMRZ5A6YPQGT.azw',
'一生的读书计划这一版有实质性的修订和扩充最突出的变化是推荐的阅读材料的来源范围已经扩展到整个世界_SFGZNMVNLL3RE36GAERWSTDVEWRBZ4MG.azw',
'三岛由纪夫典藏作品九部两次入围诺贝尔奖的文学大师三岛由纪夫代表作日本文学翻译家陈德文先生译本人_TBNZC7F5EQ5YEKOODF6VMW2I2LBZRD4W.azw',
]
for fn in filelst:
mhdict = extractNcx(os.path.join('./tests',fn))
print('process file {} \n {}'.format(fn,
json.dumps(mhdict, indent=4, sort_keys=True, ensure_ascii=False)))
if __name__ == "__main__":
#print(extracttest("../tests/demo.mobi"))
#extract_ncx_test("../tests/demo.mobi")
pass

View File

@@ -574,7 +574,6 @@ def processMobi8(
logger.debug("Processing ncx / toc ")
ncx = ncxExtract(mh, files)
ncx_data = ncx.parseNCX()
print('ncx_data K8 {}'.format(ncx_data))
# extend the ncx data with filenames and proper internal idtags
@@ -652,8 +651,10 @@ def processMobi8(
uuid = opf.writeOPF(bool(obfuscate_data))
if opf.hasNCX():
# CGDBG
# Create a toc.ncx.
ncx.writeK8NCX(ncx_data, metadata)
# ncx.writeK8NCX(ncx_data, metadata)
pass
if opf.hasNAV():
# Create a navigation document.
nav = NAVProcessor(files)
@@ -680,7 +681,8 @@ def processMobi7(mh, metadata, sect, files, rscnames):
ncx_data = ncx.parseNCX()
print('ncx_data K7 {}'.format(ncx_data))
ncx.writeNCX(metadata)
# CGDBG write ncx information to toc.ncx
# ncx.writeNCX(metadata)
positionMap = {}
@@ -1194,3 +1196,4 @@ def main(argv=unicode_argv()):
if __name__ == "__main__":
sys.exit(main())

97
mobiparse/mobi/makencx.py Executable file
View File

@@ -0,0 +1,97 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
from loguru import logger
from collections import defaultdict
from .compatibility_utils import PY2, binary_type, utf8_str, unicode_str
from .compatibility_utils import unicode_argv, add_cp65001_codec
K8_BOUNDARY = b"BOUNDARY"
""" The section data that divides K8 mobi ebooks. """
class unpackException(Exception):
pass
# import the kindleunpack support libraries
from .unpack_structure import fileNames
from .mobi_sectioner import Sectionizer
from .mobi_header import MobiHeader
from .mobi_ncx import ncxExtract
# input mobi file path
# output ncx dict
def extractNcx(infile):
infile = unicode_str(infile)
mhdict = defaultdict(dict)
# process the PalmDoc database header and verify it is a mobi
sect = Sectionizer(infile)
if sect.ident != b"BOOKMOBI" and sect.ident != b"TEXtREAd":
raise unpackException("Invalid file format")
logger.debug( "dumppalmheader ...")
sect.dumppalmheader()
# CGDBG
print('infile {} '.format(infile))
print('sect.dumpsectionsinfo() {}'.format(sect.dumpsectionsinfo()))
print('sect.dumppalmheader() {}'.format(sect.dumppalmheader()))
# scan sections to see if this is a compound mobi file (K8 format)
# and build a list of all mobi headers to process.
mhlst = []
# CG mobi header
mh = MobiHeader(sect, 0)
metadata = mh.getMetaData()
# if this is a mobi8-only file hasK8 here will be true
mhlst.append(mh)
K8Boundary = -1
if mh.isK8():
logger.debug("Unpacking a KF8 book...")
hasK8 = True
else:
# CGDBG
# This is either a Mobipocket 7 or earlier, or a combi M7/KF8
# Find out which
hasK8 = False
for i in range(len(sect.sectionoffsets) - 1):
before, after = sect.sectionoffsets[i : i + 2]
if (after - before) == 8:
data = sect.loadSection(i)
if data == K8_BOUNDARY:
sect.setsectiondescription(i, "Mobi/KF8 Boundary Section")
mh = MobiHeader(sect, i + 1)
hasK8 = True # K8
mhlst.append(mh)
K8Boundary = i
break
# hasK8 header information include K8
if hasK8:
logger.debug( "Unpacking a Combination M{0:d}/KF8 book...".format(mh.version))
else:
logger.debug("Unpacking a Mobipocket {0:d} book...".format(mh.version))
# loop for process ncx and write to json with filename - booname.ncx.json
for tmh in mhlst:
# CG
# process the toc ncx
# ncx map keys: name, pos, len, noffs, text, hlvl, kind, pos_fid, parent, child1, childn, num
logger.debug("Processing ncx / toc ")
print('hasK8 {} tmh.isK8 {}'.format(hasK8, tmh.isK8()))
ncx = ncxExtract(tmh)
ncx_data = ncx.parseNCX()
# check the mobi header information is K8 or K7
kn = 'k8ncx' if tmh.isK8() else 'k7ncx'
mhdict[kn] = ncx_data
return mhdict

132
mobiparse/mobi/mobi_ncx.py Executable file
View File

@@ -0,0 +1,132 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
from __future__ import unicode_literals, division, absolute_import, print_function
import os
from .unipath import pathof
from loguru import logger
import re
import json
# note: re requites the pattern to be the exact same type as the data to be searched in python3
# but u"" is not allowed for the pattern itself only b""
'''
NCX (Navigation Control for XML applications) is a generalized navigation definition DTD for application
to Digital Talking Books, eBooks, and general web content models.
This DTD is an XML application that layers navigation functionality on top of SMIL 2.0 content.
The NCX defines a navigation path/model that may be applied upon existing publications,
without modification of the existing publication source, so long as the navigation targets within
the source publication can be directly referenced via a URI.
http://www.daisy.org/z3986/2005/ncx-2005-1.dtd
'''
from .mobi_utils import toBase32
from .mobi_index import MobiIndex
DEBUG_NCX = False
class ncxExtract:
def __init__(self, mh):
self.mh = mh
self.sect = self.mh.sect
self.isNCX = False
self.mi = MobiIndex(self.sect)
self.ncxidx = self.mh.ncxidx
self.indx_data = None
def parseNCX(self):
indx_data = []
tag_fieldname_map = {
1: ["pos", 0],
2: ["len", 0],
3: ["noffs", 0],
4: ["hlvl", 0],
5: ["koffs", 0],
6: ["pos_fid", 0],
21: ["parent", 0],
22: ["child1", 0],
23: ["childn", 0],
}
if self.ncxidx != 0xFFFFFFFF:
outtbl, ctoc_text = self.mi.getIndexData(self.ncxidx, "NCX")
if DEBUG_NCX:
logger.debug("ctoc_text {}".format(ctoc_text))
logger.debug("outtbl {}".format(outtbl))
num = 0
for [text, tagMap] in outtbl:
tmp = {
"name": text.decode("utf-8"),
"pos": -1,
"len": 0,
"noffs": -1,
"text": "Unknown Text",
"hlvl": -1,
"kind": "Unknown Kind",
"pos_fid": None,
"parent": -1,
"child1": -1,
"childn": -1,
"num": num,
}
for tag in tag_fieldname_map:
[fieldname, i] = tag_fieldname_map[tag]
if tag in tagMap:
fieldvalue = tagMap[tag][i]
if tag == 6:
pos_fid = toBase32(fieldvalue, 4).decode("utf-8")
fieldvalue2 = tagMap[tag][i + 1]
pos_off = toBase32(fieldvalue2, 10).decode("utf-8")
fieldvalue = "kindle:pos:fid:%s:off:%s" % (pos_fid, pos_off)
tmp[fieldname] = fieldvalue
if tag == 3:
toctext = ctoc_text.get(fieldvalue, "Unknown Text")
toctext = toctext.decode(self.mh.codec)
tmp["text"] = toctext
if tag == 5:
kindtext = ctoc_text.get(fieldvalue, "Unknown Kind")
kindtext = kindtext.decode(self.mh.codec)
tmp["kind"] = kindtext
indx_data.append(tmp)
# CGDBG
'''
record number: 3
name: 03
position 461377 length: 465358 => position/150 = real page number
text: 第二章 青铜时代­——单机游戏
kind: Unknown Kind
heading level: 0 => level of section
parent: -1 => record number of previous level of section
first child: 15 last child: 26 => range of record number of next level section
pos_fid is kindle:pos:fid:0023:off:0000000000
'''
if DEBUG_NCX:
print("record number: ", num)
print(
"name: ", tmp["name"],
)
print("position", tmp["pos"], " length: ", tmp["len"])
print("text: ", tmp["text"])
print("kind: ", tmp["kind"])
print("heading level: ", tmp["hlvl"])
print("parent:", tmp["parent"])
print(
"first child: ", tmp["child1"], " last child: ", tmp["childn"]
)
print("pos_fid is ", tmp["pos_fid"])
print("\n\n")
num += 1
self.indx_data = indx_data
# {'name': '00', 'pos': 167, 'len': 24798, 'noffs': 0, 'text': '版权信息', 'hlvl': 0, 'kind': 'Unknown Kind', 'pos_fid': None, 'parent': -1, 'child1': -1, 'childn': -1, 'num': 0}
# {'name': '0B', 'pos': 67932, 'len': 3274, 'noffs': 236, 'text': '8.希罗多德', 'hlvl': 0, 'kind': 'Unknown Kind', 'pos_fid': None, 'parent': -1, 'child1': -1, 'childn': -1, 'num': 11}
#print('indx_data {}'.format(json.dumps(indx_data, indent=4, sort_keys=True, ensure_ascii=False)))
return indx_data

21
mobiparse/mobi/x Normal file
View File

@@ -0,0 +1,21 @@
# KF8 (Mobi 8)
if mh.isK8():
processMobi8(
mh,
metadata,
sect,
files,
rscnames,
pagemapproc,
k8resc,
obfuscate_data,
apnxfile,
epubver,
)
# Old Mobi (Mobi 7)
elif not k8only:
processMobi7(mh, metadata, sect, files, rscnames)
# CGDBG
print('k8only {} mh.isK8() {}'.format(k8only, mh.isK8()))

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
mobiparse/t/dqumrrbk.mobi Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

View File

Before

Width:  |  Height:  |  Size: 83 KiB

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 47 KiB

View File

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

View File

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 9.3 KiB

View File

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 82 KiB

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 57 KiB

View File

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View File

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 55 KiB

View File

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 57 KiB

View File

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 59 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Some files were not shown because too many files have changed in this diff Show More