Semantic scholar APIで論文のデータ取得
■ やりたいこと
Semantic scholarのAPIを利用して論文のアブストラクトの情報を取得する。
論文が掲載されているサイトから何かしらの検索語で論文の一覧を取得した際、著者名や論文タイトル、アブストラクトを自分の好きな形式で書きだして保存しておくのはやや面倒です。
そこで、PythonやAPI使用の練習を兼ねて、論文情報を取得・保存する処理をAPIを利用します。
■ 実装
様々な学術雑誌の論文が掲載されている「Semantic scholar」のAPIを利用して、以下の情報を取得します。
Title(論文タイトル)
Authors(著者)
Doi(doi、論文識別コードのようなもの)
field of study(研究分野)
Jounal(ジャーナル)
Year(論文が雑誌に受諾された年)
Citations(引用数)
URL(論文URL)
Abstract(アブストラクト、論文の要約のこと)
Semantic ScholarのAPIは無料かつAPIキー不要で使えることが特徴的です。ただ、AI系の論文の情報は豊富ですが、それ以外の分野の論文は少ないです。
(Semantic Scholar APIマニュアル)
Semantic Scholarと同様の検索ポータルとして、「Scopus」というサイトがあります。こちらは様々な分野の論文を取得することができます。しかし、有料のプランを契約したうえでAPIを使わないと、アブストラクトや掲載雑誌などの基本的な情報を取得することができません。
そのため、今回はSemantic scholarを採用しました。
■ コード
今回作成したコードはこちらです。
import requests
# Semantic Scholarから論文情報の取得を行う。
def search_papers_semantic(query, limit=20):
url = "https://api.semanticscholar.org/graph/v1/paper/search"
params = {
"query": query,
"limit": limit,
"fields": "title,abstract,venue,externalIds,fieldsOfStudy,year,authors,citationCount,url"
}
response = requests.get(url, params=params)
response.raise_for_status()
return response.json().get("data", [])
if __name__ == "__main__":
query = "search theory"
papers = search_papers_semantic(query, limit=50)
paper_count = 1
with open("output.txt", "w", encoding="utf-8") as f:
for paper in papers:
title = paper.get("title", "No title")
abstract = paper.get("abstract")
venue = paper.get("venue", "Unknown Journal")
doi = paper.get("externalIds", {}).get("DOI")
fields_of_study = paper.get("fieldsOfStudy", [])
year = paper.get("year", "Unknown Year")
citation_count = paper.get("citationCount", "Unknown")
url = paper.get("url", "No URL")
authors = paper.get("authors", [])
author_names = [author.get("name", "") for author in authors]
author_str = ", ".join(author_names) if author_names else "Unknown Authors"
if not abstract:
continue # アブストがなければスキップ
output = (
f"Paper {paper_count}:\n"
f"Title: {title}\n"
f"Authors: {author_str}\n"
f"DOI: {doi}\n"
f"fields_of_study: {fields_of_study}\n"
f"Journal: {venue}\n"
f"Year: {year}\n"
f"Citations: {citation_count}\n"
f"URL: {url}\n"
f"Abstract: {abstract}\n\n"
)
print(output)
f.write(output)
paper_count += 1
APIを利用して、Semantic Scholarをから論文情報を取得するコードは非常にシンプルです。
search_papers_semantic()という関数を定義し、ここで論文情報の取得を行っています。
リクエストはpostではなく、getでよいです。
def search_papers_semantic(query, limit=20):
url = "https://api.semanticscholar.org/graph/v1/paper/search"
params = {
"query": query,
"limit": limit,
"fields": "title,abstract,venue,externalIds,fieldsOfStudy,year,authors,citationCount,url"
}
response = requests.get(url, params=params)
response.raise_for_status()
return response.json().get("data", [])
search_papers_semantic()で得た論文情報は、今回テキストファイルに書き出していますが、保存スタイルをcsvに変えたりなどもできます。個人的にはBigQueryなどのなんらかのデータベースに格納しておきたいと思っており、今後やってみたいと思っています。
■ APIの補足
あとで自分が見返せるように、APIについての基本情報をまとめます。
・ APIとは、外部のアプリケーションにある便利な機能を自分のアプリケーションで利用するための技術のこと
・ 相手へ情報を送信するHTTPリクエストと相手から情報を受け取るHTTPレスポンスを記載する必要がある。
・ HTTPリクエストで送信する情報は以下の通り
ー エンドポイントURL(url変数の部分)
ー APIキー(semantic scholarでは不要)
⋯ 外部サーバーにアクセスするための認証情報
⋯ ヘッダーにAPIキーの情報を載せる
ー クエリパラメータ、使用するサービスの指定など。getの時は、ボディに記載したい情報もまとめて持たせる(requests.get(url, params=params)の部分)。
ー ヘッダー。データの種類(xmlやjson)の指定やAPIキー情報を持たせておく(postのみ)
ー ボディ。APIと送受信する情報を入力(paramsの部分)(postのみ)
⋯ リクエストの際は、GETかPOSTのメソッドを使う。どちらを使うかはAPI仕様書を読んで確認
参考
ちなみに、SemanticScholarではなく、ScopusのAPIを使って論文情報を取得する場合は以下のように行います。
import requests
# Scopus APIのヘッダー
HEADERS = {
"X-ELS-APIKey": "YOUR_SCOPUS_API_KEY",
"Accept": "application/json"
}
SCOPUS_BASE_URL = "https://api.elsevier.com/content/search/scopus?"
# Scopusから論文一覧を取得
def get_papers(query, count=10):
search_url = f"{SCOPUS_BASE_URL}query=TITLE-ABS-KEY({query})&count={count}&sort=-date&view=STANDARD"
response = requests.get(search_url, headers=HEADERS)
response.raise_for_status()
data = response.json()
return data.get("search-results", {}).get("entry", [])
scopusの場合は、以下のようにすれば論文情報の取得が可能です。
仕様書より、
・ データの形式は、「Accept」をキーにして渡す
・ 検索語は、TITLE-ABS-KEYをつけて渡す
・ viewは情報をどの程度詳細に取得するかを指定している。自分はscopusのAPIの有料契約をしていないので、STANDARDしか指定できないが、COMPLETEを指定すると、アブストラクトの情報なども取得できる。
■ 学んだこと・振り返り
・ APIの書き方
・ ちゃんとAPIの仕様書のページから、JSON形式のアウトプット見て、適切なキーの名前を確認したことはよかった。
・ __name__の使い方
if name == __main__という条件式は、ファイルがスクリプトとして直接実行された場合にのみTrueとなり、ファイルが直接実行されたときだけ、実行したいコードをこの条件式の中に記述することができる(ファイルがインポートされた場合、この条件式の中のコードは実行されない)。
これにより、ファイルが直接実行されたときだけ実行したいコードをこの条件式の中に記述することができる。
参考
Discussion