Skip to content

Commit 722ab8d

Browse files
richteagueclaude
andcommitted
Scrape arxiv.org/list/astro-ph/new instead of using the API date filter
The export API's published date reflects submission time, not listing time, causing unreliable date filtering. The /new page is authoritative for today's papers. Verifies the listing date matches today before proceeding, then fetches full metadata via the API in a single batch request. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent b70eb7e commit 722ab8d

1 file changed

Lines changed: 32 additions & 19 deletions

File tree

disk-digest.js

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,27 +12,40 @@ const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
1212
// For those that are, run a more in-depth classification using Claude API.
1313

1414
async function fetchArxivPapers() {
15-
const url = "https://export.arxiv.org/api/query?search_query=cat:astro-ph.*&sortBy=submittedDate&sortOrder=descending&max_results=300";
16-
const res = await fetch(url);
17-
const xml = await res.text();
15+
// Fetch the daily new-listings page directly
16+
const listRes = await fetch("https://arxiv.org/list/astro-ph/new");
17+
const html = await listRes.text();
18+
19+
// Verify the listing is for today (UTC) before proceeding
20+
const now = new Date();
21+
const MONTHS = ["January","February","March","April","May","June","July","August","September","October","November","December"];
22+
const todayStr = `${now.getUTCDate()} ${MONTHS[now.getUTCMonth()]} ${now.getUTCFullYear()}`;
23+
if (!html.includes(todayStr)) {
24+
console.log(` ⚠️ arxiv.org/list/astro-ph/new is not yet updated for today (${todayStr}). No papers fetched.`);
25+
return [];
26+
}
27+
28+
// Extract all unique arXiv IDs listed on the page
29+
const ids = [...new Set([...html.matchAll(/arXiv:(\d{4}\.\d{4,5})/g)].map(m => m[1]))];
30+
if (ids.length === 0) return [];
1831

19-
const today = new Date().toISOString().slice(0, 10); // YYYY-MM-DD UTC
32+
// Fetch full metadata (titles, abstracts, authors) for all IDs in one API call
33+
const apiUrl = `https://export.arxiv.org/api/query?id_list=${ids.join(",")}&max_results=${ids.length}`;
34+
const apiRes = await fetch(apiUrl);
35+
const xml = await apiRes.text();
2036

2137
const entries = [...xml.matchAll(/<entry>([\s\S]*?)<\/entry>/g)];
22-
return entries
23-
.map(([, entry]) => {
24-
const get = tag => entry.match(new RegExp(`<${tag}[^>]*>([\\s\\S]*?)<\/${tag}>`))?.[1]?.replace(/\s+/g, " ").trim() ?? "";
25-
const authors = [...entry.matchAll(/<name>([\s\S]*?)<\/name>/g)].map(m => m[1].trim());
26-
return {
27-
id: get("id"),
28-
title: get("title"),
29-
abstract: get("summary"),
30-
link: get("id"),
31-
published: get("published").slice(0, 10),
32-
authors,
33-
};
34-
})
35-
.filter(p => p.published === today);
38+
return entries.map(([, entry]) => {
39+
const get = tag => entry.match(new RegExp(`<${tag}[^>]*>([\\s\\S]*?)<\/${tag}>`))?.[1]?.replace(/\s+/g, " ").trim() ?? "";
40+
const authors = [...entry.matchAll(/<name>([\s\S]*?)<\/name>/g)].map(m => m[1].trim());
41+
return {
42+
id: get("id"),
43+
title: get("title"),
44+
abstract: get("summary"),
45+
link: get("id"),
46+
authors,
47+
};
48+
});
3649
}
3750

3851
// Claude relevance check for all fetched papers
@@ -151,7 +164,7 @@ async function main() {
151164

152165
console.log("📡 Fetching arXiv papers...");
153166
const all = await fetchArxivPapers();
154-
console.log(` ${all.length} papers published today.`);
167+
console.log(` ${all.length} papers found on arxiv.org/list/astro-ph/new.`);
155168

156169
console.log("🔍 Running Claude relevance check...");
157170
const matched = [];

0 commit comments

Comments
 (0)