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

81 lines
2.6 KiB
Python

#!/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)