PubMedの隠しAPI "Literature Citation Exporter" が便利な件

# 要点

* 詳細は公式ページを参照: https://api.ncbi.nlm.nih.gov/lit/ctxp/
* 従来のE-utilitiesはxml形式、こちらはjson形式
* 他にも、著者のフルネームが書いてあるなど、色々と便利

# 発見した経緯

GitHubの下記リポジトリで使っているのを先日発見しました。少なくとも2019年には存在していたらしいです。全然知りませんでした。というかPubMedの [公式APIマニュアル](https://www.ncbi.nlm.nih.gov/home/develop/api/) にも多分書いてないです。まさに隠しAPIですね。
* https://github.com/zhuchcn/pubmed-bib 

一応、PubMedでなくPMCの下記ページからリンクが張られているため、非公式という訳ではないようです。
* https://pmc.ncbi.nlm.nih.gov/tools/developers/

# 制約

以下の公式ページに書いてありますが、1秒間に3回以上アクセスしたらダメだそうです。普通に使う分には問題なさそうですね。
* https://api.ncbi.nlm.nih.gov/lit/ctxp/



# 従来APIとの比較

それでは使用例を比べてみましょう。ここでの id とは PubMed ID (PMID) のことです。

従来APIの使用例
https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi?db=pubmed&id=18787119

応答
```xml
<eSummaryResult>
<DocSum>
<Id>18787119</Id>
<Item Name="PubDate" Type="Date">2008 Sep 23</Item>
<Item Name="EPubDate" Type="Date">2008 Sep 11</Item>
<Item Name="Source" Type="String">Proc Natl Acad Sci U S A</Item>
<Item Name="AuthorList" Type="List">
<Item Name="Author" Type="String">Dakos V</Item>
<Item Name="Author" Type="String">Scheffer M</Item>
<Item Name="Author" Type="String">van Nes EH</Item>
<Item Name="Author" Type="String">Brovkin V</Item>
<Item Name="Author" Type="String">Petoukhov V</Item>
<Item Name="Author" Type="String">Held H</Item>
</Item>
<Item Name="LastAuthor" Type="String">Held H</Item>
<Item Name="Title" Type="String">Slowing down as an early warning signal for abrupt climate change.</Item>
<Item Name="Volume" Type="String">105</Item>
<Item Name="Issue" Type="String">38</Item>
<Item Name="Pages" Type="String">14308-12</Item>
<Item Name="LangList" Type="List">
<Item Name="Lang" Type="String">English</Item>
</Item>
<Item Name="NlmUniqueID" Type="String">7505876</Item>
<Item Name="ISSN" Type="String">0027-8424</Item>
<Item Name="ESSN" Type="String">1091-6490</Item>
<Item Name="PubTypeList" Type="List">
<Item Name="PubType" Type="String">Historical Article</Item>
<Item Name="PubType" Type="String">Journal Article</Item>
</Item>
<Item Name="RecordStatus" Type="String">PubMed - indexed for MEDLINE</Item>
<Item Name="PubStatus" Type="String">ppublish+epublish</Item>
<Item Name="ArticleIds" Type="List">
<Item Name="pubmed" Type="String">18787119</Item>
<Item Name="pmc" Type="String">PMC2567225</Item>
<Item Name="pmcid" Type="String">pmc-id: PMC2567225;</Item>
<Item Name="doi" Type="String">10.1073/pnas.0802430105</Item>
<Item Name="pii" Type="String">0802430105</Item>
</Item>
<Item Name="DOI" Type="String">10.1073/pnas.0802430105</Item>
<Item Name="History" Type="List">
<Item Name="pubmed" Type="Date">2008/09/13 09:00</Item>
<Item Name="medline" Type="Date">2008/10/23 09:00</Item>
<Item Name="entrez" Type="Date">2008/09/13 09:00</Item>
<Item Name="pmc-release" Type="Date">2009/03/23 00:00</Item>
</Item>
<Item Name="References" Type="List"/>
<Item Name="HasAbstract" Type="Integer">1</Item>
<Item Name="PmcRefCount" Type="Integer">23</Item>
<Item Name="FullJournalName" Type="String">Proceedings of the National Academy of Sciences of the United States of America</Item>
<Item Name="ELocationID" Type="String">doi: 10.1073/pnas.0802430105</Item>
<Item Name="SO" Type="String">2008 Sep 23;105(38):14308-12</Item>
</DocSum>
</eSummaryResult>
```

隠しAPIの使用例
https://api.ncbi.nlm.nih.gov/lit/ctxp/v1/pubmed/?format=csl&id=18787119

応答

```json
{
    "source": "PubMed",
    "accessed": {
        "date-parts": [
            [
                2025,
                6,
                1
            ]
        ]
    },
    "id": "pmid:18787119",
    "title": "Slowing down as an early warning signal for abrupt climate change",
    "author": [
        {
            "family": "Dakos",
            "given": "Vasilis"
        },
        {
            "family": "Scheffer",
            "given": "Marten"
        },
        {
            "family": "van Nes",
            "given": "Egbert H"
        },
        {
            "family": "Brovkin",
            "given": "Victor"
        },
        {
            "family": "Petoukhov",
            "given": "Vladimir"
        },
        {
            "family": "Held",
            "given": "Hermann"
        }
    ],
    "container-title-short": "Proc Natl Acad Sci U S A",
    "container-title": "Proceedings of the National Academy of Sciences of the United States of America",
    "publisher-place": "United States",
    "ISSN": "0027-8424",
    "issued": {
        "date-parts": [
            [
                2008,
                9,
                23
            ]
        ]
    },
    "epub-date": {
        "date-parts": [
            [
                2008,
                9,
                11
            ]
        ]
    },
    "page": "14308-12",
    "volume": "105",
    "issue": "38",
    "PMID": "18787119",
    "PMCID": "PMC2567225",
    "DOI": "10.1073/pnas.0802430105",
    "type": "article-journal"
}
```

従来APIは **xml形式** 、隠しAPIは **json形式** という違いがあります。json形式の方がPythonで情報抽出する際に便利です。xml形式の場合は、lxmlパッケージで読み込んでから、Xpathという記法を使って欲しい箇所を取り出すのが一般的だと思いますが、少し面倒です。一方、jsonはPython内で **dictとして扱える** ので、遥かに簡単です。

他にも色々違いがあります。以下にまとめてみました。隠しAPIの方が便利そうです。

| 項目 | 従来API | 隠しAPI |
|-|-|-|
| 形式 | xml | json |
| 年月日 | 月は3文字表記 | 月も数字 |
| 著者名| ファーストネームはイニシャルのみ | フルネーム |
| タイトル | 末尾にドットあり、斜体、上付き、下付きなどの装飾情報は無し | 末尾にドットなし、&lt;i&gt;, &lt;sup&gt;, &lt;sub&gt;などのhtmlタグあり |
| ページ | たまに "Pages" が空欄で "ELocationID" に書いてある場合もある | 調べた範囲で常に "page" に書いてある |

# 整形のTips

月を文字列にしたければ、たった12個なので変換用のdictをコード中に書いてしまっても良いですし、pandasで以下のように変換しても良いでしょう。
```python
# 1,2,...,12 > Jan,Feb,...,Dec
month = pd.to_datetime(f'2000/{month}/1').strftime('%b')  # 年と日はダミー
```

装飾用のhtmlタグは、邪魔だったらreplaceで消してしまえば良いです。
```python
title = title.replace('</','<').replace('<i>','').replace('<sup>','').replace('<sub>','')
```

ついでに、ページ番号の略記 (例、1234-1256 > 1234-56) は従来APIでもありますが、省略された部分を復元したければ、以下のようにすれば良いです。
```python
if '-' in pages:
  p_from, p_to = pages.split('-')
  n = len(p_from) - len(p_to)   # 省略された桁の数
  if n >= 1:
    p_to = p_from[:n] + p_to
    pages = p_from + '-' + p_to
```

これまたついでに、雑誌名で省略された単語に "." を付けたければ、単語ごとにフルネームの中に登場するかどうかで判定すれば良いです。ただし、フルネームの中に "." や "," が含まれる場合もあるので、予め除いておきます。

```python
out_list = []  # 一時的なリスト
word_list = journal_full.lower().replace('.','').replace(',','').split(' ')
for x in journal_short.split(' '):
  if x.lower() in word_list:
    out_list.append(x)
  else:
    out_list.append(x + '.')
journal_short = ' '.join(out_list)
```

# 業績リストにコピペ可能な文字列が欲しいとき

APIへのリクエストで `format=csl` を `format=citation` に変えると、主要な複数の形式に整えた文字列を返してくれます。

使用例
https://api.ncbi.nlm.nih.gov/lit/ctxp/v1/pubmed/?format=citation&id=18787119

応答

```json
{
    "id": "pmid:18787119",
    "ama": {
        "orig": "Dakos V, Scheffer M, van Nes EH, Brovkin V, Petoukhov V, Held H. Slowing down as an early warning signal for abrupt climate change. Proc Natl Acad Sci U S A. 2008;105(38):14308-14312. doi:10.1073/pnas.0802430105",
        "format": "Dakos V, Scheffer M, van Nes EH, Brovkin V, Petoukhov V, Held H. Slowing down as an early warning signal for abrupt climate change. <i>Proc Natl Acad Sci U S A</i>. 2008;105(38):14308-14312. doi:10.1073/pnas.0802430105"
    },
    "apa": {
        "orig": "Dakos, V., Scheffer, M., van Nes, E. H., Brovkin, V., Petoukhov, V., & Held, H. (2008). Slowing down as an early warning signal for abrupt climate change. Proceedings of the National Academy of Sciences of the United States of America, 105(38), 14308–14312. https://doi.org/10.1073/pnas.0802430105",
        "format": "Dakos, V., Scheffer, M., van Nes, E. H., Brovkin, V., Petoukhov, V., & Held, H. (2008). Slowing down as an early warning signal for abrupt climate change. <i>Proceedings of the National Academy of Sciences of the United States of America</i>, <i>105</i>(38), 14308–14312. https://doi.org/10.1073/pnas.0802430105"
    },
    "mla": {
        "orig": "Dakos, Vasilis et al. “Slowing down as an early warning signal for abrupt climate change.” Proceedings of the National Academy of Sciences of the United States of America vol. 105,38 (2008): 14308-12. doi:10.1073/pnas.0802430105",
        "format": "Dakos, Vasilis et al. “Slowing down as an early warning signal for abrupt climate change.” <i>Proceedings of the National Academy of Sciences of the United States of America</i> vol. 105,38 (2008): 14308-12. doi:10.1073/pnas.0802430105"
    },
    "nlm": {
        "orig": "Dakos V, Scheffer M, van Nes EH, Brovkin V, Petoukhov V, Held H. Slowing down as an early warning signal for abrupt climate change. Proc Natl Acad Sci U S A. 2008 Sep 23;105(38):14308-12. doi: 10.1073/pnas.0802430105. Epub 2008 Sep 11. PMID: 18787119; PMCID: PMC2567225.",
        "format": "Dakos V, Scheffer M, van Nes EH, Brovkin V, Petoukhov V, Held H. Slowing down as an early warning signal for abrupt climate change. Proc Natl Acad Sci U S A. 2008 Sep 23;105(38):14308-12. doi: 10.1073/pnas.0802430105. Epub 2008 Sep 11. PMID: 18787119; PMCID: PMC2567225."
    }
}
```


origは&lt;i&gt;, &lt;sup&gt;, &lt;sub&gt;などのhtmlタグなし、formatは有りのバージョンです。
一番下のNLM形式は、普通にPubMedで論文検索して "Save" ボタンを押し、Format を "Summary (text)" にしたまま "Create file" ボタンを押したときで出てくるものと多分同じです。

[2025/06/05追記] origもタイトル部には&lt;i&gt;, &lt;sup&gt;, &lt;sub&gt;などのhtmlタグがあるようです。あくまでジャーナル名などタイトル以外に&lt;i&gt;タグがあるかどうかの違いみたいです。