尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Emacs浏览器接入LLM:把杂乱的网页变成结构化知识

Emacs浏览器接入LLM:把杂乱的网页变成结构化知识 先从一个很具体的场景说起。你在 Emacs 里用 EWW 打开一篇技术文章页面确实能显示链接也能点但你的第一反应大概率是这排版也太朴素了。图片基本缺席侧边栏被拍平广告和导航区块混在文本里光标在一大段没完没了的文字中移动你得先花几秒钟判断“正文到底从哪里开始”。过去遇到这种情况大多数人的反应是Emacs 的浏览器就是不行还是老老实实切到 Chrome。但如果把标题里的 “Make the Emacs Web Browser Great Again” 当成一个技术问题来认真看你会发现它真正要解决的根本不是渲染而是信息提取。EWW 从来不缺文本缺的是从杂乱网页里把“值得读的部分”找出来的能力。而 LLM 恰好擅长做这件事。把两者接起来Emacs 浏览器反而可能成为目前最适合做深度阅读和技术研究的内容消费工具。这篇文章会从 EWW 的文本化逻辑讲起给出一个把 LLM 接入 Emacs 浏览器的最小闭环再展开到批量阅读、知识库沉淀、本地模型和云端 API 的选型以及落地时最容易踩的坑。整体思路是先运行通一条链路再逐步扩展成真正可长期使用的网页工作流。1. 为什么说 Emacs 浏览器的问题不在“浏览器”而在“信息提取”1.1 EWW 的真实身份一个文本渲染器而不是浏览器严格来说Emacs 内置的 EWWEmacs Web Wowser不做完整页面渲染。它把 HTML 拉下来用 shr 等文本渲染机制把网页转成纯文本 buffer。这个设计在早期看起来像缺陷但实际上是一种取舍浏览器要展示视觉复杂、交互丰富的页面而 Emacs 要提供的是可编辑、可检索、可组合的文本上下文。所以 EWW 里最常见的体验是打开一个现代网页图片变成占位符CSS 布局基本失效JS 效果不会执行剩下的是一大段连续文本。它不像浏览器更像是一个“网页转文本”的转换器。这个特性决定了 EWW 的适用边界适合阅读以文字为主的页面比如技术博客、文档、论文、新闻。不适合操作复杂前端应用比如在线表单、拉表格、可视化控制台。适合把网页内容复制进 org-mode 做笔记不适合做“看起来像原网页”的展示。换句话说EWW 本来就不是给“视觉浏览”设计的。它的优势在于网页内容一旦变成文本 buffer就可以被 Emacs 里几乎所有工具处理org-mode、isearch、avy、embark、甚至自定义 Lisp 函数。但这也是问题所在网页文本里混入了大量噪声正文、导航、评论、推荐阅读、cookie 弹窗全部挤在一起。1.2 真正的瓶颈网页是写给眼睛看的不是写给编辑器看的网页设计的核心目标是视觉组织。人类用眼睛扫一眼就能区分标题、正文和侧边栏但这段文本丢进 EWW 后所有视觉层次全部丢失只剩结构扁平的字符串。你可以用正则去匹配标题、链接、段落但面对一个格式混乱的真实网页正则很快就会失效。这也是传统自动化网页抓取的老问题每换一个网站几乎都要重新适配一次。如果只是想在自己电脑上读几篇文章这种适配成本太高了。LLM 改变的是这一层。它不需要你精确写规则而是理解“网页正文”这个概念。你给它一段 EWW 产生的杂乱文本它能够识别出哪些是导航哪些是广告栏哪些是真正的内容它还能进一步做总结、提出问题、抽取关键信息甚至按固定格式输出。所以标题里的 “Great Again” 并不是说 EWW 会在渲染上追上 Chrome而是说当 LLM 参与进来之后Emacs 浏览器第一次拥有了把“文本”变成“结构化知识”的能力。这个能力在视觉浏览器里不一定存在因为浏览器默认把网页当作展示对象而不是当作知识原料。1.3 LLM 补上的不是“速度”而是“语义结构”传统浏览器解决的是把 URL 变成可视化页面。LLM 浏览器解决的是把 URL 变成可理解、可处理、可沉淀的内容。这两者完全是不同的事情。你可以在 Emacs 里保留 EWW 的极简浏览体验然后把 LLM 放在中间层第一步EWW 拉取页面文本。第二步清洗掉过长空白、脚本残留、无关区块。第三步把文本交给 LLM让它输出正文摘要、关键术语、操作步骤或待办事项。第四步结果插入到当前 buffer或追加到 org 文件作为阅读笔记。这个链路里LLM 的角色不是“生成网页”而是“阅读网页”。它替代的不是浏览器而是你前 30 秒的扫读和判断。这才是这类项目最大的价值节省的不是打开网页的时间而是决定“这篇文章值不值得读、重点是什么、要不要记录”的判断时间。2. 把 LLM 接入 EWW从文本清洗到总结输出的最小闭环2.1 前置准备确认 EWW 环境和 LLM 服务可用先说前置条件。EWW 是 Emacs 内置模块通常不需要额外安装通过M-x eww输入 URL 即可打开。如果你已经使用 Emacs建议先确认Emacs 版本不能太老建议使用比较新的稳定版本。确认eww命令可以正常打开普通 HTTP/HTTPS 页面。确认本机网络环境允许访问目标页面。确认你有一个可以调用的 LLM 服务可以是本地模型服务也可以是一个兼容 OpenAI 协议的 API 服务。在把 LLM 接入 Emacs 前先用命令行验证服务是否可用。例如一个常见的本地模型服务默认监听在 127.0.0.1 的 8000 端口可以通过 curl 验证curl -s -X POST http://127.0.0.1:8000/v1/chat/completions \ -H Content-Type: application/json \ -d { model: local-model, messages: [{role: user, content: 这是测试请回复 OK}], max_tokens: 10 }如果返回结果正常说明你的 LLM 服务可以继续使用。这一步很重要因为后续在 Emacs 里调试接口会更麻烦先在外面把接口跑通能节省大量时间。2.2 最小示例把 EWW 页面文本发送给 LLM现在进入核心环节在 Emacs 里写一个简单的 Lisp 函数把当前 EWW buffer 的文本发送给 LLM并把返回结果展示出来。以下是一个示意结构重点是理解链路而不是直接照抄。不同 LLM 服务的接口地址、模型名称和请求格式可能不同使用前要适配。(defun eww-llm-summarize () Send current EWW page text to an LLM service and show a summary. (interactive) (let* ((page-text (buffer-substring-no-properties (point-min) (point-max))) ;; 把连续空白压缩一下减少 token 浪费 (clean-text (replace-regexp-in-string [ \t] page-text)) ;; 先截断避免超出模型最大上下文 (truncated (substring clean-text 0 (min (length clean-text) 4000))) (prompt (concat 这是网页文本请提取核心要点并输出 Markdown 格式\n\n truncated)) (payload (json-encode ((model . local-model) (messages . [((role . user) (content . ,prompt))]) (max_tokens . 800) (temperature . 0.3)))) (result-buffer *LLM Summary*)) (with-temp-buffer (shell-command (concat curl -s -X POST http://127.0.0.1:8000/v1/chat/completions -H Content-Type: application/json -d payload ) t) (goto-char (point-min)) ;; 这里只做了最粗糙的 content 提取实际使用需要完整解析 JSON (when (re-search-forward \content\:\\\([^\]*\\)\ nil t) (let ((summary (match-string 1))) (with-current-buffer (get-buffer-create result-buffer) (erase-buffer) (insert summary) (goto-char (point-min))) (display-buffer result-buffer))))))这个函数的问题很明显直接用substring截断文本可能把关键内容切掉。没有处理 JSON 转义如果网页文本里有双引号或反斜杠payload 会出错。没有解析完整 JSON 响应只用正则找content字段不稳定。没有处理请求失败、超时、模型不存在等情况。所以它只能算最简验证。但它的价值在于把“EWW 网页文本”和“LLM 输出”之间的管道打通了。一旦这条链路通了后面的优化都能在上面的基础上逐层做。2.3 从单页总结到批量阅读把结果写进 org-mode跑通单页总结后下一步不是急着让它变好看而是考虑怎么把结果沉淀下来。一个很自然的做法是在阅读多篇文章时把每页的 LLM 总结追加到同一个 org 文件形成一份带来源链接的阅读笔记。可以设计成这样的流程在 EWW buffer 中执行eww-llm-summarize获得当前页面的总结。同时把当前页面的 URL 抓出来插入到 org 文件条目中。按日期或主题组织多个条目。伪代码思路(defun eww-llm-save-to-org () Append LLM summary of current page to an org file. (interactive) (let* ((url (plist-get (cdr (assoc url (eww-data))) :url)) (title (plist-get (cdr (assoc title (eww-data))) :title)) (summary (eww-llm-get-summary)) (org-file ~/reading-notes.org)) (with-current-buffer (find-file org-file) (goto-char (point-max)) (insert (format \n* [[%s][%s]]\n%s\n url title summary)) (save-buffer))))在实际项目里你有两种选择一是把所有逻辑写在一个函数里界面保持简单二是拆成独立模块比如eww-llm.el专门负责请求和解析另一个文件负责 org 写入。如果只是个人用前者就够了如果想让其他 Emacs 用户使用更建议拆清楚。关键点不是代码怎么写而是流程要确认页面 → 清洗 → LLM → 验证 → 沉淀。每一步都要能单独调试。3. 真正拉开差距的不是“总结”而是“网页工作流”3.1 让 LLM 成为你的“阅读代理”很多文章讲 LLM 浏览器都会把重点放在“总结”。但总结只是最浅的一层。真正有价值的是把网页变成一个可以执行任务的原料。我一般会先让 LLM 做三件事而不只是总结判断这篇文章值不值得读。让它输出一个“推荐指数”和“适合人群”避免你在无关文章上浪费时间。抽取关键信息。比如一篇工具发布博文让 LLM 输出核心功能、安装方式、适用版本、主要坑点、作者的结论。这样你不用再回头扫读原文。整理链接资源。页面上有一堆参考链接传统浏览器把它们展示为蓝色下划线文本你需要一个个点开看。LLM 可以根据链接锚文本和上下文按类别整理成清单比如“官方文档”“原文引用”“相关项目”。这个转变的本质是你不是在用浏览器“看网页”而是在用 LLM“替你读网页”。你在 Emacs 里看到的不是一个渲染后的页面而是几个人的判断和结论。3.2 从网页提取可操作事项让内容接入 org-mode阅读技术博客经常带着一个目的这篇文章里有没有我能直接用到的东西比如一个新的命令行参数、一段配置、一个修复 bug 的方法、一个值得跟进的项目。这些内容散落在页面各处手动提取很慢而且容易漏。LLM 可以做结构化提取。假设你面对一篇关于某个新工具的评测文章你可以让 LLM 输出## 核心结论 - 定位... - 适合场景... - 不适合场景... ## 使用方式 - 安装命令... - 最小配置... - 常用参数... ## 潜在风险 - ...然后用一个函数把这段 Markdown 插入到当前 org 文件里。这样你积累的不是“网页收藏夹”而是一份可检索、可执行的工作笔记。Emacs 最强的地方本就是文本管理LLM 把网页内容变成高质量文本后Emacs 的所有工具都能继续发挥作用。3.3 批量处理一组网页从“单页消费”到“主题研究”单页总结仍然偏轻。真正能体现 LLM 价值的是批量场景你有一组相关页面想让 LLM 帮你归纳多个来源的异同或者提取多个页面里的共同要点。比如你正在调研“当前有哪些本地 LLM 推理方案”你先用 EWW 或外部脚本收集十几篇相关页面然后对每一页调用一次 LLM得到每页的结构化笔记最后再把多份笔记合成一个对比表格。这个流程手动做会非常累但把单页链路跑通后批量只是循环和错误处理的问题。批量处理需要注意三点请求之间要控速不要一上来就把所有页面并发请求。每一页的 LLM 结果要单独保存避免一次失败导致全部重来。批量任务要先跑一两条样例确认输出格式稳定后再全量执行。用 Emacs 做这件事的优势是你可以把批量脚本和结果文件全部放在同一个环境中从网页拉取到最终笔记不需要切换应用。4. 本地模型 vs 云端 API先选对工具链再谈效果4.1 两类方案的核心区别把 LLM 接入 Emacs 浏览器你可以走两条完全不同的技术路线一个是调用云端 API。优点是省事不需要准备显卡或推理环境模型能力通常更强。代价是页面内容要发到外部服务涉及隐私问题如果阅读量很大成本也需要关注。另一个是在本地跑模型服务。优点是可以处理敏感内容数量不限也不依赖网络。代价是硬件要求高模型能力可能弱一些部署和升级需要维护。这里不针对具体供应商只从通用策略上做判断如果只是自己阅读技术文章不涉及隐私可以先从云端 API 开始跑通链路再说。如果你读的是内部文档、公司代码库说明、未公开资料就更适合本地模型。如果你希望在批量任务中长期跑本地模型往往更划算但要接受输出质量可能低于云端大模型的事实。4.2 一个判断表格从四个维度做选择维度本地模型云端 API部署复杂度较高需要安装推理框架、下载模型、管理显存较低注册服务即可调用隐私安全数据不出本机适合敏感内容内容会发送到服务端需要评估长期成本硬件投入为主跑量大后更可控按调用量计费长期高频使用成本可能明显输出稳定性依赖模型参数和硬件效果波动更大通常更强但不同服务差异很大如果你的目标是先快速看到效果一条更稳妥的路径是先用一个可用的 API 把 EWW → LLM 链路跑通。确认流程稳定后再评估要不要迁移到本地模型。迁移时先在一台本地机器上部署小规模服务用两三条样本对比输出质量。只有本地模型输出达到你能接受的程度才建议正式切换。不要一开始就在工具链上纠结太久。这个项目真正的工作量在流程、清洗和长期维护不在“选哪家模型”。4.3 面向团队场景API 和共享工具的边界如果你的场景不止个人使用而是想让团队里的其他人也能用同一套“网页 → LLM 笔记”的能力情况会复杂一些。Emacs 本身有一定使用门槛直接让团队每个人都配一套 Emacs 环境并不现实。常见的折中方案是保留 Emacs 侧的脚本给熟悉 Emacs 的成员使用。同时把整理后的结果放入一个共享的应用层比如使用支持网页访问的 LLM 工具站让不熟悉 Emacs 的人也能检索和阅读同样的笔记。具体工具选型会根据团队已有的技术栈变化这里不展开某一家产品的搭建细节。重点是Emacs LLM 很适合个人钻研但团队推广时需要有比 Emacs buffer 更容易访问的出口。5. 落地时最容易踩的几个坑与排查路径5.1 输入超长不是所有页面都能完整塞进模型EWW 渲染后的页面内容可能很长尤其是一篇长博客或被拍平的论坛帖子。直接截断到前 4000 个字符虽然简单但很可能把正文最核心的部分丢掉LLM 的总结质量会明显下降。更稳妥的做法是把页面按段落或标题拆成若干块分多次调用再把结果合成。实际使用中我会先做一个“正文提取”步骤也就是先把可能的导航、评论、页脚去掉再进入 LLM。这个预处理不一定严格但能显著降低 token 消耗。也可以利用 EWW 的 buffer 特点先通过fill-paragraph或正则把连续空白压缩再按段落边界切分。判断是否超出上下文以“字符数约为 4000 到 6000 之间”作为常见经验值具体要看模型最大上下文。5.2 请求失败先定位是哪一层出了问题把 LLM 接入 Emacs 后最常见的错误就是请求失败。排查时应按由外到内的顺序先用 curl 直接调接口确认服务是否活着。再检查 Emacs 发出的 payload 是否合法特别是双引号和反斜杠有没有转义。然后看模型名称是否匹配很多服务对模型名有严格校验。最后看响应内容是否被正确解析正则提取容易失败更稳妥的方式是用 JSON 解析库。整个链路的排查顺序大致是网络 → 接口 → 参数 → 返回格式 → 展示逻辑。不要第一步就去改 Lisp 代码。5.3 输出不稳定用格式约束和温度参数收敛结果LLM 输出本身具有随机性。做网页总结时最怕的是返回格式时好时坏一会儿 Markdown一会儿纯文本一会儿还给了一段无关的话。这不是 Emacs 的问题而是提示词和参数设计不够稳。可以这样做在提示词中明确输出格式甚至给出示例输出模板。把采样温度调低比如 0.2 到 0.4降低随机性。在代码中增加格式校验如果返回内容不是预期结构就重试一次。对重试次数做上限避免无限循环。这里特别想提醒不要因为一次输出不稳定就否定整个方案。LLM 应用普遍需要调提示词和参数Emacs 集成只是把你的工作流放到了更适合反复调试的环境里。5.4 一个可复用的故障排查顺序如果你要在自己环境里长期跑这套方案建议把下面这个顺序记下来作为标准排查链路先看现象是完全没有输出还是输出为空还是输出格式错误再看输入当前 EWW 页面的 buffer 内容是否正常有没有乱码、截断或过大。再看请求用 curl 手工构造同样的请求确认服务端有没有正常返回。再看解析确认响应 JSON 被正确读出返回字段名是否匹配。再看流程如果所有单步都正常再检查函数之间的变量传递有没有断掉。这个顺序适用于绝大多数“Emacs 调用外部服务”的场景不只是 LLM。6. 把网页浏览从“视觉消费”变成“语义工作”6.1 从 EWW 到“LLM 原生浏览器”的演进方向这个项目真正值得关注的不是某一段 Lisp 代码而是它代表的一种产品方向浏览器不再只是让你看网页而是帮你理解网页。传统浏览器花大量精力做像素级渲染但在信息过载的时代用户需要的是“内容优先”的阅读体验。EWW 原本只做了文本化但它天然适合承接这一层变化。当你在 EWW 里打开页面时内容已经是一段可编辑文本LLM 加进来后这段文本可以被重排、精简、结构化。未来类似的思路可能扩展到更完整的浏览器生态里比如在后台自动生成摘要、自动提取操作步骤、自动把文章转换成可问答的知识库。Emacs 的作用不只是编辑器也是一个“可编程的信息处理平台”。LLM 本身是一个无状态的文本接口而 Emacs 可以为它提供上下文、历史记录、任务列表和组织方式。这种组合的价值远大于“在一个网页里弹出一个 AI 对话框”。6.2 对个人知识库和研究流程的实际影响如果你平时依赖 org-roam、org-mode 或 Markdown 管理知识这套方案能改变你的阅读习惯。过去你需要在浏览器和笔记应用之间不断切换看到一篇文章复制关键段落回到编辑器整理。现在你可以在 Emacs 内部完成从浏览到总结再到存储的全过程而且总结之后的文本可以继续被检索和复用。长期积累下来你得到的不再是几十个浏览器书签而是一批有来源、有摘要、有判断的知识条目。LLM 的总结不一定完美但它给了你一个初始版本你只需要校对和补充而不是从零开始整理。6.3 现阶段最重要的边界最后必须说清楚适用边界。Emacs LLM 的方案非常适合技术博客、文档、论文、新闻等以文本为主的页面。需要快速判断文章是否值得深读的场景。需要把网页内容转成笔记或任务的研究流程。愿意花时间调试 Emacs 环境和个人工作流的用户。它不适合需要完整视觉还原的页面。大量依赖 JavaScript 交互的应用。希望浏览器自己完成所有判断、完全不检查 LLM 输出的场景。追求零配置开箱即用的用户。换句话说这套方案并不是要让 Emacs 变成一个现代浏览器。它要做的是让 Emacs 环境里的“阅读”和“知识管理”变得前所未有的顺畅。你仍然可以保留 Chrome 处理复杂页面但当你认真读一篇文章、做一个调研、沉淀一份笔记的时候Emacs LLM 会是一个比传统浏览器更有深度的选择。真正的 Great Again不是让 Emacs 浏览器去比拼渲染速度而是让它回到自己最擅长的事情上把网页当成文本把文本变成知识。
返回列表