66 lines
2.1 KiB
Python
66 lines
2.1 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Search the Crossref works API. No API key required.
|
|
Good for journal articles / DOIs that arXiv and Semantic Scholar might miss.
|
|
|
|
CLI usage:
|
|
python3 search_crossref.py "UAV magnetic compensation" --max 10
|
|
|
|
Importable:
|
|
from search_crossref import search_crossref
|
|
"""
|
|
import sys
|
|
import json
|
|
import argparse
|
|
import urllib.request
|
|
import urllib.parse
|
|
|
|
CROSSREF_API = "https://api.crossref.org/works"
|
|
UA = "literature-search-verify-skill/1.0 (mailto:research-assistant@example.com)"
|
|
|
|
|
|
def search_crossref(query, max_results=10, timeout=20):
|
|
params = {"query": query, "rows": max_results}
|
|
url = f"{CROSSREF_API}?{urllib.parse.urlencode(params)}"
|
|
req = urllib.request.Request(url, headers={"User-Agent": UA})
|
|
with urllib.request.urlopen(req, timeout=timeout) as resp:
|
|
data = json.loads(resp.read())
|
|
results = []
|
|
for item in data.get("message", {}).get("items", []) or []:
|
|
titles = item.get("title") or []
|
|
title = titles[0] if titles else ""
|
|
authors = []
|
|
for a in item.get("author", []) or []:
|
|
name = " ".join(filter(None, [a.get("given"), a.get("family")]))
|
|
if name:
|
|
authors.append(name)
|
|
year = None
|
|
date_parts = (item.get("issued", {}) or {}).get("date-parts")
|
|
if date_parts and date_parts[0]:
|
|
year = date_parts[0][0]
|
|
containers = item.get("container-title") or []
|
|
results.append({
|
|
"source": "crossref",
|
|
"title": title,
|
|
"authors": authors,
|
|
"year": year,
|
|
"venue": containers[0] if containers else None,
|
|
"doi": item.get("DOI"),
|
|
"arxiv_id": None,
|
|
"abstract": None,
|
|
})
|
|
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_crossref(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)
|