#!/usr/bin/env python3 """ Search arXiv via its public Atom API. No API key required. CLI usage: python3 search_arxiv.py "UAV magnetic compensation" --max 10 Importable: from search_arxiv import search_arxiv """ import sys import json import argparse import urllib.request import urllib.parse import xml.etree.ElementTree as ET ARXIV_API = "http://export.arxiv.org/api/query" NS = {"atom": "http://www.w3.org/2005/Atom"} def search_arxiv(query, max_results=10, timeout=20): params = { "search_query": f"all:{query}", "start": 0, "max_results": max_results, "sortBy": "relevance", "sortOrder": "descending", } url = f"{ARXIV_API}?{urllib.parse.urlencode(params)}" with urllib.request.urlopen(url, timeout=timeout) as resp: data = resp.read() root = ET.fromstring(data) results = [] for entry in root.findall("atom:entry", NS): id_el = entry.find("atom:id", NS) title_el = entry.find("atom:title", NS) summary_el = entry.find("atom:summary", NS) published_el = entry.find("atom:published", NS) if id_el is None or title_el is None: continue arxiv_id_full = id_el.text.strip() arxiv_id = arxiv_id_full.rsplit("/", 1)[-1] title = " ".join(title_el.text.split()) summary = " ".join(summary_el.text.split()) if summary_el is not None else "" authors = [ a.find("atom:name", NS).text for a in entry.findall("atom:author", NS) if a.find("atom:name", NS) is not None ] published = published_el.text[:10] if published_el is not None else None pdf_url = None for link in entry.findall("atom:link", NS): if link.attrib.get("title") == "pdf": pdf_url = link.attrib.get("href") results.append({ "source": "arxiv", "arxiv_id": arxiv_id, "title": title, "authors": authors, "year": published[:4] if published else None, "published": published, "abstract": summary, "pdf_url": pdf_url, "doi": 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_arxiv(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)