技术文章最危险的状态,不是明显报错,而是看起来仍然合理,关键步骤却已经失效。模型名下线、SDK 参数改名、官方页面迁移、示例依赖升级,都可能让一篇曾经正确的教程逐渐误导读者。只在文章底部写一个发布时间,无法回答它现在是否仍可信。
可持续的技术内容需要一条维护流水线:记录上次核验时间,监听外部变化,自动执行低成本检查,把风险文章送入人工复审队列,再根据搜索意图决定更新原 URL 还是另写新文。本文给出一套可落地的 技术文章过期检测 方法,并明确一个容易被滥用的边界:不能只改日期,假装内容已经更新。
一、先区分“时间旧”和“内容过期”
文章发布得早,不等于内容错误;昨天发布,也可能引用了已经废弃的接口。过期判断应基于证据,而不是只计算文章年龄。可以把信号分为四类:
- 时间信号:超过计划复审日期,尚未重新核验;
- 依赖信号:模型、API、SDK、框架或运行时发布新版本,或者旧版本进入弃用周期;
- 可执行信号:链接失效、代码构建失败、响应结构变化、截图与当前界面不一致;
- 用户信号:站内搜索无结果、读者反馈、错误日志或客服问题指向同一篇文章。
时间信号适合提醒,其他三类更接近真实风险。维护系统不应在 nextReviewAt 到期时自动修改正文,而应生成待办并保留检测证据。
二、为每篇文章保存 reviewedAt 与 nextReviewAt
最小内容记录至少包含:
{
"contentVersion": "1.3",
"publishedAt": "2026-05-10T02:00:00.000Z",
"updatedAt": "2026-07-18T08:30:00.000Z",
"reviewedAt": "2026-07-18T08:30:00.000Z",
"nextReviewAt": "2026-10-18",
"reviewedBy": "editor-id",
"reviewStatus": "verified"
}
这些字段职责不同:
publishedAt是首次发布时刻,通常不应改写;updatedAt表示正文或关键页面信息最近一次实质修改;reviewedAt表示最近一次完成事实、链接和示例核验;nextReviewAt是内部任务计划,不是搜索引擎指令;contentVersion用于关联修改记录、测试结果和回滚。
只打开文章看一眼,不应直接把 reviewedAt 往后推。复审动作应有检查项与结论,例如“官方 API 文档已核对、三个外链可访问、示例在 Node.js 22 执行通过”。如果检查失败,将状态改为 needs_update 或 blocked,而不是继续显示“已验证”。
复审频率按变化风险设置,比全站统一 90 天更合理。例如模型 API、价格和 SDK 教程可每月或每季度检查;基础算法概念可以半年或一年检查;出现官方弃用公告、代码失败或读者反馈时则立即复审。这里的周期只是站内策略,不是 SEO 排名规则。
三、从正文提取依赖,监听官方版本变更
版本监控不能只订阅新闻。发布时应把文章依赖转成结构化清单:
{
"articleSlug": "openai-compatible-multi-model-config-nodejs",
"dependencies": [
{ "type": "npm", "name": "openai", "tested": "5.x" },
{ "type": "runtime", "name": "node", "tested": "22.x" },
{ "type": "api", "name": "chat-completions", "tested": "2026-08" }
]
}
监控来源优先使用官方渠道:GitHub Releases API、官方 changelog、npm 包元数据、产品弃用公告和状态页。npm outdated 可以辅助发现本地依赖版本差异,但“出现新版本”并不等于文章已经过期。系统应先比较变化类型:
- 补丁更新且没有影响示例的变更,记录事件即可;
- 次版本新增能力,检查文章是否需要补充;
- 主版本、弃用通知或接口字段变化,提高复审优先级;
- 文章指定的版本仍受支持且搜索意图是旧版维护,可保留并明确版本范围。
不要让模型只根据版本号自动重写文章。模型可以总结 changelog、定位可能受影响的段落,但最终结论必须回到官方说明和实际测试。多模型配置的具体实现可以参考OpenAI 兼容 API 多模型统一配置,其中的 provider、模型名和端点都应该成为可监控依赖。
四、链接检查不仅看 HTTP 200
定时任务可从 Markdown、HTML 和 sources 数组提取 URL,检查以下状态:
- 404、410:目标已移除,应查找官方替代页;
- 301、308:记录最终地址,确认不是跳到无关首页;
- 401、403、429:可能是权限或反爬限制,不能直接判定内容不存在;
- 200:仍要检查最终 URL、内容类型和页面标题;
- 超时、DNS、TLS 错误:进入重试队列,连续失败后人工确认。
一个谨慎的检查器会限制并发、设置超时、遵守站点规则,并保留检测时间与最终跳转地址:
async function inspectLink(url) {
const startedAt = Date.now();
try {
const response = await fetch(url, {
method: 'HEAD',
redirect: 'follow',
signal: AbortSignal.timeout(8000),
headers: { 'user-agent': 'ContentFreshnessBot/1.0' }
});
return {
url,
status: response.status,
finalUrl: response.url,
checkedAt: new Date().toISOString(),
durationMs: Date.now() - startedAt
};
} catch (error) {
return { url, error: error.name, checkedAt: new Date().toISOString() };
}
}
有些服务器不支持 HEAD,出现 405 时需要用受限的 GET 复查。链接变更后还要确认新页面确实支持原文结论;把失效来源换成主题相近的页面,并不能完成事实核验。站内链接则应在每次构建时检查,具体的孤儿页与锚文本治理可参考技术博客文章内链设计。
五、代码回归要固定环境、输入与断言
代码块语法正确,不代表教程还能完成目标。可执行示例应拆成独立 fixture,记录运行环境和期望结果,并在依赖变更或复审时执行:
import assert from 'node:assert/strict';
import { normalizeModelConfig } from './example.mjs';
const result = normalizeModelConfig({
provider: 'compatible',
baseUrl: 'https://example.invalid/v1/',
model: 'demo-model'
});
assert.equal(result.baseUrl, 'https://example.invalid/v1');
assert.equal(result.model, 'demo-model');
回归记录应包含 commit、Node.js 与依赖版本、测试命令、退出码以及失败摘要。涉及真实 API 时,不要把密钥写进仓库;使用隔离测试账号、最小请求和费用上限。无法稳定调用外部服务时,可以分别做 schema 校验、模拟响应测试和少量人工连通测试。
当回归失败时,先区分文章错误、示例仓库错误和上游临时故障。对 AI 接口的 429、超时与 5xx,可以沿用大模型 API 429、超时和 5xx 排查中的错误分类,避免一次网络波动把文章误判为过期。
六、建立有证据的复审队列
复审队列的每个任务应回答“为什么需要看这篇”,而不是只列标题。建议字段包括:
{
"articleSlug": "example-slug",
"reason": ["review_due", "major_release", "code_failed"],
"evidence": ["release-url", "ci-run-id"],
"risk": "high",
"status": "queued",
"owner": null,
"createdAt": "2026-08-13T12:00:00.000Z"
}
优先级可以由可解释的分数组成:核心代码失败权重最高,官方弃用与安全变更其次,仅到复审日期的权重较低;再结合页面访问量、业务关键程度和最近用户反馈排序。分数只帮助排队,不替代编辑判断。
任务状态可以使用 queued → investigating → updating → validating → reviewed → published。失败证据、负责人、复审备注和最终修改摘要都应保留。若多人或多个 Agent 并行维护,使用 slug 加内容版本作为幂等键,避免同一文章被重复改写。质量评估方法可与AI 总结质量评估与回归测试共用固定样例和审核门槛。
七、什么时候更新旧 URL,什么时候写新文章
判断标准不是“改动大不大”,而是用户搜索意图是否仍然相同。
适合更新原 URL 的情况:
- 同一任务的参数、界面或代码发生变化;
- 原结论被新证据修正,但读者仍在寻找同一个答案;
- 旧写法已弃用,需要替换并说明迁移路径;
- 文章结构需要重写,但主题与目标读者不变。
原 URL 已积累外链、收藏和站内引用。更新时保留它,可以避免制造两篇同意图页面。必要时在正文增加“适用版本”和更新记录,不要悄悄抹去历史边界。
适合发布新文章的情况:
- 新旧版本对应不同任务,且旧版本仍有独立读者;
- 新主题形成新的搜索意图,例如“迁移指南”不同于“从零配置”;
- 新内容需要长期独立维护,无法在原文中清楚表达;
- 旧页面是历史档案或故障记录,不应被覆盖。
新文章发布后,应建立明确双向内链;如果旧页面已经没有保留价值,可把它重定向到最匹配的新页面。不要仅为增加页面数量复制旧文并替换年份或模型名。
八、dateModified 只在实质修改后更新
Google 的文章日期指南强调页面需要显示清晰日期,并建议结构化数据中的日期与页面可见日期保持一致;同时也明确提醒,不要因为文章没有实质变化就人为刷新日期。Schema.org 的 dateModified 表示创意作品最近修改的日期或时间,不是“今天重新发布”的按钮。
可以更新 dateModified 的例子:
- 修正已经失效的 API 配置并重新测试;
- 重写关键章节以覆盖新的主版本;
- 添加会改变读者决策的重要事实、限制或迁移步骤;
- 修复实质性错误,而非只改标点。
通常不应更新的例子:
- 自动任务重新抓取了相同内容;
- 只修改排版、空格或无关样式;
- 仅更换广告、推荐卡片或页脚;
- 没有复审正文,只把日期改成今天。
页面可见的“更新于”、Article JSON-LD 的 dateModified、站点数据中的 updatedAt 应指向同一次实质修改。datePublished 保留首次发布日。Sitemap 的 lastmod 也应反映页面最后一次重要修改,而不是每次构建时间。这样做是为了向读者和爬虫准确表达页面状态,而不是保证排名提升。
九、一次完整复审怎么执行
建议将复审固定为以下步骤:
- 读取触发原因、历史版本和上次测试记录;
- 打开所有关键官方来源,核对当前版本与弃用信息;
- 检查站内外链接及跳转后的实际页面;
- 在记录的环境中运行核心代码和断言;
- 标记仍有效、需修改、需删除和暂时无法确认的结论;
- 决定更新原 URL、另写新文、合并或下线;
- 修改正文、摘要、标题、结构化数据与相关内链;
- 人工审核后更新
reviewedAt,按风险设置nextReviewAt; - 只有发生实质修改时更新
updatedAt与dateModified; - 保存修改摘要、证据和测试结果,发布后检查页面与 sitemap。
复审时还应检查是否与站内其他文章形成重复。可以借鉴AI 内容去重:URL、标题相似度与内容指纹先发现候选,再由编辑按搜索意图判断是否合并。
十、维护仪表盘应关注什么
一个实用仪表盘不必先追求复杂图表,至少应回答:
- 已超过
nextReviewAt的文章有多少; - 哪些文章收到主版本、弃用或安全事件;
- 链接检查与代码回归最近何时成功;
- 高风险任务积压多久、由谁负责;
- 每篇文章的当前版本和最近修改摘要是什么;
- 哪些文章因证据不足被标为待确认。
这些数据衡量的是维护过程,不是搜索效果承诺。流量下降可以成为调查信号,但不能单独证明文章已过期;同样,流量稳定也不能证明配置仍然安全。把维护事件接入日志、指标和告警时,可以继续参考AI 内容管线可观测性。
结语
技术文章的可信度来自持续核验,而不是发布日期看起来很新。以 reviewedAt 和 nextReviewAt 管理责任,用官方版本变更、链接检查和代码回归发现风险,再通过可解释的复审队列处理,才能让内容库长期可维护。
最重要的规则只有两条:搜索意图不变时优先更新原 URL;页面没有实质变化时,不要刷新 dateModified。维护记录真实、证据可追溯,比制造“常新”的日期更有价值。