見出し画像

Pandocで作ったePub3ファイルから制御コードを削除して綺麗なePub3フォーマットに一発変換する方法(Pythonスクリプトあり)

 前回は圧縮時に規定のファイル順で保存する方法がわからなかったのでマニュアル操作だったところをいろいろ調べてやりようが分かった今回はそれを盛り込みました。一発変換は正義。

 おさらいですがPandocでepub3を作成する際の問題点は、特定のファイルに制御コードが紛れ込む、というものです。

 このため「epub3を解凍→ファイルを修正→epub3に圧縮」という手順が必要です。ただし、epub3に圧縮時に規定のフォーマット(mimetypeファイルをzipファイルの先頭に置く)にする必要があります。(※ここが分からなかった)

 ※制御コードが含まれていてもKDPであれば独自形式に変換する際に無視されるのですが楽天Koboでは登録時にエラーとなります。私は楽天Koboで電子書籍を登録しているのでこれは少々困ります。

 ……で、なんだかんだでできたコードは以下の通りです。
 実行にはPython3.10以上が必要です。
 実行しepub3のフルパスを指定すると同じフォルダに「ファイル名+_output.epub」で出力されます。
 そのほか詳細はコメントに記載。

import os
import shutil
import zipfile

def clean_control_characters(directory):
    for subdir, dirs, files in os.walk(directory):
        for file in files:
            print(file)
            if file.endswith('.xhtml'):
                filepath = subdir + os.sep + file
                with open(filepath, 'r', encoding='utf-8') as f:
                    content = f.read()
                # 制御文字を削除
                cleaned_content = ''.join(ch for ch in content if ch.isprintable() or ch in '\n\t')
                with open(filepath, 'w', encoding='utf-8') as f:
                    f.write(cleaned_content)

def create_epub(input_file, output_file, work_dir):
    # 入力ファイルを解凍
    with zipfile.ZipFile(input_file, 'r') as zip_ref:
        zip_ref.extractall(work_dir)
    # 制御文字を削除
    clean_control_characters(work_dir)
    # mimetypeファイルを先頭に圧縮
    with zipfile.ZipFile(output_file, 'w') as epub:
        epub.write(os.path.join(work_dir, 'mimetype'), 'mimetype', compress_type=zipfile.ZIP_STORED)
        # 他のファイルを圧縮
        for folder, subfolders, files in os.walk(work_dir):
            for file in files:
                if file != 'mimetype':
                    epub.write(os.path.join(folder, file), os.path.relpath(os.path.join(folder,file), work_dir), compress_type=zipfile.ZIP_DEFLATED)
    # 作業ディレクトリを削除
    shutil.rmtree(work_dir)

# 入力ファイルと出力ファイル
input_file = input("ファイルパスを入力してください:").replace("\\","/").replace('"','')
output_file = os.path.join(os.path.dirname(input_file),os.path.basename(input_file).split(".")[0]+'_output.epub')
work_dir = os.path.join(os.path.dirname(input_file), 'tmp_work')

# ePubファイルを作成
create_epub(input_file, output_file, work_dir)

以上。

この記事が気に入ったらサポートをしてみませんか?