2026-07-20 03:58:38 -10:00

60 lines
1.9 KiB
Python

#!/usr/bin/env python3
"""
Search the Semantic Scholar Graph API. No API key required for light use;
set the S2_API_KEY environment variable for higher rate limits.
CLI usage:
python3 search_semantic_scholar.py "UAV magnetic compensation" --max 10
Importable:
from search_semantic_scholar import search_s2
"""
import sys
import os
import json
import argparse
import urllib.request
import urllib.parse
S2_API = "https://api.semanticscholar.org/graph/v1/paper/search"
FIELDS = "title,authors,year,venue,externalIds,abstract,citationCount"
def search_s2(query, max_results=10, timeout=20):
params = {"query": query, "limit": max_results, "fields": FIELDS}
url = f"{S2_API}?{urllib.parse.urlencode(params)}"
req = urllib.request.Request(url)
api_key = os.environ.get("S2_API_KEY")
if api_key:
req.add_header("x-api-key", api_key)
with urllib.request.urlopen(req, timeout=timeout) as resp:
data = json.loads(resp.read())
results = []
for p in data.get("data", []) or []:
ext = p.get("externalIds") or {}
results.append({
"source": "semantic_scholar",
"title": p.get("title"),
"authors": [a.get("name") for a in (p.get("authors") or [])],
"year": p.get("year"),
"venue": p.get("venue"),
"doi": ext.get("DOI"),
"arxiv_id": ext.get("ArXiv"),
"abstract": p.get("abstract"),
"citation_count": p.get("citationCount"),
})
return results
if __name__ == "__main__":
ap = argparse.ArgumentParser(description=__doc__)
ap.add_argument("query")
ap.add_argument("--max", type=int, default=10)
args = ap.parse_args()
try:
out = search_s2(args.query, args.max)
print(json.dumps(out, ensure_ascii=False, indent=2))
except Exception as e:
print(json.dumps({"error": str(e)}, ensure_ascii=False))
sys.exit(1)