乐于分享
好东西不私藏

从手工下载到自动更新,我给自己搭了一个 AI 论文库

从手工下载到自动更新,我给自己搭了一个 AI 论文库

大家好,我是王胖纸,Atlasnote的独立开者。

昨天,乔木分享了AK大神在Hugging Face 做的热门论文Digg榜,靠人工投票筛选出每日、每周、每月最热AI论文。链接如下:

https://huggingface.co/papers/week/2026-W17

作为一名具有知识收藏癖的同学,我做了一件看起来不算大,但实际非常提高效率的事情:把 Hugging Face Papers 上的这些热点论文,整理成了一套本地论文库,并让它每天早上 6 点自动更新。

一开始,这件事只是“帮我把这个月的论文都下载下来”。

后来我发现,如果只是把 PDF 堆在一个文件夹里,短期看起来省事,长期一定会越来越乱。于是这件事很自然地从“下载文件”,变成了“设计一个可持续维护的本地论文归档系统”。

这篇文章就想把整个过程讲清楚:我们是怎么从下载,走到结构化归档,再走到定时自动更新的。

第一步不是下载,而是先搞清楚这个网站到底怎么组织论文

一开始最容易犯的错误,就是看到 monthly 页面,就以为那是“这个月的全部论文”。

但真正把数据拿下来以后,很快就会发现不是这么回事。

以我们这次处理截止到 April 2026 为例:

• monthly/2026-04 最终整理出来是 105 篇

• 但同一时间段相关的 weekly 页面,合起来远远不止这些

• 截至 2026 年 4 月 22 日,我们本地已经归档了:

• weekly/2026-W14

• weekly/2026-W15

• weekly/2026-W16

• weekly/2026-W17

• 其中当前周 2026-W17 在自动同步后已经增长到 76 篇

这意味着一件很关键的事:

**monthly 更像“月度精选”,weekly 更像“按周展开的更完整集合”。**

如果没有先弄清这个关系,后面无论是命名、归档还是自动更新,都会建立在错误假设上。

所以我们这次的做法不是“见页面就抓”,而是先回答三个问题:

1. monthly 和 weekly 是替代关系,还是并行关系?

2. 两者是否允许重复论文?

3. 到底应该做“当前快照”,还是做“按 period 的长期归档”?

这三个问题想清楚以后,后面的工作路径就稳定了。

第二步不是写脚本,而是先定归档结构

最早的版本,其实就是把 PDF 全部放进一个 monthly 文件夹、一个 weekly 文件夹里。

这种结构短期没问题,但只要你真的打算长期用,就会立刻出现两个问题:

• 新一周的数据进来以后,旧文件夹到底是覆盖、追加,还是重排?

• 如果某个月后来又补了几篇论文,文件编号要不要整体改?

这类问题如果不在一开始解决,后面所有自动化都会越来越脆。

所以我们最后把结构改成了按 period 归档:

AK-AI论文集/
  monthly/
    2026-04/
  weekly/
    2026-W14/
    2026-W15/
    2026-W16/
    2026-W17/
  _meta/

这个结构的好处非常直接:

• 每个月、每周都是独立快照

• monthly 和 weekly 可以各自保留重复论文,不互相干扰

• 当前 period 可以继续增量更新

• 已结束的 period 可以冻结,不再被随意改动

这一步其实是整个项目里最重要的决定。

因为一旦目录结构稳了,脚本、状态文件、定时器才能围绕一个清晰目标去工作。

第三步才是把动作拆成可重复执行的脚本

我后来越来越强烈地感受到:

像这种要长期运行的流程,真正的核心不应该是 Agent,也不应该是 prompt,而应该是一个可以独立运行、可重复执行、可恢复的脚本入口

所以我们没有把“自动更新论文库”做成一句模糊的指令,而是做成了一个明确的本地 skill,对应的核心入口是一个 Node 脚本。

它支持的动作很明确:

• check:检查当前归档状态

• migrate:把旧的平铺结构迁移成按 period 归档

• sync:同步当前 month / week

• repair:修复某个指定 period

• finalize:冻结旧 period

这一步的意义是:

先把动作做成确定性的工具,再让 Agent 调用它。

也就是说,Agent 是操作界面,不是运行时依赖。

真正的执行链路应该是:

定时器 -> 脚本 -> 归档目录

而不是:

定时器 -> Agent -> skill -> 临时判断 -> 再去执行

这样做的好处,是稳定性会高很多。

因为你以后不管是手动修复,还是每天自动更新,调用的其实都是同一套脚本逻辑。

第四步再引入定时任务,而不是一开始就“自动化”

很多自动化项目之所以最后失控,不是因为脚本不会写,而是因为太早引入“自动跑”,导致问题一旦发生,就会在后台不断重复。

这次我们的顺序刚好反过来:

1. 先手工验证下载路径和 PDF 来源

2. 再整理目录结构

3. 再实现同步脚本

4. 最后才把它接入 macOS 的定时系统

定时这一层,我们最终没有用 Codex 去“持续驱动”,也没有依赖某个常驻 Agent。

我们用的是 macOS 自带的 launchd,具体是当前用户的 LaunchAgents

原因很简单:

• 它本来就是系统级的定时调度器

• 不需要额外常驻一个 Agent

• 适合处理用户目录下的本地任务

• 比把逻辑硬塞进 prompt 稳定得多

所以最后的分工是这样的:

• script:真正执行同步

• skill:让 Agent 知道如何调用这套工具

• launchd:负责每天定时触发

现在这套任务已经正式安装,并且设成了每天早上 6:00 自动运行

真正麻烦的,不是写代码,而是处理“环境和边界”

如果只看最后结果,这件事会显得很顺:

抓页面、下 PDF、写 manifest、加定时器,结束。

但实际过程中,真正花时间的地方,往往都不是“主逻辑”,而是边界条件。

这次比较典型的有三个坑。

1. 页面顺序和真实时间顺序不完全等价

一开始我们已经下载过一版 monthly PDF,但后来真正把同步脚本接上以后,发现如果按照页面里的真实时间字段重新排序,原来的编号会有一批要重排。

这其实是好事。

因为它提醒我们:

编号应该服从明确规则,而不是服从某次临时抓取时的偶然顺序。

2. 定时任务的运行环境,和终端环境不是同一个世界

脚本在终端里能跑,不代表放进 launchd 以后还能直接跑。

我们这次就碰到了一个很典型的问题:

• 手动运行时网络是通的

• 放进 LaunchAgent 以后第一次运行失败

• 最后查出来,问题不是脚本本身,而是 launchd 默认不会继承终端里的代理环境

这个坑特别容易忽略。

也正因为踩了这个坑,我会更倾向于把“首次自动运行是否成功”当成单独的一次验收,而不是默认它一定没问题。

3. 大 PDF 的下载超时不能按小文件标准来设

最开始的下载超时比较保守,结果在当前周自动同步时,有论文 PDF 太大,120 秒还没下完,就被提前判失败了。

这类问题不算复杂,但它会直接影响自动化的稳定性。

最后我们把下载超时放宽,整个链路才真正稳下来。

这套工作流最后长成了什么样子?

如果把整个过程浓缩成一句话,我会这样概括:

先把论文当“归档对象”来设计,再把下载当“同步动作”来实现。

最后形成的工作路径是这样的:

1. 先确认来源结构,不急着下载

2. 先定 period 归档规则,不急着自动化

3. 再做一个可独立运行的同步脚本

4. 用 skill 把这套脚本包装成 Agent 可调用能力

5. 最后再接上 launchd 做定时

这条路径的好处,是每一步都比较可控。

哪怕后面要扩展,比如:

• 增加中文目录

• 加入精选筛选

• 增加某个主题分类

• 把这套东西接到公众号内容生产链路里

也都还有很清晰的落脚点。

这次做完以后,我最大的感受是什么?

以前我很容易把这类事理解成“写个脚本就好了”。

但这次做下来,我的感受更接近:

真正有价值的不是“能下载”,而是“这套下载以后还能长期维护”。

如果只是下一批 PDF,任何人都可以临时拼一个脚本。

但如果想让它在一周后、一个月后还保持可读、可修复、可扩展,那重点就不再是脚本本身,而是:

• 目录怎么设计

• period 怎么定义

• 当前期和历史期怎么分工

• 状态放哪里

• 定时器和脚本怎么解耦

这也是为什么我现在越来越倾向于把这类个人自动化,当作一个小型系统来做,而不是一段一次性脚本。

因为只有这样,它才会在未来继续帮你省时间,而不是变成一个你自己都不想再碰的旧工具。

结尾

如果你也想搭一个自己的论文归档系统,我会建议你先记住这三句话:

先归档,再自动化。

先脚本,再 Agent。

先保证可恢复,再追求全自动。

把顺序做对,后面的很多问题,其实都会轻松很多。

如果你对Atlasnote 感兴趣,可以到官网:atlasnote.ai 下载免费试用。也可以参考这篇Atlasnote使用指南。

AtlasNote 完整使用指南 v1.0:从零构建你的专属知识地图

如果你是一个AI新手,想要进阶了解更多AI知识,可以了解一下我的AI新手进阶65课:

全网最贴心AI教程:注册、付费、Prompt,使用指南、私藏工具,Agent….你想要的都在这里了