|
#!/usr/bin/env python |
|
# -*- coding: utf-8 -*- |
|
|
|
### |
|
### 转换空之文库(轻国阅读Android) sln 文档格式为 txt |
|
### Script to convert Sora.SLNovel to txt |
|
### |
|
|
|
import os |
|
import sys |
|
import shutil |
|
import zipfile |
|
import json |
|
|
|
#LINE_SPACE = "\t" |
|
LINE_SPACE = " " |
|
|
|
DEFAULT_WORKSPACE = "WorkSpace" |
|
|
|
def load_content(name): |
|
""" 读取正文内容 """ |
|
for line in file(name): |
|
# txt模式,跳过图片行 {{I}} |
|
if line.find('{{I}}') == 0: continue |
|
# 替换每行前的占位符 {{T}} |
|
yield line.strip().replace('{{T}}', LINE_SPACE) + '\n' |
|
|
|
def conv_SLNovel_sln(src, extract_path): |
|
""" 转换'空之文库'的sln格式为txt """ |
|
# 展开zip包到目标路径 |
|
zipfile.ZipFile(src).extractall(extract_path) |
|
|
|
# 读取 Package 文件中的章节信息并排序 |
|
package = json.JSONDecoder().decode(open('%s%sPackage' % (extract_path, os.path.sep), 'r').read()) |
|
chapter_list = sorted(package, key=lambda obj: obj['Index']) |
|
|
|
# 读取章节中的书籍和卷ID |
|
out_filename = "sln%s_%s.txt" % (chapter_list[0]['BookID'], chapter_list[0]['VolumeID']) |
|
output = open(out_filename, 'w') |
|
|
|
# 输出章节标题,并导出内容 |
|
for chapter in chapter_list: |
|
# {u'ChapterID': 30174, u'Name': u'\u5e8f\u7ae0', u'VolumeID': 3876, u'BookID': 1127, u'Index': 0} |
|
chapter_id = chapter['ChapterID'] |
|
chapter_name = chapter['Name'].encode('utf-8') |
|
# 输出标题 |
|
output.write("%s\n\n" % chapter_name) |
|
|
|
# 输出章节内容 |
|
contents = load_content('%s%sContent%s%s' % (extract_path, os.path.sep, os.path.sep, chapter_id)) |
|
output.writelines(contents) |
|
|
|
output.write("\n") |
|
|
|
output.close() |
|
return out_filename |
|
|
|
def main(): |
|
if (len(sys.argv) < 2): |
|
print "Usage: python %s 3876.sln" % sys.argv[0] |
|
print " (locate: /sdcard/Android/file/com.Sora.SLNovel/DBData/<BookID>/<VolumeID>.sln)" |
|
return |
|
|
|
if os.path.exists(DEFAULT_WORKSPACE): |
|
shutil.rmtree(DEFAULT_WORKSPACE) |
|
|
|
out_file = conv_SLNovel_sln(sys.argv[1], DEFAULT_WORKSPACE) |
|
shutil.rmtree(DEFAULT_WORKSPACE) |
|
|
|
print "conv to %s success!" % out_file |
|
|
|
main() |