縦書きEPUBをPDFに変換する

## はじめに
こちらは縦書きのEPUBをPDFに変換したときの備忘録です。
変換ソフトやwebアプリ等で変換してもうまくいかず、
自分でやったところうまくいったので記事にしました。
Pythonを使ってますが、やってること自体は簡単なので別言語でもできると思います。

## 必要なもの
- Chrome
- EPUBファイル
- Python
     - bs4 0.0.1
     - lxml 4.9.1
     - pypdf 3.3.0

## EPUBの展開
EPUBの実態は`zip`ファイルなので展開できます。
記事で使用するデモ用のepubは**夏目漱石**作の**こころ**使用しています。理由はフリーで手に入るからです。(ファイル名は`kokoro.epub`)
早速作業開始します。

`kokoro.epub`の拡張子を`.zip`に変更し展開します。
展開結果は以下のようになります。
```
kokoro
│  content.opf
│  cover.jpeg
│  mimetype
│  page_styles.css
│  stylesheet.css
│  titlepage.xhtml
│  toc.ncx
│
├─META-INF
│      container.xml
│
└─text
        part0000.html
        part0001.html
        part0002.html
        part0003.html
        part0004_split_000.html
        part0004_split_001.html
        part0005.html
```

## htmlファイルの結合
htmlファイルに各文章が入っているため1つのファイルに結合します。
以下`python`スクリプトを`kokoro`ファルダに配置して実行します。
```
import glob
from bs4 import BeautifulSoup

texts=[]
    
for file in glob.glob('./text/*.html'):
    with open(file,encoding='utf-8')as f:
        soup = BeautifulSoup(f.read(),"lxml")
    body=soup.find('body')
    texts.append(''.join([str(content) for content in body.contents]))
    texts.append('<div style="page-break-after: always;"></div>')#改ページ
with open('body.txt','w',encoding='utf-8') as f:
    f.writelines(texts)
```
やっていることは、各htmlファイルからbody部を抜き出して、１つのファイルにまとめていきます。
その時、印刷時の改ページの設定もしておきます。

次に`text`ファルダにある適当なhtmlをコピーして`index.html`という名前に変更します。
そして、htmlの`body`部を作成したものに置き換えます。
(スクリプト作ってもよかったですが、コピペでもたいして時間変わらないので作りませんでした。すみません。)

```変更前.html
<?xml version='1.0' encoding='utf-8'?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops" xml:lang="ja">
  <head>
    <link class="horizontal" rel="alternate stylesheet" href="../styles/a00773_h.css" type="text/css" title="横組"/>
    <title>こころ</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  <link rel="stylesheet" type="text/css" href="../stylesheet.css"/>
<link rel="stylesheet" type="text/css" href="../page_styles.css"/>
</head>
<body class="newpagestyle">
  <div class="align_left"><p class="class1"><span class="size">こころ</span><br class="class1"/></p></div>
  <div class="align_right"><div class="class2"><p class="calibre">夏目漱石</p>
  </div>
  </div>
</body></html>
```

```変更後.html
<?xml version='1.0' encoding='utf-8'?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops" xml:lang="ja">
  <head>
    <link class="horizontal" rel="alternate stylesheet" href="../styles/a00773_h.css" type="text/css" title="横組"/>
    <title>こころ</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  <link rel="stylesheet" type="text/css" href="../stylesheet.css"/>
<link rel="stylesheet" type="text/css" href="../page_styles.css"/>
</head>
<body class="newpagestyle">
  <div class="align_left"><p class="class1"><span class="size">こころ</span><br class="class1"/></p></div>
  <p class="class1"><br class="class1"/></p>
  </div>
  <div style="page-break-after: always;"></div>
</body></html>
```
```
text
        index.html
        part0000.html
        part0001.html
        part0002.html
        part0003.html
        part0004_split_000.html
        part0004_split_001.html
        part0005.html
```

## リンク先の変更
現時点で`index.html`をブラウザで開いてみます。
横スクロールで見れる小説になっていることが確認できます。
ここで1つ問題があります。目次等でリンクが張ってある場合もともとあったhtmlファイルに
飛んでしまいます。これはPDFにしたときにちゃんと動かないのでこれを修正します。
リンクいらない方はこの項目はしなくても構いません。
`index.html`をエディタで開いて`href=`属性で`xxxx.html#xxxx`となっているところを`#xxxx`になるように修正していきます。
(これもスクリプト作ってません。大体リンク張っている位置は固まってるのですぐ終わります。)
修正後、再度`index.html`をブラウザで開いてみます。そして、リンクが`index.html`内で移動していることを確認します。

## PDFで保存
できた`index.html`をブラウザで`ctrl+p`の印刷画面で`PDFに保存`でPDFにします。余白等のパラメータは自分の好みで設定してください。
保存名は`body.pdf`にします。

## 表紙の作成
`titlepage.xhtml`か`cover.jpeg`のどちらかを印刷画面で`PDFに保存`します。
`titlepage.xhtml`は`style`タグが邪魔して変な大きさになる時があるので調整してください。
保存名は`cover.pdf`にします。

## 表紙と本体の結合
表紙と本体を結合します。`pypdf`を使って結合しているだけです。
Web上にあるPDF結合ツールを使っても構いません。
```
from pypdf import PdfWriter

merger = PdfWriter()

for pdf in ["cover.pdf", "body.pdf"]:
    merger.append(pdf)

merger.write("kokoro.pdf")
merger.close()
```

完成です。

## 最後に
今回は縦書きEPUBのPDF変換を行いました。
みなさまのお役に立てれば幸いです。
今回手抜きで作らなかった部分やこうした方がいい等のコメントがありましたら教えてください。