我做了个东西,从一个来源拉数据,清理它,然后把它展示得比原站更好。标准工作。
然后我查询了系统里第二大的条目。其他所有条目都返回了几百个结果。这个:零。不是坏了。就是空的。
我以为是我搞砸了。把代码查了三遍。直接测了接口端点。这个条目在他们界面里存在。它只是……空心的。
就是从那时起,我开始往下挖。
那个来源看起来很完整。范围广,界面打磨过,API 干净。但自愿参与意味着会有一些洞,是你从文档里看不见的。
三个竞争对手都有同一批实体的数据。完整记录。所以信息在某个地方存在。
不是你缺少一个接口端点。是那个接口端点缺少现实。
我问了一个没人想到要问的问题:这些数据在互联网之前住在哪里?
答案是:印刷期刊。档案。自 19 世纪以来一直运行的模拟格式。每周出版三次。没有结构化数据,只有网站上的文档。
所以我下载了一份。密集的机构腔文本,公告埋在各个下属办公室之间。数据在那里。
我的竞争对手已经手工做这件事三十年了。
我用一个下午写了个爬虫。一半是好奇,一半是较劲。
文档解析才是真正开始疼的地方。
一个词会被软连字符切开:Unicode U+00AD,眼睛看不见,对每个 regex 都致命。你盯着屏幕,以为是自己的 pattern 错了。不是。文本里藏着一个幽灵字符。JavaScript 的 \w 不匹配非 ASCII 字符,所以普通单词会变成不可能命中的匹配。数字里有渲染器留下的幻影空格:"20. 000",而不是 "20.000"。
每个 bug 花在找到上的时间都比修复更久。文本抽取永远是这个比例:90% 侦探工作,10% 代码。
十条记录从噪声里显形。日期、标识符、地点,全都在该在的地方。我跑了两遍,确认自己不是在幻觉。结果一样。它真的能用。
解析让你看见那里有什么。我开始找那里没有什么。ID 是连续的。我把它们枚举了一遍。
53% 是死的。系统会清除已经结束的条目:没有档案,没有历史。有些记录存在,但没有任何支撑文档。答案是:请亲自来。2026 年了。
这个来源不是数据库。它是一扇窗口,而且有人一直在把它关上。
第一个数据源塑造了架构。第二个数据源击碎了每个假设。
我需要第二套架构。这是一种客气的说法,意思是第一套其实并不是架构,只是一个刚好适配某个场景的可用方案。那个奇怪的来源揭示了真相:你为手上已有的数据而建,不是为你将会遇见的数据而建。
这次我认真做了一套。Registry pattern,共享接口,基础契约,让每个实现都能忠于自己的形状。
这个架构更好,是因为我等了。如果我第一天就做它,我只会为我唯一认识的来源设计。第二个来源,那个奇怪的来源,逼我找出真正重要的东西。
你无法为未知设计。但未知抵达时,你可以重构。
架构教我怎么建。市场教我为了什么而建。
我要进入的是一个有三十年老牌玩家的市场。他们的技术看起来像 2005 年。他们的护城河不是技术,而是信任、品牌认知、几十年积累的数据。
那个现代竞争者三年前带着 AI 和漂亮 UI 入场。价格低于老牌玩家。三年后,老牌玩家仍然占主导。事实证明,更便宜并不自动意味着定位更好。
锚定很重要:第一个价格会成为参照点。之后降价容易,涨价几乎不可能。订阅本身不是产品,它只是通向背后东西的门。
我把价格定高。之后总能降下来。
四个教训,压缩版:
- 权威不等于完整。 主来源缺了整整一块。数据存在,只是不在任何人预期的地方。
- 第二个来源会显露你的架构。 只有当某个东西拒绝你建出的形状时,你才会知道设计的真相。
- 数据不是永久的。 如果你需要它,存下来。来源不会替你存。
- 为你正在变成的东西定价,而不是为你现在是什么定价。 订阅是一扇门。把门后面的东西建出来。
有意思的工作住在缝隙里。我也住在那里。

评论