1. 一份日报的诞生:为什么要做 arXiv 每日论文分析
每天早上刷 arXiv 的人不少,但真正能把当天上百篇新论文筛明白的人不多。我自己做计算机视觉和机器人方向的研究,前几年养成了一个习惯:每天花二十分钟扫一遍 arXiv 的 cs.CV、cs.RO、cs.LG 三个分类的新提交。坚持了几个月之后发现一个问题——纯靠肉眼扫,效率极低,而且很容易漏掉那些标题起得平平无奇、但内容其实很硬的工作。后来我就琢磨着把这套流程自动化,做成一份每日论文分析报告,2026-09-14 这一期就是其中一份比较典型的产出。
这份报告解决的核心问题很具体:在信息过载的环境下,用一套可复现的流程,把当天 arXiv 上跟计算机视觉、机器人、机器学习相关的新论文做一轮粗筛、分类、摘要和趋势标注,最终输出一份能在十分钟内读完的简报。它适合三类人参考:一是每天需要跟踪前沿但时间有限的研究生和工程师;二是想搭建自己论文追踪系统的开发者;三是刚入门机器学习、想通过读论文建立领域感觉的新手。整套流程不依赖任何特殊网络手段,用的都是公开接口和常规工具链,下面我把设计思路、实现细节和踩过的坑完整拆一遍。
2. 整体设计与思路拆解
2.1 为什么选 arXiv 而不是其他来源
做论文追踪,第一步是选数据源。我对比过几个常见渠道:期刊官网更新慢、会议论文集有周期性、社交平台上的推荐流噪声太大。arXiv 的优势在于更新频率高(工作日每天都有新提交)、覆盖范围广(cs.CV、cs.RO、cs.LG 基本囊括了我要的方向)、而且提供结构化的元数据接口。它的官方 API 支持按分类、日期、关键词检索,返回的是 Atom XML 格式,解析起来不复杂。
这里有个细节值得说:arXiv 的 API 有速率限制,官方建议每次请求间隔三秒。我一开始没注意,连续快速请求了几十次,结果被临时限流,返回 503。后来改成批量拉取加本地缓存,就再没出过问题。所以设计上我采用的是按分类分别请求、结果落地到本地 JSON、后续分析全部读本地文件的模式,既减轻了接口压力,也让整个流程可重复。
2.2 报告要回答哪几个问题
一份日报如果只是把论文标题列出来,那跟直接看 arXiv 列表没区别。我在设计时定了四个必须回答的问题:
- 今天有哪些新论文:按 cs.CV、cs.RO、cs.LG 分类列出,附标题、作者、摘要首句。
- 哪些值得优先看:用关键词权重和摘要长度做一轮打分,把可能重要的排前面。
- 今天有没有明显的主题聚集:比如某天突然出现很多关于 3D 高斯泼溅或者机器人导航的论文,这种聚集往往意味着方向在升温。
- 跟昨天相比有什么变化:新出现的术语、突然增多的方向,用简单的词频对比就能看出来。
这四个问题对应报告里的四个板块,逻辑上是递进的:先看全貌,再抓重点,然后找趋势,最后看变化。
2.3 技术选型背后的考量
整套流程我用 Python 实现,核心依赖只有三个:requests负责拉数据,feedparser解析 Atom XML,jieba做中文分词和关键词提取。没有上重型框架,原因很简单——这个任务的复杂度不值得引入深度学习模型。我见过有人为了做论文分类去微调 BERT,效果确实好一点,但维护成本高、跑一次要几分钟,对于每日更新的场景来说性价比太低。
关键词打分用的是最朴素的 TF-IDF 变体:先维护一个领域词表(比如“diffusion”“SLAM”“manipulation”“segmentation”这些),统计每篇论文摘要里命中词表的词,再按词的权重加权求和。权重是我手动调的,高频但泛的词(如“learning”)权重低,具体方向词(如“NeRF”“VLA”)权重高。这套方法粗糙但够用,实测下来排序结果跟我的直觉判断吻合度在八成以上。
3. 核心细节解析与实操要点
3.1 arXiv API 的请求构造
arXiv API 的基础地址是http://export.arxiv.org/api/query,支持的参数不少,我常用的几个是:
| 参数 | 作用 | 示例 |
|---|---|---|
search_query | 检索条件 | cat:cs.CV |
start | 起始序号 | 0 |
max_results | 返回条数 | 100 |
sortBy | 排序字段 | submittedDate |
sortOrder | 排序方向 | descending |
按分类拉当天论文,检索式写成cat:cs.CV AND submittedDate:[202609140000 TO 202609142359]。注意日期格式是YYYYMMDDHHMM,时区是 UTC,所以如果你在东八区,实际要往前推八小时。我一般直接拉最近 24 小时的全部结果,然后在本地按日期过滤,这样更稳妥。
请求头里建议带上User-Agent,标明用途。虽然 arXiv 没有强制要求,但养成好习惯,万一哪天需要申请更高的请求配额,有记录可查。
3.2 摘要解析与关键词提取
拿到 Atom XML 之后,feedparser会把每条 entry 解析成字典,标题在entry.title,摘要在entry.summary,作者在entry.authors,分类在entry.tags。这里有个坑:arXiv 的摘要里经常包含换行符和多余空格,直接拿来做词频统计会出问题。我的处理是先re.sub(r'\s+', ' ', summary)把空白字符统一成单个空格,再 strip 掉首尾。
关键词提取分两步走。第一步是词表匹配,维护一个约两百词的领域词表,覆盖计算机视觉(segmentation、detection、tracking、pose estimation)、机器人(manipulation、navigation、SLAM、locomotion)、机器学习(transformer、diffusion、reinforcement learning、contrastive)三大块。第二步是统计词频,用jieba.analyse.extract_tags对摘要做一次无监督抽取,取前十个词作为补充。两步结果合并去重,就得到每篇论文的关键词列表。
注意:词表需要定期维护。我每个月会花半小时看看最近冒出来的新术语,手动加进去。比如“world model”“VLA”“3D Gaussian Splatting”这些词,都是后来才补进词表的。
3.3 打分排序的权重设计
打分公式很简单:score = Σ(词权重 × 出现次数) + 摘要长度修正。词权重我分了三档:
- 高权重(3.0):具体方向词,如“NeRF”“SLAM”“VLA”“diffusion policy”。
- 中权重(1.5):方法类词,如“transformer”“contrastive”“distillation”。
- 低权重(0.5):泛化词,如“learning”“network”“model”。
摘要长度修正的作用是避免短摘要因为词少而吃亏。修正项是min(len(summary)/500, 1.0),也就是摘要超过 500 字符就加满 1 分。这个数值是我试出来的,500 字符大约对应 arXiv 摘要的中位数长度。
实测下来,这套打分能把当天最值得看的十篇左右排到前面,剩下的按分类平铺。我不追求百分百准确,只要能帮我省掉八成筛选时间就达到目的了。
4. 实操过程与核心环节实现
4.1 环境准备与依赖安装
整个项目跑在 Python 3.10 上,依赖很少,一条命令搞定:
pip install requests feedparser jieba如果你要用中文分词,jieba首次运行会构建词典缓存,大概需要十几秒,之后就快了。我建议把项目放在一个独立目录里,结构如下:
arxiv-daily/ ├── fetch.py # 拉取数据 ├── analyze.py # 分析打分 ├── report.py # 生成报告 ├── data/ # 存放每日 JSON └── keywords.txt # 领域词表词表文件一行一个词,格式是词 权重,用空格分隔。这样改词表不用动代码,维护起来方便。
4.2 数据拉取脚本的完整实现
fetch.py的核心逻辑是遍历分类列表,逐个请求,结果存成data/YYYY-MM-DD.json。关键代码如下:
import requests import feedparser import json import time from datetime import datetime, timedelta CATEGORIES = ["cs.CV", "cs.RO", "cs.LG"] BASE_URL = "http://export.arxiv.org/api/query" def fetch_category(cat, max_results=200): query = f"cat:{cat}" params = { "search_query": query, "start": 0, "max_results": max_results, "sortBy": "submittedDate", "sortOrder": "descending", } headers = {"User-Agent": "arxiv-daily-report/1.0"} resp = requests.get(BASE_URL, params=params, headers=headers, timeout=30) resp.raise_for_status() return feedparser.parse(resp.text) def collect(date_str): all_entries = [] for cat in CATEGORIES: feed = fetch_category(cat) for entry in feed.entries: published = entry.published[:10] if published == date_str: all_entries.append({ "title": entry.title.strip(), "summary": entry.summary.strip(), "authors": [a.name for a in entry.authors], "category": cat, "link": entry.link, "published": entry.published, }) time.sleep(3) # 遵守速率限制 return all_entries if __name__ == "__main__": today = datetime.utcnow().strftime("%Y-%m-%d") entries = collect(today) with open(f"data/{today}.json", "w", encoding="utf-8") as f: json.dump(entries, f, ensure_ascii=False, indent=2) print(f"collected {len(entries)} entries for {today}")这里有几个实操要点。第一,time.sleep(3)不能省,我前面说过被限流的教训。第二,日期过滤放在本地做,因为 API 的日期检索有时区偏差,本地过滤更可靠。第三,max_results设 200 是因为 cs.LG 一天的新论文有时能到一百多篇,设小了会漏。
4.3 分析与报告生成
analyze.py读入 JSON,对每篇论文做关键词提取和打分,输出排序后的列表。report.py再把结果渲染成 Markdown。报告结构我固定成四块:
- 今日概览:总论文数、各分类数量、平均摘要长度。
- 重点推荐:打分前十五名,每条附标题、作者首作者、关键词、链接。
- 主题聚集:统计当天出现频率最高的十个关键词,标注跟昨天相比的新增词。
- 分类清单:按 cs.CV、cs.RO、cs.LG 分列全部论文标题。
主题聚集这块我用了一个小技巧:把昨天的关键词频率存下来,今天做差集,新增的词单独标出来。2026-09-14 这一期里,“world model”和“VLA”就是新增的高频词,说明当天有不止一篇论文在往这个方向靠。
4.4 2026-09-14 这一期的实际产出
拿这一期举例,当天 cs.CV 有 87 篇新论文,cs.RO 有 34 篇,cs.LG 有 112 篇,合计 233 篇。打分排第一的是一篇关于 3D 场景重建的工作,关键词命中“3D Gaussian Splatting”“real-time”“reconstruction”,得分 14.5。排第二的是一篇机器人操作方向,命中“VLA”“manipulation”“generalization”,得分 13.2。
主题聚集显示当天最高频的词是“diffusion”(出现 41 次)、“transformer”(38 次)、“3D Gaussian Splatting”(19 次)。新增词里“world model”出现 7 次,比昨天多了 5 次,值得留意。这些数字单看没什么,但连续记录几周之后,就能看出哪些方向在持续升温、哪些在降温。
5. 常见问题与排查技巧实录
5.1 拉取失败与限流处理
最常见的问题是请求返回 503 或超时。原因基本是两个:请求太频繁,或者网络波动。我的处理策略是加重试机制,用tenacity库或者手写一个简单的循环:
def fetch_with_retry(url, params, retries=3): for i in range(retries): try: resp = requests.get(url, params=params, timeout=30) if resp.status_code == 200: return resp except requests.RequestException: pass time.sleep(5 * (i + 1)) raise RuntimeError("fetch failed after retries")重试间隔用递增的方式,第一次等 5 秒,第二次 10 秒,第三次 15 秒。实测下来,绝大多数临时故障都能在三次内恢复。
5.2 关键词提取不准的调整
有时候一篇论文明明很重要,但打分很低,原因是它的摘要用词不在我的词表里。这种情况我一般先看摘要,如果确实是新方向,就把新词补进词表。还有一种情况是摘要太短,信息量不够,打分自然低。这种论文我会在报告里单独标一个“短摘要待查”的标签,提醒自己手动看一眼。
提示:词表不要一次性加太多词。我试过把词表扩到五百词,结果打分区分度反而下降了,因为太多词命中导致分数趋同。两百词左右是个比较舒服的规模。
5.3 报告可读性的优化
最初的报告是纯文本列表,读起来很累。后来我做了三处改进:一是给重点推荐加粗标题,二是用表格展示分类统计,三是把链接做成 Markdown 格式方便点击。还有一个小细节,作者名只显示第一作者加“et al.”,避免一行太长。
5.4 常见问题速查表
| 问题现象 | 可能原因 | 解决方法 |
|---|---|---|
| 返回 503 | 请求过于频繁 | 增加 sleep 间隔,加重试 |
| 摘要为空 | XML 解析异常 | 检查 feedparser 版本,打印原始 entry |
| 打分普遍偏低 | 词表覆盖不足 | 补充领域新词 |
| 报告里论文重复 | 多分类交叉 | 按 arXiv ID 去重 |
| 日期对不上 | 时区偏差 | 本地按 published 字段过滤 |
去重这块补充一句:一篇论文可能同时挂在 cs.CV 和 cs.LG 下,拉取时会重复。我的做法是用entry.id做唯一键,存进字典去重。这个坑我踩过一次,报告里同一篇论文出现两遍,看着很别扭。
6. 从日报到趋势:这套流程还能怎么用
跑了一段时间之后,我发现这份日报的价值不止于当天。把每天的 JSON 存下来,积累几周就能做趋势分析。比如统计某个关键词在两周内的出现频率变化,画一条曲线,就能看出方向的热度走势。我用 matplotlib 画过“3D Gaussian Splatting”的三十天词频曲线,从零星出现到每天十几篇,拐点非常明显。
另一个扩展方向是做作者追踪。把同一作者的多篇论文串起来,能看出他最近在做什么。我有几个关注的研究者,就是通过这种方式发现他们转向了新方向。实现上很简单,在 JSON 里按作者名建索引就行。
还有一个用法是给组会做素材。每周把七天的报告合并,挑出打分最高的二十篇,打印出来当组会讨论清单。比临时找论文效率高得多。
我个人在实际操作中的体会是,这套流程最大的价值不是省时间,而是建立了一种稳定的信息摄入节奏。每天固定时间看一份结构化的简报,比随机刷网页更容易形成领域感觉。工具本身不复杂,关键是坚持跑、持续调词表、定期回看积累的数据。如果你也在做类似的事情,建议先从最小可用版本开始,跑通之后再逐步加功能,别一上来就追求大而全。