暗无天日

=============>DarkSun的个人博客

r11y:一行命令把网页变 Markdown

flarework.com 上介绍了一个叫 r11y 的工具,看完觉得这就是我要的东西,一个能从命令行把 URL 转成干净 Markdown 的工具,运行速度快,输出简洁,适合给 LLM 和 Agent 场景使用。

是什么

r11y 是一个 GraalVM 原生编译的 CLI 工具(Clojure 编写,MIT 许可),它能做的就一件事,给你一个 URL,返回干净的 Markdown。

名字的来源是「readability」的 i18n/a11y 式缩写,首字母加中间字母数加末字母。念出来是「oh rlly?」,你还记得那个经典的「O RLY?」猫头鹰 meme 吗。

o-rly-owl.png

为什么用

给 LLM 喂网页时,真正的痛点是 HTML 标签带来的噪音。有人测过,一篇博客从原始 HTML 到干净 Markdown,token 从 16k 降到 3k,省掉 60-80% 的浪费。这些浪费不只是成本问题,它还把真正的内容淹没掉,减弱了 attention 的效果。

r11y 编译成原生二进制(GraalVM),冷启动只需要 40ms 左右,不需要 JVM 暖机也没有 Node/Python 解释器启动。作者拿三个典型页面做了对比(各跑 5 次,含网络请求):

URL r11y defuddle trafilatura readability-rust
长文(~8k 词) 0.43s 0.74s 0.99s 0.57s
文档页(Cloudflare) 0.26s 0.54s 0.53s 0.36s
Next.js landing 0.30s 0.63s 0.52s 0.27s

不过网络延迟吃掉了大部分时间,纯看处理效率的话差距可能更大。

除了速度,它还处理了不少边缘情况。元数据提取这块,优先从网页里的 JSON-LD(一种嵌在 HTML 中的结构化数据,搜索引擎用它展示富摘要)抓取,没有的话就退到 OpenGraph(Facebook 定义的协议,用来控制链接分享时的标题、描述和图片)、再到 Twitter Card(Twitter 版的 OpenGraph),最后还从 HTML 的 <time> 标签和 URL 里猜日期。一条链走到底,总有一个能命中。React/Next.js 那种 <div role="paragraph"> 语义 soup 会先归一化再提取。Cloudflare 有时候返回 Markdown 内容但标成 text/html ,r11y 也能识别。GitHub 仓库会自动拉 README,blob URL 则直接返回原始内容。

怎么用

安装很简单,macOS arm64 或 Linux x86_64 直接用 brew,

brew install dazld/tap/r11y

或者从 GitHub Releases 页下载静态二进制。

基本用法就一行命令,

r11y https://example.com

输出 Markdown 到 stdout,可以直接 pipe 进文件或另一个工具。

-m 参数还能带 YAML frontmatter,

r11y -m https://www.wired.com/story/some-article/

出来的结果大概是这样,

---
title: Intelligence on Earth Evolved Independently at Least Twice
author: Yasemin Saplakoglu
url: https://www.wired.com/story/intelligence-evolved-at-least-twice/
date: 2025-05-11T07:00:00.000-04:00
---

除了当命令行工具用,r11y 也能当 Clojure 库来调用。简单说就是在你的 Clojure 项目里引入这个库,在代码中直接调用 extract-content-from-url 函数,不用走命令行。CLI 只输出 Markdown 文本,但库函数返回的是一个 Clojure map(可以理解为结构化数据容器),包含以下字段:

{:markdown "# Clojure\n..."                                           ; 正文 Markdown
 :links    [{:text "Why Clojure?" :url "http://..."} ...]              ; 正文中的链接(已去重排序)
 :images   [{:alt "" :url "https://..."} ...]                          ; 正文中的图片
 :metadata {:title "Clojure" :sitename "Wikipedia" :date "..." ...}}   ; 元数据

这样做的好处是,你一次调用就能拿到所有结构化的数据——纯文本拿去喂 LLM,链接列表拿去爬关联页面,图片和元数据分别存入索引。 :links:images 只来自正文而非导航栏/页脚等噪音区域,并且已经去重排序了。

注意 r11y 不执行 JavaScript,所以纯服务端渲染的页面没问题,但 SPA 应用(React/Vue 客户端渲染)需要先跑一轮 headless browser 拿到 HTML 再喂给 r11y。

原文作者拿它做两件事,新用户 onboarding 时自动爬客户网站填资料,以及批量文档摄入。对我自己来说最吸引我的是 Agent 循环这个场景,给 LLM 喂网页的时候不用再纠结 HTML 格式了。

CLI : Markdown : LLM : Web Scraping : Clojure