Jupyter Notebookの.ipynbファイルを印刷プレビューと同じレイアウトでPDFに一括変換する方法

# はじめに
```jupyter Notebook```はデータサイエンスのプロジェクトや研究で頻繁に使用されるツールです。

このノートブックを```PDF```に変換する必要がある場面も多く、そのためのいくつかの方法が提案されています。

しかし、これらの方法にはそれぞれ課題があります。

この記事では、それらの方法と課題を概観し、新しい効率的な変換方法を紹介します。
 **特に、複数の```.ipynb```ファイルを一括で変換する場合や、数式を含むノートブックを変換する場合に本記事の方法は役立ちます!!**

# これまでの変換方法とその課題
## 1. jupyter nbconvert コマンド
### 方法
```nbconvert```を使用して、```Jupyter Notebook```を直接```PDF```に変換します。
この方法は、```.ipynb``` ファイルを中間の ```.tex``` ファイルに変換し、次にこの ```.tex``` ファイルを```PDF```に変換するという手順で動作します。

### 課題
- **LaTeXの依存**
この変換方法は```LaTeX```を介して行われるため、システムに```LaTeX```が正しくインストールされている必要があります。
- **パッケージの問題**
一部の```LaTeX```パッケージが不足しているか、または特定の設定が適切でない場合、変換中にエラーが発生することがあります。
- **レイアウトの崩壊**
日本語の場合、タイトルや日付などのレイアウトがずれてしまうことがあります

## 2. wkhtmltopdf
### 方法
```wkhtmltopdf```は、```Webkit```エンジンをベースにしたコマンドラインツールで、```HTML```ドキュメントを```PDF```に変換します。
このツールは、Webページのレンダリング能力を活用して高品質の```PDF```を生成することができます。

### 課題
- **JavaScriptの互換性**
```MathJax```や他の```JavaScript```ベースのレンダリングツールとの互換性に問題があるため、 **数式が正しくレンダリングされません** 


## 3. ブラウザの印刷機能
### 方法
ほとんどのモダンブラウザには、```Web```ページを```PDF```として保存するための印刷機能が組み込まれています。
この機能を利用すると、```Jupyter Notebook```をブラウザで開き、```PDF```として保存することができます。

### 課題:
- **操作性の悪さ**
複数のファイルを```PDF```に変換するときには、```ipynb```ファイルを一つずつ開いて、一つずつ印刷プレビューして...というようにかなり面倒くさい作業になってしまいます。

# 本記事の方法: シェルスクリプトを活用した変換
本記事では、```Jupyter Notebook```の```.ipynb```ファイルを```PDF```に変換する新しい方法として、シェルスクリプトを使用した自動変換アプローチを提案します。
提案する方法は、いくつかのステップで構成されており、まず```Jupyter Notebook(.ipynbファイル)```を```HTML```に変換し、次に```HTML```を```PDF```に変換します。


### 特徴
1. **一括変換:** 複数の```.ipynb```ファイルを一度に変換することができます。
2. **ブラウザのヘッドレスモード:** ```Google Chrome```のヘッドレスモードを使用して、高品質な```PDF```を生成します。
3. **JavaScriptの完全なレンダリング:** ブラウザのヘッドレスモードを使用することで、```MathJax```などの```JavaScript```ベースのツールによるレンダリングが完了するのを待ってから```PDF```を生成します。
4. **環境構築の簡単さ:** ```Latex```を必要としないため簡単に再現できます。

# 環境構築
## 1. Jupyter Notebookのセットアップ
```.ipynb```ファイルを```html```に変換するためのツールをインストールするために```Anaconda```が必要です。

### インストール方法:
[Anacondaの公式サイト](https://www.anaconda.com/download)から、```Anaconda```をインストールします。
詳細は省きます。

## 2. ライブラリのインストール

### nbconvert
```nbconvert```は、```Jupyter Notebook```の内容を様々なフォーマットに変換するための便利なツールです。

**役割**
- ```ipynb```ファイルを静的なフォーマット（例: ```HTML```, ```LaTeX```, ```PDF```）に変換します。
- グラフやコード、マークダウンなどを適切に整形して出力します。

**インストール**
```bash
conda install nbconvert
```

## 3. Google Chromeのインストール
```Google Chrome```の印刷機能が必要となるのでインストールします。

インストールした```Google Chrome```の```Path```を控えておいてください。

```bash:Pathの例(MacOSで私の環境の場合)
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome

```

# ipynbをpdfに一括変換するシェルスクリプト

```shell:convert_to_pdf.sh
#!/bin/bash

# 引数が指定されていない場合はエラーメッセージを表示
if [ "$#" -ne 1 ]; then
    echo "Usage: $0 /path/to/your/directory"
    exit 1
fi

# 引数で指定されたディレクトリへ移動
cd "$1"

# すべての.ipynbファイルに対してループを実行し、.htmlに変換
for notebook in *.ipynb; do
    jupyter nbconvert --to html "$notebook"
done

# すべてのHTMLファイルに対してループを実行し、PDFに変換
for file in *.html; do
    # ファイル名から拡張子を除去
    filename=$(basename -- "$file")
    filename_noext="${filename%.*}"
    
    # Google Chromeのヘッドレスモードを使用してPDFに変換
    /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --headless --disable-gpu --virtual-time-budget=5000 --print-to-pdf="$filename_noext".pdf "$file"
done

```
**※注意点**
上記のシェルスクリプトは、```MacOS```の```Google Chrome```のデフォルトのインストール場所を前提としています。しかし、環境によっては```Google Chrome```のインストール場所が異なる場合があります。そのような場合は、シェルスクリプト内の最後から二行目にある```Google Chrome```の```Path```を適切な```Path```に変更する必要があります。

# 使い方
## 1. シェルスクリプトの準備
上記のシェルスクリプトを```convert_to_pdf.sh```という名前で保存します。

## 2. 実行権限の付与
シェルスクリプトを実行可能にするために、次のコマンドを実行して実行権限を付与します。

```bash
chmod +x convert_to_pdf.sh
```

### 3. シェルスクリプトの実行
シェルスクリプトを実行して、指定したディレクトリ内の```.ipynb```ファイルを```PDF```に変換します。

```bash
./convert_to_pdf.sh /path/to/your/directory
```

このコマンドを実行すると、指定したディレクトリ内のすべての```.ipynb```ファイルが順番に```HTML```に変換され、次に```PDF```に変換されます。

# まとめ
```Jupyter Notebook```の```.ipynb```ファイルを```PDF```に変換するための新しい方法を紹介しました。従来の方法にはいくつかの課題がありましたが、本記事で紹介した方法を使用することで、これらの課題を効果的に解決することができます。
 **特に、複数の```.ipynb```ファイルを一括で変換する場合や、数式を含むノートブックを変換する場合にこの方法は役立つでしょう!!**
今後もデータサイエンスのプロジェクトや研究でJupyter Notebookを活用する方には、この変換方法が役立つことを期待しています。