← Back to SKILL.md1#!/usr/bin/env python32"""Search arXiv and display results in a clean format.3 4Usage:5 python search_arxiv.py "GRPO reinforcement learning"6 python search_arxiv.py "GRPO reinforcement learning" --max 107 python search_arxiv.py "GRPO reinforcement learning" --sort date8 python search_arxiv.py --author "Yann LeCun" --max 59 python search_arxiv.py --category cs.AI --sort date --max 1010 python search_arxiv.py --id 2402.0330011 python search_arxiv.py --id 2402.03300,2401.1234512"""13import sys14import urllib.request15import urllib.parse16import xml.etree.ElementTree as ET17 18NS = {'a': 'http://www.w3.org/2005/Atom'}19 20def search(query=None, author=None, category=None, ids=None, max_results=5, sort="relevance"):21 params = {}22 23 if ids:24 params['id_list'] = ids25 else:26 parts = []27 if query:28 parts.append(f'all:{urllib.parse.quote(query)}')29 if author:30 parts.append(f'au:{urllib.parse.quote(author)}')31 if category:32 parts.append(f'cat:{category}')33 if not parts:34 print("Error: provide a query, --author, --category, or --id")35 sys.exit(1)36 params['search_query'] = '+AND+'.join(parts)37 38 params['max_results'] = str(max_results)39 40 sort_map = {"relevance": "relevance", "date": "submittedDate", "updated": "lastUpdatedDate"}41 params['sortBy'] = sort_map.get(sort, sort)42 params['sortOrder'] = 'descending'43 44 url = "https://export.arxiv.org/api/query?" + "&".join(f"{k}={v}" for k, v in params.items())45 46 req = urllib.request.Request(url, headers={'User-Agent': 'HermesAgent/1.0'})47 with urllib.request.urlopen(req, timeout=15) as resp:48 data = resp.read()49 50 root = ET.fromstring(data)51 entries = root.findall('a:entry', NS)52 53 if not entries:54 print("No results found.")55 return56 57 total = root.find('{http://a9.com/-/spec/opensearch/1.1/}totalResults')58 if total is not None:59 print(f"Found {total.text} results (showing {len(entries)})\n")60 61 for i, entry in enumerate(entries):62 title = entry.find('a:title', NS).text.strip().replace('\n', ' ')63 raw_id = entry.find('a:id', NS).text.strip()64 full_id = raw_id.split('/abs/')[-1] if '/abs/' in raw_id else raw_id65 arxiv_id = full_id.split('v')[0] # base ID for links66 published = entry.find('a:published', NS).text[:10]67 updated = entry.find('a:updated', NS).text[:10]68 authors = ', '.join(a.find('a:name', NS).text for a in entry.findall('a:author', NS))69 summary = entry.find('a:summary', NS).text.strip().replace('\n', ' ')70 cats = ', '.join(c.get('term') for c in entry.findall('a:category', NS))71 72 version = full_id[len(arxiv_id):] if full_id != arxiv_id else ""73 print(f"{i+1}. {title}")74 print(f" ID: {arxiv_id}{version} | Published: {published} | Updated: {updated}")75 print(f" Authors: {authors}")76 print(f" Categories: {cats}")77 print(f" Abstract: {summary[:300]}{'...' if len(summary) > 300 else ''}")78 print(f" Links: https://arxiv.org/abs/{arxiv_id} | https://arxiv.org/pdf/{arxiv_id}")79 print()80 81 82if __name__ == "__main__":83 args = sys.argv[1:]84 if not args or args[0] in {"-h", "--help"}:85 print(__doc__)86 sys.exit(0)87 88 query = None89 author = None90 category = None91 ids = None92 max_results = 593 sort = "relevance"94 95 i = 096 positional = []97 while i < len(args):98 if args[i] == "--max" and i + 1 < len(args):99 max_results = int(args[i + 1]); i += 2100 elif args[i] == "--sort" and i + 1 < len(args):101 sort = args[i + 1]; i += 2102 elif args[i] == "--author" and i + 1 < len(args):103 author = args[i + 1]; i += 2104 elif args[i] == "--category" and i + 1 < len(args):105 category = args[i + 1]; i += 2106 elif args[i] == "--id" and i + 1 < len(args):107 ids = args[i + 1]; i += 2108 else:109 positional.append(args[i]); i += 1110 111 if positional:112 query = " ".join(positional)113 114 search(query=query, author=author, category=category, ids=ids, max_results=max_results, sort=sort)115