Notionでの論文管理をサポートするツールを作りました

# 変更履歴

## 250105
Papntをアップデートしました。
- GROBIDを用いて、抽出された全文をページに追加する機能を用意しました

## 250101
Papntが少しアップデートされました。
- arXivの論文にも対応しました。DOIを入力して`papnt doi`してください
- `papnt paths`でディレクトリを指定すると、そのディレクトリ以下にあるすべてのPDFを追加するようにしました（130nnoel様にプルリクしていただきました）
- Authorが100人を超える論文にも対応できるようにしました。100件以上はNotionに登録できないので、99番目までとlast authorだけ登録し、ページ内に残りのAuthorをベタ書きする形としました

<details><summary>さらに前</summary>

## 231108

現在、Pythonのバージョンが3.12だとpipでのインストールに失敗することがあるようです。
バージョン3.10または3.11のPythonを使うのがオススメです。
詳細を記載しました。
インストールの失敗について、ご報告いただきありがとうございました。

## 230614

Notionデータベース作成の方法に誤りがあったため修正しました。
`First`プロパティも、`Select`タイプにする必要があります。
ご指摘ありがとうございました。

</details>

# 前置き

[私はこんな感じでNotionを使って論文の管理をしている](https://qiita.com/issakuss/items/f204f56fe2b28988eff8)のですが、
その際に使っているPythonプログラムをコマンドラインツールとしてまとめて、配布してみました。

その名も **Papnt** です。

所詮素人が作ったプログラムなので大目に見てください。
このプログラムを使った結果について、一切責任は取れません。

# なにができるの？

- Notionデータベースに論文DOIを入力→`papnt doi`→論文の詳細な情報がデータベースに追加されている！
- Notionデータベースに論文PDFをアップ→`papnt pdf`→論文の詳細な情報がデータベースに追加されている！
- `papnt paths (論文PDFのパス)`→論文の詳細な情報がデータベースに追加されている！
- Notionデータベースのうち引用したい論文にタグをつける→`papnt makebib`→bibファイルが作られている！

（NEW）しかも、論文情報と一緒にPDFから抽出した全文が追加されてる！

以下は使い方です。

# Notion側の準備

## データベース作成

特定の名前・タイプをもったプロパティから成る、空のデータベースを作ります。
以下の手順に従うと、比較的簡単にできあがります。

まず、以下をコピーし、Notionのどこかのページにペーストしてください。

```
|Name|First|Year|PDF|Journal|Type|Authors|Title|Cite in|Citekey|Edition|Publisher|Volume|Issue|Pages|Subject|DOI|HowPublished|info|
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
||Select|Number|Files & media|Select|Select|Multiselect||Multiselect|||Select||||Multiselect|||Checkbox|
```

シンプルテーブルが作られるはずです。
このシンプルテーブルについて、OptionからHeader row（行見出し）をオンにします。

![header-row-on.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304493/27929288-d9ee-537d-cd40-8a2b9c3d4573.png)

右角の３点ボタンから、Turn into database（データベースに変換）します。

![turn-into-db.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304493/b79c274c-859d-a444-e726-58b3458b352a.png)

1行目に書かれているとおりのプロパティタイプに変更していってください。
たとえば、Yearの列には「Number」と書かれているので、プロパティタイプをNumberにしてください。

![edit-type.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304493/f5a00b86-a010-9742-0218-eab7807929ec.png)

1行目に何も書いていない列（プロパティ）はTextタイプのままにしておいてください。
この作業が終わったら、一行目は削除してしまってください。

これで論文情報を記入するデータベースが完成しました。

ここで作った以外のプロパティを持たせても大丈夫です。
例えば、ページを生成した日付などのプロパティがあると便利です。
プロパティの表示順や、表示・非表示設定は自由です。

プロパティの名前を変えていただくこともできます。
しかし、設定のために一手間かかるのでいったんこの名前のまま進めましょう。

![make-database.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304493/b1651d0b-ac5c-9a98-5455-665307115513.png)

## Notion APIとの接続

作成したデータベースを、Notion APIで操作できるように設定してください。
詳細は、「Notion API データベース」あたりでググってください。
TokenkeyとDatabase IDを取得し、作成したIntegrationをデータベースにadd connectionできればOKです。

![addconn.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304493/13503a17-6155-cf39-99f4-0d4244379365.png)

:::note info
データベースをインライン表示している場合はご注意ください。
インラインでデータベースを埋め込んでいるページのIDではなく、データベースそのもののIDを取得する必要があります。

データベースの左上の`::`をクリックして、Open as pageしてからTokenkey、IDの取得、add connectionをしましょう。

![openaspage.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304493/5ff53b3c-88c2-8045-40d2-4dda23b00210.png)
:::

# Papntのインストール

## pipでインストール

ご自身でPython環境をお持ちでしたら、以下のコマンドでインストール完了です。

```
% pip3 install git+https://github.com/issakuss/papnt.git@main
```

いくつかのパッケージがご使用の環境にインストールされるのでご注意ください。
また、Python == 3.10 or 3.11 が必要です。

<details><summary>3.12以降じゃダメな理由</summary>

PDFからDOIを読み取るのにpdf2doiというパッケージを使っています。
このパッケージはPyMuPDF==1.21.0のインストールを指定しています。
(https://github.com/MicheleCotrufo/pdf2doi/blob/master/requirements.txt)
ところが、Python3.12用のwheelは、PyMuPDF==1.23.5まで用意されていないようです。
(https://github.com/pymupdf/PyMuPDF/issues/2723)
そのためPython3.12以降からですと、sdistを用いてPyMuPDFをインストールすることになります。
この場合、VisualStudioなど、あれこれとソフトが必要になるようです。
(https://github.com/pymupdf/PyMuPDF/issues/2037)

</details>

## Homebrewでインストール

macOSをご使用でしたら、Homebrewを使って以下のコマンドでインストールするのがオススメです。

```
% brew install issakuss/papnt/papnt
```

Python環境ごとインストールするので、面倒なことを考える必要がありません。
ただし、インストールに少々時間がかかります。
私の環境だと6分ほどかかりました。

# Papntの設定

`papnt`とだけ打って実行すると、以下のようなメッセージが出ます。

![message.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304493/49a54665-27f3-4ab1-7fb7-9dfd33174059.png)

表示されたパスにあるconfig.iniを、テキストエディットやメモ帳など、お手元のエディタで開いてください。
以下のように表示されるはずです。

```ini: config.ini
[database]
    tokenkey = ''
    database_id = ''

[propnames]  ; Propety Names
    ; bib name = property name
    ; Check bib names: https://ja.wikipedia.org/wiki/BibTeX
    ; Note that bib names will be used as lower case
    doi = DOI
    author = Authors
    title = Title
    edition = Edition
    year = Year
    journal = Journal
    volume = Volume
    pages = Pages
    publisher = Publisher
    ID = Citekey
    ENTRYTYPE = Type
    howpublished = HowPublished

    ; Other property
    output_target = Cite in
    pdf = PDF

[abbr]  ; Specifiation of abbreviation
    Full Name = Abbreviated
    PLOS ONE = PLOS ONE

[grobid]
    server = ''  # Keep it empty if you do not wanna extract fulltext
    ; server = 'https://kermitt2-grobid.hf.space'  # Demo server provided by GROBID developer, no use too much!

[misc]
    ; Directory to save bib files
    dir_save_bib = ''
```

## 必須項目

以下の２項目には、それぞれNotionデータベースにアクセスするためのTokenkeyとDatabase IDを入力してください。

```ini: config.ini
[database]
    tokenkey = vja_Qgg2FGGjfaFQFGgagafFgjoiHffaefHFfaeKeeLs
    ; ↑こんな感じの50桁です（適当に作った例です）
    database_id = ac4ss3gajfhkga887fav2343tgggaq34
    ; ↑こんな感じの32桁です（適当に作った例です）
```

さらに、以下にbibファイルの保存先を指定してください。

```ini: config.ini
[misc]
    ; Directory to save bib files
    dir_save_bib = ''
```

以下は例です。

```ini: config.ini
[misc]
    ; Directory to save bib files
    dir_save_bib = /Users/issakuss/Desktop
```

## GROBIDサーバーの設定

PDFから全文を抽出する機能を使いたい場合は、GROBIDサーバーを`[grobid] server`に指定してください。
大体の人は、以下のような設定になると思います。

```
[grobid]
    server = 'http://localhost:8070'
```

全文抽出をOFFにする場合は、以下のように空欄にしてください。

```
[grobid]
    server = ''
```

そもそもGROBIDサーバーって何？という方は、こちらをご覧ください。
https://grobid.readthedocs.io/en/latest/Grobid-service/
オススメの方法はDockerです。
Dockerを使える環境にさえあれば、

```
docker run --rm --init --ulimit core=0 -p 8070:8070 -p 8081:8071 grobid/grobid:0.8.1
```

でいけます。
http://localhost:8070
をWEBブラウザで開いたときに、以下のような画面が出ていればサーバーの設定はOKです。

![ss-grobid-server.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304493/ce6bb04d-511b-c89d-bcfa-4f3b02bb5d1d.png)

GROBIDサーバーとかよくわかんないけどちょっと試してみたいという方は、

```
[grobid]
    server = 'https://kermitt2-grobid.hf.space'
```

としてみてください。
GROBID制作者が用意したデモ用サーバーを使って全文抽出を試すことができます。
ただ、負荷がかかることは前提としていないようです。
ご迷惑になるかと思うので、普通に使うときは自前でGROBIDサーバーを用意しましょう。
Dockerさえ準備できればあとは簡単ですよ！


## プロパティ名の設定

もしプロパティの名前を変更する場合は、`[propnames]`を編集してください。
たとえば、`Authors`というプロパティ名を`Chosya`に変えたい場合は、

```
    author = Chosya
```

としてください。

# コマンドの実行

Terminalなりコマンドプロンプトなりでコマンドを打って使用してください。

## `papnt doi`

データベースに記入されたDOIをもとに、情報を埋めるコマンドです。

これを使うにはまず、データベース内のページにDOIを記入します。

![enter-doi.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304493/f2c55adf-1307-3176-32c3-47f5a7b760e2.png)

`papnt doi`を実行すると、自動で論文情報が入力されます。

![info-filled-doi.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304493/c45d587e-f813-9381-e82d-66ad2d51e20a.png)

また、GROBIDサーバーが設定されていると、ページ内に抽出された全文が貼り付けられます。

![ss-grobid-sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304493/1edd007a-0003-6f73-d3ce-f77c76c51ed9.png)

情報が埋められると、`info`というプロパティに自動でチェックがつきます。
`papnt doi`は、`DOI`に入力があり、かつ`info`にチェックがついていないページを探します。
そしてヒットしたすべてのページの情報を、入力されたDOIをもとに埋めます。

<details><summary>より詳細な挙動</summary>

1. Notion APIでデータベースを取得します。
2. そこから、`DOI`に入力があり、かつ`info`にチェックがついていないページを探します。
3. ヒットしたすべてのページにおいて、入力されたDOIをもとに論文情報を収集します。
DOIから論文情報を収集するのには、[crossrefapi](https://github.com/fabiobatalha/crossrefapi)を使います。
5. 収集した論文情報をNotion Propertyの形に整えます。
6. Notion APIを使ってデータベースに反映させます。

</details>

## `papnt pdf`

データベースにアップロードされたPDFファイルをもとに、情報を埋めます。

これを使うにはまず、データベース内のページにPDFファイルをアップロードします。
![up-pdf.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304493/6f314e26-c18e-e408-dd5e-0c4699a2879d.png)

`papnt pdf`を実行すると、自動で論文情報が入力されます。
`papnt doi`と同様、`PDF`にファイルがあり、かつ`info`にチェックがついていないページを探します。
そしてヒットしたすべてのページの情報を、PDFに書かれたDOIをもとに入力します。

PDFからDOIを抽出できない場合があります。
その際は手動でDOIをコピーして、`papnt doi`を使用してください。
誤ったDOIに基づいて情報入力してしまうこともあるのでご注意ください。

<details><summary>より詳細な挙動</summary>

1. Notion APIでデータベースを取得します
2. そこから、`PDF`にファイルがあり、かつ`info`にチェックがついていないページを探します
3. PDFファイルを"you-can-delete-this-file.pdf"という名前でダウンロードします
このファイルは自動的に削除されます。
4. [pdf2doi](https://pypi.org/project/pdf2doi/)を用いてDOIを抽出します
5. 以降は`papnt doi`の挙動3以降と同様です

</details>

## `papnt paths`

ローカルにある論文PDFファイルのパスを指定すると、その論文の情報をデータベースに追加します。

以下のようにして、論文PDFファイルのパスを指定して実行します。

```
papnt paths /Users/issakuss/Downloads/sample1.pdf
```

すると、データベースにページが追加され、情報が入力されます。
PDFのアップロードまではされません。
NotionのAPIに、ファイルアップロード機能がないためです。

複数のファイルをカンマで区切って入力することで、複数の論文をいっぺんに追加することもできます。

```
papnt paths /Users/issakuss/Downloads/sample2.pdf,/Users/issakuss/Downloads/sample3.pdf
```

また、PDFファイルのパスではなくディレクトリを指定することも可能です。
そのディレクトリ以下にあるPDFファイルすべてを対象に実行します。

```
papnt paths /Users/issakuss/Downloads/takusan-no-pdf-folder/
```

<details><summary>より詳細な挙動</summary>

1. 入力されたファイルパスをカンマで区切ります。
2. それぞれのパスに対して、`papnt pdf`の挙動4以降と同様の処理をします。

</details>

## `papnt makebib`

特定のタグをつけた論文からbibファイルを作成するコマンドです。

これを使うにはまず、bibファイルに含めるページの`Cite in`プロパティに任意のタグをつけます。
たとえば、`next-paper`というタグをつけてみましょう。
別のタグ（たとえば`latest-paper`）がついていても問題ありません。

![enter-citein.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304493/4b9b662e-a992-149a-2f75-dea1e49e4e40.png)

続いて、以下のコマンドを打ちます。

```
% papnt makebib next-paper
```

しばらくすると、next-paper.bibという名前でファイルが生成されます。
保存先は、config.iniファイルで指定したディレクトリです。

<details><summary>より詳細な挙動</summary>

1. Notion APIでデータベースを取得します。
2. そこから、指定されたタグのついたページを探します。
3. ページに書いてある論文情報をもとにbibファイルを生成します。

</details>


さらに、同じディレクトリにnext-paper.jsonというファイルも生成されます。
これには、生成したbibファイルに含まれるすべてのジャーナル名の略称情報が含まれています。

```json: next-paper.json
{
  "default": {
    "container-title": {
      "Frontiers in Psychology": "Front. Psychol.",
      "Scientific Reports": "Sci. Rep."
    }
  }
}
```

たとえばPandocなら、`--citation-abbreviations`オプションを使用してこのjsonファイルを指定することで、省略したジャーナル名を参考文献リストに記載することができます。

一部、省略がうまくいかないことがあります。
たとえば「PLOS ONE」が、「PLO ONE」になったりします。
そういったジャーナル名に対応するためには、config.iniに手動で省略形を記載してください。

```ini: config.ini
[abbr]  ; Specifiation of abbreviation
    Full Name = Abbreviated
    PLOS ONE = PLOS ONE
```
左に省略前のジャーナル名、右に省略後のジャーナル名を書いてください。
jsonファイルの生成に反映されます。

<details><summary>より詳細な挙動</summary>

1. 生成されたbibファイルを読み込みます。
2. bibファイルに含まれるジャーナル名の一覧を作ります。
3. 各ジャーナル名について、[iso4](https://pypi.org/project/iso4/)を使って省略名を生成します。
4. config.iniによって指定されている省略名があれば、それをもって上書きします。
4. jsonファイルとして出力します。

</details>

## （おまけ）PDFを副クリックしてNotionデータベースに追加

macOS限定です。

まず、[こちらのサイト](http://www5.wind.ne.jp/miko/mac_soft/automator_actions/pgs/GetFilePathAMA.html)からGet `File Path.action`をDLしてインストールしてください。

:::note info
ポップアップに従って「他社製のAutomatorアクションを有効にする」にチェックすることが求められます。
私の環境だとなぜかチェックができない（チェックボックスが反応しない）のですが、
Automatorアプリを開き、メニューバー→Automator→他社製のAutomatorアクション… でなんとかなりました。
:::

:::note info
私の環境だとさらにセキュリティに弾かれたのですが、Terminalから

```
sudo spctl --master-enable
```

でなんとかなりました。
一時的にセキュリティが弱められるので、使い方等よくググってからお試しください。
:::


[add-pdfs-to-notion-db.workflow.zip](https://github.com/issakuss/papnt/raw/main/add-pdf-to-notion.workflow.zip)をDLして、解凍してください。
workflowファイルをダブルクリックしてインストールしてください。

その後適当な論文PDFを副クリックすると、クイックアクションに`NotionDBに追加`が加わっているはずです。

![add-notion-db.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304493/baa33b1b-d5ff-b5fd-d098-d0c1cd56bd76.png)

これを実行してみてうまくいくようならそれでOKです。
「command not found: papnt」的なエラーが出ましたら、papntのPATHを設定してやる必要があります。
エラーメッセージにある`ワークフローを表示`ボタンを押して、`NotionDBに追加.workflow`をAutomatorで編集しましょう。

![automator.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304493/637e3094-bfda-be52-494c-111d0c54cd4c.png)

`シェルスクリプトを実行`の項目に注目。
初期設定で、`PATH=/opt/homebrew/bin:$PATH`となっています。
`/opt/homebrew/bin`にpapntがないと「command not found: papnt」となります。

ご自身の環境のどこにpapntがあるかを調べるために、ターミナルを開いて`which papnt`をします。
これで出てきたパスから、最後の`papnt`を除いて.workflowファイルを書き換えてください。

たとえば、`which papnt`したときに
`/opt/homebrew/Caskroom/miniconda/base/envs/papnt/bin/papnt`
と表示されたなら、

![スクリーンショット 2023-06-08 16.38.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304493/678e47bf-78dd-a48d-9d30-f7f2c8ea0464.png)

こうです。

# 大目に見てください

macOSでのみ動作チェックしたので、Windowsでもうまく動くか未確認です。
もっといろんな環境で確認してからリリース（？）しようかと思ったのですが、
いつまで経っても世に出せなさそうだったので見切り発車です。
うまく動かない旨ご報告いただければ、できるだけ対応します。
時間はかかります。

パソコンに被害を及ぼしうるようなシロモノではないと思うのですが、
所詮シロウトのプログラムなのでご警戒ください。
ご不安であれば、ご自身でコード読み取っていただいて、
使えそうな部分だけピックアップするような形ででも使ってください。

`pdf2doi`の限界などのために、誤った論文情報を持ってくるようなことはしばしばあります。
論文情報が正しいかどうか、必ずご自身でご確認ください。