Biopythonを使ってPMCから論文取得
おさらい
- PubMed: 生命医学文書のインデックス
- PMC: 生命医学文書フルテキストのアーカイブ
- ClinicalTrials.gov: 臨床試験のデータベース
PubMedにはMeSH termやPublication Typeなどのメタデータが付与されていますが、テキストはAbstractしか入手できません。PMCはfull textが取得できますが、PubMedのように複雑な検索ができません。
PubMedで特定の条件に合致する論文を検索、PMCからfull textを入手する一連の流れをまとめました。
対象
課題をRandomized Controlled Trialのテキストを探すことに設定します。
filed Publication TypeにRandomized Controlled Trialを指定して検索します。49万件ヒットしました。

まずはこれらの書誌情報やAbstractを機械的に取得することを目指します。
色々使うので用語を整理します
- Entrez Programming Utilities (E-utilities): NCBIのデータベースを操作するためのプログラムの総称
- ESearch: 検索機能
- EFetch: ダウンロード機能
- BioPython: Entrezのラッパーとして使えるPythonライブラリ
Biopythonインストール
pipでインストール可能です。
pip install biopython
PMIDを取得
ESearchを使ってまずはダウンロードしたい論文のPMID (PubMed ID)を取得。
from tqdm import tqdm from Bio import Entrez Entrez.email = YOUR_EMAIL pmids = [] term = 'Randomized+Controlled+Trial[pt]' db='pubmed' retmax = 1000 handle = Entrez.esearch(db='pubmed',term='Randomized+Controlled+Trial[pt]') record = Entrez.read(handle) count = int(record['Count']) for retstart in tqdm(range(0, count, retmax)): handle = Entrez.esearch(db=db, term=term, retmax=retmax, retstart=retstart) record = Entrez.read(handle) pmids.extend(record['IdList'])
スペースを挟む連語を検索ワードに使うときは+で繋ぎましょう。[pt]はpublication typeです。はじめからfree full textのものだけを取得したければterm = 'Randomized+Controlled+Trial[pt] AND free+full+text[sb]'
とします。細かいオプションなどは公式を確認してください。
RCTは49万件、そのうちfree full textにアクセス可能なものは13万件あります。
論文を取得
EFetchを使って前項で取得したPMIDの論文を取得します。
retmax = 1000 for i in tqdm(range(0, count, retmax)): handle = Entrez.efetch(db='pubmed', id=pmids[i:i+retmax], retmode='xml') text = handle.read() with open('{}-{}.xml'.format(i, i+retmax), 'w') as f: f.write(text)
こんな感じで書誌情報とともにAbstractを取得できます。

詳細は公式。
EntrezではEFetchに200より多いIDを渡す場合はPOSTメソッドを使うように言われています。Biopythonでは自動でよしなにしてくれます。ちなみに10,000件一気に取ろうとしたら1リクエスト2分半かかりました。
PMIDに対応するPMCIDを取得
PMCにフルテキストがある論文はLinkOutにPMCへのリンクがあります。

ただしfree full textの条件を入れたとしても、必ずしもPMCIDが紐づいているとは限りません。以下一例。

先ほど取得したPubMedの情報からPMCIDを取得することができますXMLのArticleIdListに記述されています。
<ArticleIdList> <ArticleId IdType="pubmed">31360445</ArticleId> <ArticleId IdType="doi">10.7189/jogh.09.020402</ArticleId> <ArticleId IdType="pii">jogh-09-020402</ArticleId> <ArticleId IdType="pmc">PMC6657003</ArticleId> </ArticleIdList>
ID Converter APIを叩いて確認することもできます。1リクエスト200 IDまでという点に注意します。
tool = YOUR_TOOL_NAME email = YOUR_EMAIL ids = [] retmax = 200 for i in tqdm(range(0, len(pmids), retmax)): url = 'https://www.ncbi.nlm.nih.gov/pmc/utils/idconv/v1.0/?tool={}&email={}&email&ids={}&format=json'.format(tool, email, ','.join(pmids[i:i+retmax])) r = requests.get(url) j = json.loads(r.text) ids.extend(j['records'])
print(sum([1 for id in ids if 'pmcid' in id))
84550
Publication Type: Randomized Controlled Trialでヒットした49万件のうち8.5万件のfull textがPMCで公開されていることがわかりました。
全文を取得
再びEFetchを使ってPMCから全文を取得します。
pmcids = [id['pmcid'] for id in ids if 'pmcid' in id] retmax = 1000 for i in tqdm(range(0, len(pmcids), retmax)): handle = Entrez.efetch(db='pmc', id=pmcids[i:i+retmax], rettype='full', retmode='xml') text = handle.read() with open('{}-{}_pmc.xml'.format(i, i+retmax), 'w') as f: f.write(text)
先ほどのPubMedのデータとマージすればMeSHなどのメタデータと全文を合わせたものが入手できます。
だいたいこんな感じ。ジャーナルや論文自体のメタデータはPubMedのデータとダブりあり。

ただし出版社によってはfull textのダウンロードを禁じている場合があります。その場合は4行目に”The publisher of this article does not allow downloading of the full text in XML form.”とコメントが入ります。

参考
- MEDLINE, PubMed, and PMC (PubMed Central): How are they different?
- Finding Article Identifiers
- Biopython を利用したNCBIのEntrez データベースへのアクセス