#!/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 os import json import argparse import urllib.parse sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) from http_utils import fetch 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)}" data = json.loads(fetch(url, headers={"User-Agent": UA}, timeout=timeout)) 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)