每次刷 X 或 Hacker News,总能看到开发者在争论 AI 生态的两极叙事。一边坚信我们正处在一个永久的超级周期里,另一边则警告说,巨额的 GPU 资本开支若没有成比例的软件收入做支撑,必将引爆一场类似互联网泡沫的崩盘。与其在社交平台上选边站,我决定用一个理智的工程师方式解决问题——自己搭一个轻量级、实时的指标仪表盘,用数据来追踪这一切。于是就有了 AI Stock Bubble Index。
这篇文章会完整拆解整个项目的架构决策、客户端性能优化技巧,以及数据管道中遭遇的难题——比如通过本地代理爬取 Google News RSS 还不会被限流——以及为什么在面对一个数据密集型的工具站点时,最终选择了完全零后端、纯 JAMstack 的路线。
![]()
从一开始,我就给自己定下了一套严格的架构纪律。整个技术栈看起来异常简洁:Google News 与财经信息源作为数据源头,经 Node.js ESM 刮刀配合代理抓取,再通过术语匹配与权重计算,产出 JSON 静态资产,最终由 React hydration 渲染成交互式仪表盘。每一步都尽量向静态资产靠拢,避免任何运行中的服务端逻辑。
第一个真正的技术挑战,是获取外部信息流而不让瓶颈或代理故障毁掉数据采集。平台的核心能力之一,就是自动发现关于 AI 资本开支、估值、营收和模型发布的相关头条。如果你曾尝试用 Node.js 去抓取 Google News 的 RSS(https://news.google.com/rss/search?q=...),就会知道那是个雷区。尤其是当你用 Node 18 以上的版本,试图使用环境变量中的 HTTPS_PROXY 配合原生的 fetch() 方法时,它一定会抛出 UND_ERR_CONNECT_TIMEOUT。
这背后的原因在于,Node 的全局 fetch 是基于 undici 实现的,而 undici 为了严格遵循 Web API 规范,会刻意忽略系统环境代理设定。要解决这个问题,必须显式传入 dispatcher,或者直接在请求逻辑里使用 ProxyAgent 来指定代理。于是我在代码里明确导入了 node:fs、fast-xml-parser 和 undici,并初始化了一个指向本地代理 127.0.0.1:7890 的 ProxyAgent 实例。在 fetch 调用中,将这个 agent 作为 dispatcher 传入,让 undici 能够从受限网络下通过本地隧道完成请求。
这还只是抓取阶段的第一步。Google News RSS 本身对请求频率也有隐式的限制,过快地连续请求会触发验证码或直接拒绝连接。为了避免被列入黑名单,我在每次请求之间加入了基于指数退避的随机延迟,并为不同的搜索关键词分批拉取。把搜索词切分成更小的批次,每批之间留出足够的冷却时间,这样既保证了数据覆盖率,又没有触发风控。
第二个挑战,是如何从海量的新闻标题中,提取出真正与“AI 泡沫”相关的那一小部分,而不是把所有提到 AI 的报道都收进来。我在管道里设计了一个术语匹配与权重引擎。首先定义了一套种子关键词,像“资本开支”、“GPU 集群”、“估值泡沫”、“营收不及预期”、“模型变现”等,并为每个词赋予不同的权重。当一篇文章的标题或摘要中标中多个关键词时,权重会叠加,达到阈值的才被认定是相关信号。为了减少误报,还加入了一些否定词表,比如“游戏显卡”、“AI 绘画课程”这类明显不相关的噪声。
这个权重引擎是整个项目中少数需要一点“后端智能”的地方,但它依旧被设计成在构建时预计算。整个语料抓取下来之后,在 Node 脚本里跑完匹配和打分,结果直接写入静态 JSON 文件。也就是说,网站上线后,所有数据的“思考”过程都已经在构建阶段完成,用户访问时只是一个纯粹的静态资源服务,没有任何运行时的计算开销。
这也直接带出了第三个核心决策:完全的 JAMstack 与客户端性能优化。为了避免任何后端服务器维护,我把生产出的 JSON 数据推到一个 CDN 上,前端使用 React 写成单页应用,通过 fetch 直接从 CDN 加载最近一次构建的指数数据。这样一来,仪表盘的刷新并不依赖实时的服务端查询,而是靠定时的静态构建来驱动。为此,我设定了一个 GitHub Actions 工作流,每隔几个钟头自动运行一次抓取和权重计算脚本,把新的 JSON 资产部署到 CDN,并触发前端页面的 stale-while-revalidate 策略。
在前端性能上,为了不让体积庞大的 JSON 堵塞首屏,我做了两步处理。首先,将指数数据按日期分片,首屏只加载最近七天的聚合结果,其余的历史数据在用户主动切换时间范围时才按需拉取。其次,利用 React 的 hydration 机制确保初始 HTML 是预渲染的,用户在 JavaScript 完全加载之前就已经能看到上一次构建留下的静态骨架,几乎没有白屏时间。
这样的设计也并非没有妥协。因为完全依赖静态构建,数据存在最多几个小时的延迟,但对于追踪宏观的资本开支、估值趋势这类信号来说,几小时的滞后完全可以接受。相比之下,零数据库、零服务器运维、甚至零托管成本换来的稳定与省心,才是这个项目最核心的价值。
回顾整个构建过程,最深刻的教训可能不是技术细节,而是工程取舍的直觉。当你面对一个看起来需要实时流处理、复杂后端管道的仪表盘需求时,回归静态文件和定时构建常常是更稳健的起点。把“推送”换成“拉取”,把“运行时计算”换成“构建时计算”,不仅降低了系统复杂度,也极大地缩小了故障面。对于独立开发者或小团队的数据观察工具来说,这或许是一个被严重低估的范式。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.