semanticscholar-skill について
semanticscholar-skillは、Semantic Scholar APIを使って学術文献を検索するための構造化ワークフローです。論文や著者の検索、引用分析、関連論文の推薦、結果のエクスポートに対応し、補助モジュールがレート制限を処理します。
主な機能
- 01複数の方法による論文検索
- 02論文と著者の情報取得
- 03引用と参考文献のたどり
- 04類似論文と推薦の検索
- 05年や分野などによる絞り込み
- 06BibTeX、Markdown、JSONへの出力
活用シーン
- 01研究テーマに関する文献の探索
- 02既知の題名や識別子から論文を検索
- 03引用と関連研究の追跡
- 04研究者の出版物の調査
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ agents365-ai/ semanticscholar-skill --skill semanticscholar-skillインストール後、Claude Code で/semanticscholar-skillを入力して読み込まれたか確認します。
同梱ファイルs2.py
詳細
Semantic Scholar 検索ワークフロー
構造化された4フェーズのワークフローを使用して、Semantic Scholar API 経由で学術論文を検索します。
重要なルール: API リクエストに対して、Bash を複数回続けて呼び出すことは絶対にしないでください。すべての検索を実行する Python スクリプトを1つだけ作成し、それを一度だけ実行してください。レート制限はすべて s2.py 内で自動的に処理されます。
フェーズ1:意図の把握と計画
ユーザーの意図を解析し、検索戦略を選択します。
判断ツリー
既定では
search_bulk()を使用してください。 Semantic Scholar の公式ドキュメントによると、関連性検索はリソースをより多く消費するため、ほとんどの場合、バルク検索が推奨されます。TLDR フィールドや著者・引用の詳細をインラインで取得する必要がある場合にのみ、search_relevance()を使用してください。
| ユーザーの要望 | 戦略 | 関数 |
|---|---|---|
| 幅広いトピックの調査 | バルク検索(推奨) | build_bool_query() を指定した search_bulk() |
| TLDR/著者の詳細をインラインで取得 | 関連性検索 | search_relevance() |
| 正確な技術用語、完全一致フレーズ | ブール演算子を使ったバルク検索 | build_bool_query() を指定した search_bulk() |
| 特定の記述や手法 | スニペット検索 | search_snippets() |
| タイトルがわかっている論文 | タイトル一致 | match_title() |
| DOI/PMID/ArXiv がわかっている論文 | 直接検索 | get_paper() |
| 特定の研究を引用している論文 | 引用のたどり検索 | get_citations() |
| ある論文に関連する論文 | シード論文1件による推薦 | find_similar() |
| 複数の論文に関連する論文 | 複数のシード論文による推薦 | recommend() |
| 研究者を検索 | 著者検索 | search_authors() |
| 研究者のプロフィール | 著者の詳細 | get_author() |
| 研究者の出版物 | 著者の論文 | get_author_papers() |
クエリ構築ルール
- 曖昧な用語(例:「stem cells」は間葉系幹細胞を意味する場合と、幹細胞様T細胞を意味する場合があります):完全一致フレーズと除外語を指定して
build_bool_query()を使用します- 例:
build_bool_query(phrases=["stem-like T cells"], required=["CD4", "TCF7"], excluded=["mesenchymal", "hematopoietic stem cell"])
- 例:
- 複数の文脈を含むクエリ(例:「がんと自己免疫におけるトピック X」):個別に検索を計画し、
deduplicate()で重複を除去します - 幅広いトピック:フィルター(年、掲載媒体、fieldsOfStudy、最小引用数)を指定して
search_relevance()を使用します
フィルターの計画
| フィルター | 使用する場合 |
|---|---|
year="2020-" | 最近の研究のみ |
publication_date="2024-01-01:2024-06-30" | 正確な期間(YYYY-MM-DD) |
fields_of_study="Medicine" | 分野を限定 |
min_citations=10 | 確立された論文のみ |
pub_types="Review" | レビュー/メタ分析を検索 |
pub_types="ClinicalTrial" | 臨床試験のみ |
open_access=True | オープンアクセス論文のみ |
チェックポイント: 先に進む前に、(1)検索戦略がユーザーの意図に合っていること、(2)フィルターが適切であること、(3)無関係な結果を避けるのに十分具体的なクエリであることを確認してください。
フェーズ 2:検索を実行する
以下の標準の前置コードで始まり、その後すべての検索を実行する Python スクリプトを 1 つ作成します。
# --- Standard prelude (use in every script) ---
import sys, os, glob
_candidates = [
os.path.expanduser("~/.claude/skills/semanticscholar-skill"),
os.path.expanduser("~/.openclaw/skills/semanticscholar-skill"),
*glob.glob(os.path.expanduser("~/.claude/plugins/**/semanticscholar-skill"), recursive=True),
*glob.glob(os.path.expanduser("~/.codex/skills/semanticscholar-skill")),
".",
]
SKILL_DIR = next((p for p in _candidates if os.path.isfile(os.path.join(p, "s2.py"))), None)
if SKILL_DIR is None:
raise RuntimeError("Cannot locate semanticscholar-skill (s2.py not found)")
sys.path.insert(0, SKILL_DIR)
from s2 import *
# --- end prelude ---
# Build precise query
q = build_bool_query(
phrases=["stem-like T cells"],
required=["CD4", "IBD"],
excluded=["mesenchymal"]
)
papers = search_bulk(q, max_results=30, year="2018-", fields_of_study="Medicine")
papers = deduplicate(papers)
print(format_results(papers, "Stem-like CD4 T cells in IBD"))
/tmp/s2_search.py に保存し、1 回の Bash 呼び出しで python3 /tmp/s2_search.py を実行します。レート制限、再試行、バックオフは s2.py 内で自動的に処理されます。
API キーがない場合: このスキルは S2_API_KEY なしで動作します。キーがない場合、または無効な場合、s2.py は自動的に未認証モード(x-api-key ヘッダーなし)に切り替わり、リクエスト間隔を 5 秒に広げます。S2 のドキュメントによると、匿名リクエストは未認証ユーザー全体で共有される 1000 req/s のプールを使用し、「利用が集中する時間帯にはさらに制限される」可能性があります。そのため、通常時のプールには余裕がありますが、慎重を期して 5 秒の間隔を設けることで、利用集中時の制限を避けられます。それでも 429 が継続して発生する場合は、_MIN_GAP を 10 秒に増やしてください。検索 1 件あたりの max_results は 30 以下にし、1 つのスクリプトにまとめる検索数を減らしてください。S2 はすべてのリクエストに API キーを含めることを推奨しています。https://www.semanticscholar.org/product/api#api-key-form から取得してください。
チェックポイント: スクリプトが正常に実行され(例外なし)、結果が返されたことを確認します。結果が 0 件の場合は、提示する前にクエリの範囲を広げるか、フィルターを緩和してください。
実行例
以下の各例では、スクリプトの先頭にフェーズ 2 の標準の前置コードがあることを前提としています。
例 1:著者のワークフロー — 「自己教師あり学習に関する Yann LeCun の論文を見つける」
authors = search_authors("Yann LeCun", max_results=5)
print(format_authors(authors))
# Use the first match's ID to get their papers
author_id = authors[0]["authorId"]
papers = get_author_papers(author_id, max_results=50)
# Filter locally for topic
ssl_papers = [p for p in papers if "self-supervised" in (p.get("title") or "").lower()]
print(format_results(ssl_papers, "Yann LeCun - Self-Supervised Learning"))
例 2:引用の連鎖と意図 — 「Transformer 論文を引用したのは誰で、どのように活用したのか?」
paper = get_paper("DOI:10.48550/arXiv.1706.03762")
print(f"Title: {paper['title']}, Citations: {paper['citationCount']}")
# Citation envelopes carry contextsWithIntent — keep them, don't flatten.
citing = get_citations(paper["paperId"], max_results=50)
citing.sort(key=lambda c: (c.get("citingPaper") or {}).get("citationCount", 0), reverse=True)
print(format_citations(citing, max_items=10)) # renders intent labels + context snippet
例 3:複数のシードによる推薦と BibTeX エクスポート — 「この 2 件に似ているものの、NLP に関するものではない論文を見つける」
recs = recommend(
positive_ids=["DOI:10.1038/nature14539", "ARXIV:2010.11929"],
negative_ids=["ARXIV:1706.03762"],
limit=20
)
print(format_results(recs, "Vision papers like Deep Learning & ViT, excluding NLP"))
# Export BibTeX for top results
bib_data = batch_papers([r["paperId"] for r in recs[:10]], fields="title,citationStyles")
print(export_bibtex(bib_data))
フェーズ 3:要約して提示する
- 一貫した形式(要約テーブル+上位 10 件の詳細)で出力するには、
format_results()を使用します - ユーザーの言語が中国語の場合は、要約を中国語で提示します
- 結果の合計件数と使用した検索戦略を必ず記載します
- ユーザーの具体的な質問に基づき、最も関連性の高い論文を強調します
フェーズ 4:ユーザーとの対話ループ
結果を提示した後、必ず以下の選択肢を提示してください。
- 翻訳 — タイトルや要約を中国語(または他の言語)に翻訳する
- 詳細 — 指定した論文番号のアブストラクト全文を表示する
- 絞り込み — 異なる用語やフィルターを使って検索範囲を狭める、または広げる
- 類似論文 — 特定の検索結果に類似した論文を見つける(
find_similar()) - 引用 — 特定の論文を引用した論文と、その活用方法を調べる(意図ラベルには
get_citations()とformat_citations()を使用) - エクスポート —
export_bibtex()、export_markdown()、またはexport_json()で結果を保存する - 完了 — 検索セッションを終了する
ユーザーが完了を伝えるまでループします。各フォローアップでも、同じ単一スクリプトのパターンを使用します。
追加リソース
- S2folks GitHub — Semantic Scholar 公式コード例:https://github.com/allenai/s2-folks
- Postman Collection — コード不要の API テスト:https://www.semanticscholar.org/product/api/tutorial からリンクされています
- API ドキュメント — 全エンドポイントのリファレンス:https://api.semanticscholar.org/
API クイックリファレンス
ヘルパーモジュール(s2.py)
各スクリプトの先頭で、フェーズ 2 の標準の前置コードを使用します。その後、以下の関数を呼び出します。モジュールの docstring(help(s2) または s2.py を参照)には、フェーズごとの各関数の概要が 1 行ずつ記載されています。
論文検索関数
| 関数 | 用途 | 最大結果数 |
|---|---|---|
search_relevance(query, **filters) | 広範な検索 | 1,000 |
search_bulk(query, sort=..., **filters) | ブール演算による精密検索 | 10,000,000 |
search_snippets(query, paper_ids=, authors=, inserted_before=, **filters) | 全文の該当箇所を検索 | 1,000 |
match_title(title) | タイトルの完全一致検索 | 1 |
paper_autocomplete(query) | クエリ補完の候補 | — |
get_paper(paper_id) | 論文の詳細情報を1件取得 | — |
get_citations(paper_id, max_results, publication_date=) | 被引用論文を取得 | 10,000 |
get_references(paper_id, max_results) | 引用している文献を取得 | 10,000 |
find_similar(paper_id, limit, pool) | 1件を起点に類似論文を推薦 | 500 |
recommend(positive_ids, negative_ids, limit) | 複数件を起点に論文を推薦 | 500 |
batch_papers(ids, fields) | 論文を一括取得(≤500) | — |
著者関数
| 関数 | 用途 | 最大結果数 |
|---|---|---|
search_authors(query, max_results) | 名前で研究者を検索 | 1,000 |
get_author(author_id) | 著者のプロフィール(所属、h-index) | — |
get_author_papers(author_id, max_results, publication_date=) | 著者の出版物を取得 | 10,000 |
get_paper_authors(paper_id, max_results) | 論文の著者一覧を取得 | 1,000 |
batch_authors(ids, fields) | 著者情報を一括取得(≤1000) | — |
フィルターパラメーター(kwargs)
snake_case の kwargs は S2 の camelCase パラメーターに自動変換されます(fields_of_study → fieldsOfStudy、min_citations → minCitationCount、publication_date → publicationDateOrYear、pub_types → publicationTypes、open_access → openAccessPdf)。ここでは snake_case を使用してください。
year、publication_date、venue、fields_of_study、min_citations、pub_types、open_access
year:"2020-"、"-2019"、"2016-2020"publication_date:"2024-01-01:2024-06-30"(YYYY-MM-DD 形式の範囲。終端を省略できます)pub_types:Review、JournalArticle、Conference、ClinicalTrial、MetaAnalysis、Dataset、Book、CaseReport、Editorial、LettersAndComments、News、Study、BookSection
ブール検索構文(bulk search のみ)
| 構文 | 例 | 意味 |
|---|---|---|
"..." | "deep learning" | 完全一致する語句 |
+ | +transformer | 必ず含める |
- | -survey | 除外 |
| | CNN | RNN | OR |
* | neuro* | 前方一致ワイルドカード |
() | (CNN | RNN) +attention | グループ化 |
term~N | bugs~3 | あいまい検索:N 回の編集以内の単語に一致(例:buggy、buns) |
"phrase"~N | "blue lake"~3 | 近接検索:語句間の距離が最大 N 語 |
安全に構築するには、build_bool_query(phrases, required, excluded, or_terms, fuzzy, proximity) を使用してください。
fuzzy:(term, edit_distance)タプルのリストproximity:(phrase, word_distance)タプルのリスト
出力関数
| 関数 | 用途 |
|---|---|
format_table(papers, max_rows=30) | Markdown の要約表 |
format_details(papers, max_papers=10) | TLDR/要約を含む詳細項目 |
format_citations(citations, max_items=10) | 引用意図ラベルと文脈の抜粋を含む引用情報 |
format_results(papers, query_desc) | 要約、表、詳細をまとめて出力 |
format_authors(authors, max_rows=20) | 著者表(名前、所属、h-index) |
export_bibtex(papers) | BibTeX エントリー(citationStyles フィールドが必要) |
export_markdown(papers, query_desc) | 完全な Markdown レポートをファイルに保存 |
export_json(papers, path) | JSON エクスポートをファイルに保存 |
deduplicate(papers) | paperId で重複を削除 |
対応する ID 形式
DOI:10.1038/...、ARXIV:2106.15928、PMID:19872477、PMCID:PMC2323569、CorpusId:215416146、ACL:2020.acl-main.447、DBLP:conf/acl/...、MAG:3015453090、URL:https://...
論文フィールド
デフォルト:title,year,citationCount,authors,venue,externalIds,tldr
追加:corpusId(整数、S2 のセカンダリ ID)、url(S2 論文ページへのリンク)、abstract、references、citations、openAccessPdf、publicationDate、publicationVenue、fieldsOfStudy、s2FieldsOfStudy、journal、isOpenAccess、referenceCount、influentialCitationCount(影響力のある被引用のみ)、citationStyles、embedding、textAvailability
externalIds オブジェクトに含まれる項目:ArXiv、MAG、ACL、PubMed、Medline、PubMedCentral、DBLP、DOI
著者フィールド:name、affiliations、paperCount、citationCount、hIndex、homepage、externalIds、papers
フィールドは最小限にしてください。 公式の S2 チュートリアルによると、「必要以上にフィールドを含めるのは避けてください。応答速度が低下することがあります。」 ユーザーが明示的に必要としている場合にのみ、
abstract、references、citationsを追加してください。
sort パラメーターの値(一括検索のみ)
sort キーワード引数で指定できる値は、次の 3 つのみです。
| 値 | 意味 |
|---|---|
citationCount:desc | 被引用数の多い順(デフォルト) |
publicationDate:desc | 新しい順 |
paperId:asc | 安定した決定的な順序(ページネーションに便利) |
レコメンデーションの上限
find_similar() と recommend() は、1 回の呼び出しで最大 500 件の論文を返します(limit の最大値 = 500)。
データセット API 関数
S2 の全データセット(論文、著者、要約、埋め込みなど)を一括ダウンロードする場合:
| 関数 | 目的 | キーが必要? |
|---|---|---|
list_releases() | 利用可能なリリース日文字列をすべて一覧表示します | いいえ |
list_datasets(release_id="latest") | リリース内のデータセットを一覧表示します | いいえ |
get_dataset_links(release_id, dataset_name) | データセットの事前署名付きダウンロード URL を取得します | はい |
get_dataset_diffs(start, end, dataset_name) | 2 つのリリース間の差分を取得します | はい |
利用可能なデータセット名(dataset_name として渡します):
| 名前 | 説明 | おおよそのサイズ |
|---|---|---|
papers | 論文の主要属性(タイトル、著者、日付など) | 約 2 億レコード、30 × 1.5 GB |
abstracts | 利用可能な論文の要約テキスト | 約 1 億レコード、30 × 1.8 GB |
authors | 著者の主要属性(名前、所属、論文数) | — |
citations | 論文間の引用関係 | — |
embeddings-specter_v1 | 論文の高密度 SPECTER ベクトル埋め込み | 約 1 億 2,000 万レコード、30 × 28 GB |
publication-venues | 掲載先のメタデータ | — |
s2orc | オープンアクセス PDF の本文テキスト | — |
tldrs | 自然言語による短い要約 | 約 1 億レコード、30 × 200 MB |
すべてのデータセットは JSON Lines(1 行につき 1 レコード)で提供されます。差分レスポンスには update_files(主キーに基づく挿入/置換)と delete_files(データセットから削除)が含まれます。
レート制限
s2.py は、S2_API_KEY が設定されているかどうかに応じて自動的に調整されます。
| モード | 間隔 | 公式の制限 | 再試行 |
|---|---|---|---|
| 認証済み(有効なキー) | 1.1 s | 導入時はキーごとに 1 req/s、専用の割り当て。すべてのエンドポイントで累積(申請により引き上げ可能) | 指数バックオフで 5 回(2s→60s) |
| 未認証(キーなし、または無効なキー) | 5.0 s | 全匿名ユーザーで共有する全体の 1000 req/s。「利用が集中する時間帯には、さらに制限される可能性があります」 | 指数バックオフで 5 回(2s→60s) |
S2 は、匿名で利用できるエンドポイントであっても、すべてのリクエストに API キーを含めることを推奨しています。専用の割り当てが得られ、負荷時もスムーズに利用でき、サポートが必要な場合もより適切な支援を受けられます。導入時の 1 req/s のキー割り当ては申請により引き上げ可能です。https://www.semanticscholar.org/product/api#api-key-form で取得してください。
匿名ユーザー向けの 1000 req/s の割り当ては、通常時は十分な量ですが、ドキュメントでは、利用が集中する時間帯には大幅に制限される可能性があると明記されています。そのため、キーがない場合の
_MIN_GAPのデフォルト値は 5 s であり、1000 req/s の割り当て上は技術的に可能な 1 ms ではありません。継続的に 429 が発生する場合は、s2.pyで_MIN_GAP = 10.0を設定するか、キーを取得してください。1 req/s のキー割り当てはすべてのエンドポイントで累積されるため、連続した呼び出し(例:get_paper→get_citations)は別々にカウントされます。
一括検索のレスポンス構造
search_bulk() は、すでにページ分割が解除された論文のリストを返します。内部の生レスポンスには次の項目があります。
| フィールド | 型 | 意味 |
|---|---|---|
total | 整数 | 一致する論文の推定合計数(正確ではありません) |
token | 文字列 | さらにページがある場合に存在します。次のリクエストに渡します |
data | 配列 | このページの論文 |
s2.py がトークンによるページネーションを自動的に処理するため、最終的なフラットなリストだけが返されます。
トラブルシューティング
| エラー | 原因 | 対処方法 |
|---|---|---|
HTTPError 403 | S2_API_KEY が設定されていますが、無効または期限切れです | s2.py は自動的に未認証モードに切り替わります。または unset S2_API_KEY を実行するか、https://www.semanticscholar.org/product/api#api-key-form で新しいキーを取得してください |
HTTPError 404 | 論文または著者の ID が不正です | ID の形式を確認してください。S2 は {"error": "Paper/Author/Object not found"} または "...with id ### not found" を返します |
5 回の再試行後に HTTPError 429 | 匿名ユーザー向けのレート制限に継続して達しました | 60 s 待つ、s2.py の _MIN_GAP を 5.0 から 10.0 に引き上げる、max_results を 30 以下にする、または API キーを取得してください |
ModuleNotFoundError: s2 | スキルディレクトリがパスに含まれていません | スキルが ~/.claude/skills/、~/.openclaw/skills/、または ~/.claude/plugins/ 配下の Claude Code プラグインとしてインストールされていることを確認してください |
ModuleNotFoundError: requests | requests がインストールされていません | pip install requests または uv pip install requests を実行してください |
| 返された結果が 0 件 | クエリが具体的すぎるか、フィルターが絞り込みすぎています | クエリの範囲を広げ、フィルターを削除し、search_bulk() の代わりに search_relevance() を試してください |
KeyError: 'data' | エンドポイントがエラーオブジェクトを返しました | API エラーの詳細を確認するには r.get("message") を確認してください |
tldr フィールドが空 | すべての論文に TLDR があるわけではありません。一括検索では TLDR は返されません | 代わりに abstract フィールドを使用してください |