Skip to content

05 自动建站与收录:把审核过的内容变成可检查、可撤回的页面 ​

这一环的输入应当是已经通过内容审核的页面记录,而不是模型刚刚吐出的草稿。输出也不只是一个网址:它包括可读 HTML、链接关系、资源文件、索引设置、版本清单和测试结果。这样,当下一轮实验需要换标题、改说明或恢复旧版本时,才能知道线上实际展示了什么。

本项目先做一个离线可运行的小站。它提供 Unix 时间戳转换器,以及解释秒和毫秒的英文指南。页面、样本和站点名称都是独立教学设计,没有复制来源文章的图片、品牌或模板;样本不代表真实关键词需求或商业成绩。代码只生成本地文件,不购买域名、不配置账户、不上传站点,也不向任何搜索引擎提交地址。

5.1 为什么第一版选择静态 HTML ​

内容站最先需要解决的是:用户点开地址后,能不能直接看到答案;维护者能不能确认页面由哪份内容生成。构建时生成 HTML,能让这两件事比较容易检查。正文、标题、来源和导航都在初始响应里,只有转换器本身需要 JavaScript。关闭脚本仍可读指南,但不能执行转换,这个限制也明确写在页面中。

三个常见方向都能做好 SEO,区别主要在开发与运行成本:

方案适用情况需要承担的工作
本项目的 Python 静态生成器两三种模板、内容更新不频繁、先验证流程编辑体验简单;全站重建;没有账户、服务器端搜索或个性化
Astro以内容为主,需要组件与少量交互管理 Node 依赖、内容集合和构建;按需渲染需适配器
Next.js已有 React 应用,内容与动态产品紧密结合管理服务端/客户端边界、缓存和水合;静态导出不支持所有运行时功能

Astro 官方文档说明默认在构建时预渲染,也允许页面按需渲染;Next.js 静态导出会在构建期执行对应的 Server Components,输出可以由静态服务器托管的文件。具体限制应按项目锁定版本核对,不能把框架名字等同于“搜索引擎友好”。[T01][T02]

若未来工具需要保存用户数据,应先界定哪些页面仍可静态提供,哪些请求需要服务端授权,再增加动态部分。不要为了一个换算工具提前引入登录系统、数据库 API 和整站客户端渲染。反过来,价格、库存或权限确实需要实时判断时,静态导出也不应被当作万能方案。

**验收方法:**对文章地址直接发 HTTP 请求,检查返回内容里已有标题、主体与可点击的普通链接;再开启脚本,比较渲染后内容有没有被清空或改错。Google 能处理不少 JavaScript 页面,但初始 noindex 可能令其跳过后续渲染;不能指望脚本再移除它。[T03]

5.2 页面记录就是模板合同 ​

seo_loop.site.build_site(pages, output_dir, base_url, preview=True) 接受普通 Python 字典列表。它不会执行模型生成的模板、脚本或 shell 命令。

必需字段包括:id、slug、title、description、body、sources、updated_at、kind、topic。正文只能是纯文本字符串或非空字符串列表;字符串按空行分成段落。locale 缺省为 en-US,version_hash 可选。每个来源需要 id、url、title,没有外链来源时允许空列表,但内容审核仍应单独判断是否缺证据。

  • id 是内容身份,不随标题变化。
  • slug 是稳定相对路径,只接受小写字母、数字、连字符和受控的目录层级。保留路径、重复路径、路径穿越、百分号编码和祖先/子页面冲突会被拒绝。
  • updated_at 表达实质内容更新时间。日期可以写成 ISO 日期;带时间则必须明确时区,不接受未来时间。
  • kind 仅为 guide 或 tool。当前工具模板专用于 Unix 时间戳转换;扩展到其他工具前应增加单独类型、模板和测试,不能只换标题。
  • topic 用于主题页与相关文章入口。原型给主题生成稳定哈希路径,避免任意文本进入路径;正式站可增加持久 topic_slug 映射改善可读性,迁移时保留旧地址映射。

translation_group 是可选的真实翻译关系声明,不是“同一关键词”的分组。一个组至少有两个已生成页面,且语言地区不能重复,才输出语言关联标签。代码只验证结构,不会证明两篇内容语义等价,也不会识别英语正文被错误标成中文的情况;这些仍由编辑审核负责。

缺字段和非法值应在写文件前失败。不要用“未知”补标题、把错误日期变成今天、把错误规范网址回退到首页。这样的宽容会把一次数据错误扩散到整个站点。

5.3 从记录到可用网页的构建过程 ​

生成器先校验全部输入,再在输出目录旁创建独立版本目录。所有文件写完后,它计算逐文件 SHA-256,写入 build-manifest.json,最后用文件系统的原子替换切换输出符号链接。构建或切换失败时清理新目录,旧版本不动。测试已经注入过切换失败,确认旧输出和链接目标保持一致。

这里的“原子”指受支持文件系统上的本地目录入口切换,并不代表数据库事务与文件切换构成一个共同事务,也不代表 CDN 全球节点同步切换。核心流程另外记录渲染日志以便恢复。生产部署需要平台自身的版本发布机制与状态核对,不能照搬一个本地 symlink 就声称零停机。

目录使用方式有几个约束:

  1. 输出路径可以尚不存在,也可以是空目录;已有非空普通目录会被拒绝,避免覆盖用户文件。
  2. 已有符号链接必须指向同一父目录下、符合当前输出名的受管版本目录,并包含构建清单;任意外部链接不被接管。
  3. 旧版本保留,便于回滚。原型不会自动删除历史目录。长期运行应设置经确认的保留规则,并确保至少保留当前与可回滚版本。
  4. 打包时应复制符号链接指向的完整内容,或连同对应版本目录一起打包。只移动链接到另一个父目录会使相对目标失效。
  5. 原型按单进程串行构建设计;生产多 worker 应增加站点级锁或唯一发布协调器,避免两次已成功构建互相覆盖入口。

清单记录输入页面的版本标识和内容摘要,以及 HTML、CSS、JavaScript、robots 和 sitemap 的字节摘要。不把构建时刻写入页面,因此相同输入可以生成相同字节。这一点对于判断回滚是否恢复旧版本很重要。摘要证明内容是否变化,不能证明内容正确、署名真实或审批有效。

5.4 页面必须先让人走得通 ​

首页提供全部资源入口,主题索引让读者选择主题,主题页列出相应工具和指南。文章有面包屑、来源和同主题、同语言的相关页面。所有导航使用真正的 a href,不要求爬虫模拟点击事件。

这些入口解决了两个具体问题:新页面不会只存在于数据库里,访问者读到一半也能找到下一步。正式站增长后,应记录“哪些已上线页面链接到这篇文章”,而不只是“这篇文章链接到哪里”。如果一个新主题找不到合理入口,要先考虑是否缺一个有用的主题页,或它根本不属于站点范围。

原型没有伪造作者介绍、使用量、评分和客户评价。若正式网站要显示作者,应该有真实负责人、可核对的简介和更新责任。来源列表也不是质量装饰:正文结论必须能由具体资料支持,而不是在页脚堆一批知名网站。

可访问性设计已经包含跳到正文的链接、可见焦点、表单标签、状态播报、响应式网格和无需注册的操作入口。浏览器与辅助技术兼容性仍需人工走查;这些 HTML 特征本身不构成完整 WCAG 合规结论。生产验收至少覆盖键盘、手机缩放、错误输入与屏幕阅读器的实际反馈。

5.5 转换器要真的完成任务 ​

工具从“用户到底要输入什么”开始设计,而不是从“哪个关键词适合做工具页”开始。当前版本支持两个方向:Unix 时间戳转 UTC/指定 IANA 时区日期;带明确 UTC 或偏移量的 ISO 日期转秒和毫秒。

它要求用户自己选择秒或毫秒,不凭数字位数猜测;接受负时间戳和毫秒精度,拒绝精度更细的输入、科学计数法、逗号、非法时区和超出 Date 范围的数据。秒转毫秒先用字符串与 BigInt 处理,避免 1.001 × 1000 的浮点误差令正确输入被误拒绝。

日期方向严格检查月份、闰年、每月天数、时分秒与偏移范围。没有时区的本地日期会被拒绝,因为夏令时切换时同一个墙上时间可能出现两次。2024-11-03T01:30:00-04:00 与 2024-11-03T01:30:00-05:00 是两个不同的时刻,测试确认相差一小时。工具不处理闰秒;历史时区展示依赖运行浏览器的 Intl 数据库,这个边界直接显示在工具旁。

Node 测试实际执行 JavaScript 函数,验证 epoch、负数、小数、上海与纽约时区、闰日、夏令时偏移及多种非法输入。它验证计算逻辑,不等同于真实浏览器布局、表单点击或屏幕阅读器验收。完整上线前还应在计划支持的浏览器运行相同样例,并检查脚本禁用时的说明。

5.6 把预览与公开索引分成两道门 ​

预览模式默认开启。每张 HTML 包含 noindex,follow;sitemap 是合法的空 URL 集合;robots 不公布 sitemap。robots 仍允许读取页面,因为爬虫必须看见 noindex 才能处理它。Google 不支持在 robots.txt 中写一个 noindex 字段来代替页面指令。[T04][T05]

这不提供保密性。含未公开商业信息、账户数据或草稿的预览环境,应该增加身份验证或限制访问。禁止抓取也不能保证 URL 不出现在搜索结果中。当前本地演示推荐只绑定 127.0.0.1;不要为了让别人看一眼就把开发服务器公开到公网。

切换到公开构建要同时满足:调用显式 preview=False、所有页面都有 publication_approved=True、基地址使用非占位 HTTPS 源站。常见示例域和保留测试域会被拒绝。这个布尔值只是本地程序的误操作防线,不等同于用户已经授权上传、证明了域名所有权或同意了服务条款。真实发布仍需另行确认具体域名、托管服务、内容范围、成本和索引意图。

公开模式生成自引用 canonical、可索引页面的 sitemap 以及 robots 的 sitemap 声明;404 模板始终 noindex。程序不发出网络请求,也不会“顺便”提交收录。

5.7 四种容易混淆的控制 ​

想解决的问题主要控制常见误用
不让未授权的人看登录或访问控制把 robots 当保险柜
公开可读但不进入索引可读取的 noindex同时禁止抓取,令新指令不可见
多个近似地址选择代表页canonical 与一致的内部链接所有文章都指向首页
告知哪些正式地址值得发现sitemap 与站内链接把草稿、跳转、错误页一起提交

canonical 是规范化信号,并非一定执行的命令。真实不同的语言页、不同内容的分页页,不应仅为“集中权重”全部指向一个入口。站内链接、canonical、重定向和 sitemap 应表达同一套 URL 规则;Google 仍可能根据实际内容选择其他代表页。[T06]

原型只接受源站形式的 base_url,不支持挂载到 /blog/ 子目录,避免导航根路径与 canonical 路径不一致。若以后要支持子目录,应一次性修改 URL 生成、资源前缀、404、robots 作用域与测试,不要只改一处字符串。

5.8 sitemap 的 lastmod 不能是每日签到 ​

生成 sitemap 时,页面更新时间取自内容记录;首页和主题页没有可靠的实质更新依据时省略 lastmod。日期字段存在,不代表它一定可靠,因此编辑工作流仍应记录“改了什么,为什么属于实质更新”。修改页脚年份或每日重新运行构建,不应把所有文章刷新成今天。

Google 明确表示只会在持续准确、可核实的情况下使用 lastmod;忽略 priority 和 changefreq。单个 sitemap 的上限是未压缩 50 MB 或 50,000 个 URL,超过就拆分并使用索引文件。提交只是发现提示,不能证明已抓取、已索引或有排名。[T07]

生产 sitemap 队列从已发布页面表生成,而不是扫描磁盘上所有 HTML。先排除预览、noindex、重定向与不存在的地址,再核对 canonical。生成后解析 XML,并对列出的地址抽样请求。地图本身返回 200 XML,不应被登录页、WAF 页面或 HTML 错误页替换。

5.9 分页、筛选和站内搜索要各自设计 ​

当内容多到需要分页时,为每一页提供独立地址和可抓取的前后页链接;第二页有不同条目,就不应 canonical 到第一页。无限滚动或“加载更多”可以保留,但底层需要无需点击脚本也能访问的分页地址。Google 的分页指南也明确反对把整个序列的 canonical 统一指向第一页。[T08]

筛选参数的风险来自组合空间。语言、单位、排序、标签各增加几个选项,很容易产生大量近似地址。先用产品需求决定哪些组合值得成为独立落地页:是否有稳定需求、独立内容和维护责任。允许的组合进入显式白名单;重复参数、非法页码与无意义顺序在路由层处理。对无结果且无意义的组合返回正确错误状态,不要生成无穷的“没有结果”成功页。

若筛选页完全不需要搜索展示,可在制定清楚策略后限制抓取;若它已被索引而目标是移除,先确保爬虫能读取 noindex。canonical 可能逐渐减少重复页的抓取,但不能替代控制 URL 生成。[T09] 站内搜索结果默认不成为内容生产来源,不能让任意查询自动产生一张可索引页面。

当前原型没有实现分页、参数路由或站内搜索。以上是扩展规范,不能因为写进了指南就算已完成。

5.10 状态码由实际托管层兑现 ​

静态生成器能写 404.html,不能决定服务器面对未知路径时究竟返回 404 还是 200。很多托管平台会把所有地址回退到首页,这对单页应用可能方便,却会制造软 404。公开发布前必须测试实际 HTTP 响应,而不是只检查文件是否存在。

  • 正常页面返回 200,并包含应有正文。200 空壳或错误文案不代表有效内容。
  • 暂时移动使用相应临时重定向;永久迁移通常使用 301 或 308,目标应是最相关的有效页面,避免长链与循环。不要把所有删除页面一律重定向首页。
  • 确认不存在返回 404;明确永久移除可使用 410。Google 通常将普通 4xx 视为不存在,不必为了所谓“410 更快”批量改造。[T10]
  • 临时服务故障应暴露正确 5xx,视情况给重试提示,不应返回 200 加“维护中”。故障持续时需告警,不能把它归类为“内容表现下降”。
  • 304 是条件请求中的“内容未改变”,不是空白页面错误,也不是替代 200 的通用成功码。客户端带验证器、服务端确认一致时才返回,响应没有新的正文。[T11]

缓存设计要与版本一致。HTML 采用可重新验证的策略;内容指纹资源可以较长缓存。当前原型资源名固定为 site.css 和 converter.js,因此生产不能给它们无限期 immutable 缓存,否则回滚页面可能配上错误脚本。扩展生产构建时应把资源摘要加入文件名,再更新所有引用。

验收样本至少包含首页、工具、指南、主题、未知路径、旧路径、带参数地址、robots、sitemap 和脚本资源。逐条记录 URL、状态码、Location、Content-Type、缓存头、canonical 与实际正文摘要。

5.11 国际 SEO 先确认是否真有那个版本 ​

语言、地区、币种和目标市场不是同一个字段。en-US 表达美国英语版本,并不证明需求来自美国;html lang 应符合主要正文,搜索市场判断还需单独数据。原型默认英文导航并显式标注其语言,文章根据 locale 设置文档语言,但没有完整多语言产品界面。

hreflang 只用于真实对应版本,并包含自己与其他版本的互相声明。地区代码不能单独使用,也不能用 en-UK 代替 en-GB。每个实际语言版本通常声明自己的规范地址,而不是把所有译文 canonical 回英语页。[T12] x-default 仅在确有默认选择页时使用,不凭空指向首页。

代码采用一份较小的已审查 locale 白名单。这比正则接受任意“两个字母加两个字母”更保守,但也意味着新增市场要改代码并加测试。通过同一 translation_group 生成双向标签可减少漏链;译文一旦撤下,要重新生成整组关系。

真正困难的是持续维护:英文修正了一处单位解释,中文版本能否及时同步?建议保存 source_page_id、source_version_hash、翻译审阅者和审阅日期。源版本更新后,把译文标为待审,而不是机器直接覆盖已发布译文。以上元数据属于建议扩展,当前 builder 不负责翻译同步。

5.12 结构化数据只描述页面上真实存在的东西 ​

当前页面仅输出 WebPage 与 BreadcrumbList,内容来自可见标题、摘要、语言、更新时间和导航关系。没有评分、评价人数、真人作者、价格或所谓工具用户数。JSON-LD 在序列化后额外转义 <、> 和 &,防止恶意标题提前闭合 script 标签。

不要把问答段落自动升级成 FAQ 富结果承诺。截至本次核验,Google 官方更新记录说明 FAQ 富结果自 2026 年 5 月 7 日起不再展示,并在 6 月移除相应文档。旧教程里“政府和健康站仍可获得”的限制已经不足以表达当前状态。[T13] 页面仍可以保留有用问答,但目的应是回答用户问题。

结构化数据测试要分开看:JSON 是否能解析、类型属性是否正确、标注是否与可见内容一致、当前搜索功能是否支持。前两项自动通过不代表后两项成立,更不保证获得特殊展示。

5.13 性能验收要区分本地测试与真实访问 ​

Core Web Vitals 当前包括 LCP、INP、CLS。良好目标分别为不超过 2.5 秒、200 毫秒和 0.1,按真实访问的第 75 百分位观察,并区分移动端与桌面。单次 Lighthouse 得分不等于站点已经满足真实用户指标。[T14]

对本项目,先控制可解释的成本:正文直接输出,无第三方字体、广告与跟踪脚本;转换器只在工具页加载,事件处理不需要网络请求;布局采用系统字体与简单网格。它们减少风险,却不能代替测量。服务器距离、压缩、缓存、设备性能和未来广告都可能改变实际体验。

上线前,固定设备模拟、网络条件、页面样本与测试次数,再比较同条件下的结果。LCP 慢就定位最大元素和资源发现链;INP 慢就检查长任务与事件处理;CLS 高就定位移动元素,尤其是后插入的广告、提示和图片。不要为了一个总分同时改十项,最后无法判断哪一项有效。

没有足够真实用户数据时,报告“现场数据不足”,保留实验室结果作为诊断。不要把缺数据写成零延迟、零偏移或已经通过。

5.14 从收录准备到收录观察 ​

授权正式发布后,先检查 DNS、HTTPS、未登录访问、状态码、移动正文与索引标记,再在用户控制的 Search Console 资源中完成所有权验证。权限与凭据应由账户流程安全处理,不能塞进网页 JavaScript 或仓库。本文没有执行这些步骤。

然后选择少量代表页检查:Google 是否能读取、声明的 canonical 是什么、平台选中的 canonical 是什么、上次抓取时间、是否存在索引排除原因。URL Inspection API 返回检查信息,并不是通用提交索引的接口。普通内容站通过 sitemap、内链和适当的手动检查建立发现路径;Google Indexing API 仅支持符合条件的 JobPosting 或嵌入 VideoObject 的 BroadcastEvent 页面,不应用来批量催收普通指南。[T15]

IndexNow 可以把新增、更新和删除地址通知参与引擎,需要按协议验证主机控制权。200 表示收到,202 表示已接收但密钥验证待完成,均不能直接记为“已索引”。参与引擎之间会共享提交信息,应在授权接入前把目的与范围说明清楚。[T16] 是否接入取决于目标市场和维护成本;不要把它描述成 Google 的通用收录入口。

把观察状态分开存:发布成功、提交被接收、已发现、已抓取、已索引、产生展示。最后两项可能长期没有可确认数据,报告也应保留未知,不由 AI 补齐。若一个页面一直没有进入索引,先检查内容是否独立有用、是否被规范合并和是否存在访问故障,再决定是否需要继续提交。

5.15 观测接口先定义,默认不采集 ​

当前站点没有任何 analytics 请求。Content Security Policy 禁止 connect-src,JavaScript 没有 fetch、XHR 或 beacon。它也不把用户输入写进 URL、本地存储或日志。

如果未来要衡量工具任务完成,可另行批准一份最小事件合同:event_name=conversion_succeeded、页面 ID、页面版本摘要、单位类别、错误类别、时间桶和必要的同意状态。不要记录原始时间戳、输入日期、完整查询串、邮箱、账户 ID 或广告身份标识。转化失败只保存枚举原因,例如 invalid_timezone,不要把异常原文当成自由文本上传。

这只是建议接口,不是已经接通的采集。启用前还要决定接收方、处理目的、保留时长、访问人员、地区要求与退出方式,并修改 CSP 的精确允许目标。第三方服务的秘密密钥必须留在受控服务端;浏览器公开标识符也不应被当成授权凭据。服务端日志同样要控制 URL 查询参数与 IP 的保存,不应因为“没有埋点”就默认完全没有个人数据处理。

衡量成功以完成任务为中心。用户三秒完成换算后离开,可能比停留两分钟仍看不懂更好。不要故意拖延结果、分页藏答案或插入打断性广告来拉长时长。

5.16 发布、回滚与失败处置清单 ​

**第一道门:内容与版本。**检查页面任务、证据引用、来源许可、真实更新时间和审阅结论。保存将要发布的页面摘要;批准后内容又变化,则原批准不能自动覆盖新版本。

**第二道门:本地构建。**运行测试、解析所有 HTML/JSON/XML、检查内部链接目标与清单摘要。当前站点单测覆盖路径、URL、转义、语言关系、预览/公开开关、非法日期、版本稳定性和失败恢复;自动化测试只能证明所覆盖的条件。

**第三道门:预览体验。**在手机与桌面检查导航、工具正反转换、错误提示、键盘和脚本禁用;检查 CSP 控制台是否误拦自己需要的资源。可见性测试和浏览器检查完成前,不写“已全面验证”。

**第四道门:实际发布权限。**确认域名、主机、上传范围、服务与成本、索引意图,以及平台新增协议。预览审核通过不自动等于公开批准。

**第五道门:上线后的 HTTP 与索引意图。**从真实地址取样核对响应头、正文摘要、robots 与 sitemap。确认线上部署 ID 对应本地清单,再允许提交队列运行。公共站若误带 noindex,按发布事故处理,不等流量周报发现。

**第六道门:可操作的回滚。**上线前记录上一部署 ID、上一构建清单、数据库内容版本和需要恢复的配置。先演练恢复到旧文件,再核对关键页面摘要与转换器结果。若回滚需要删除新页面,还需决定返回旧页、重定向或正确错误状态;“删掉文件”不能独立完成这个决定。

以下情况应停止后续扩张:大量正常页变 404、canonical 指向错误主机、全站 noindex、工具对有效输入给出错误结果、原始输入被意外发送到第三方,或页面内容与批准版本不一致。先恢复安全版本、记录范围、通知负责人,再调查根因。排名短期波动则进入观测流程,不自动触发全站回滚。

本阶段能验收的是:代码能从明确记录生成可用静态文件,默认不会公开索引,并能在本地保留与切换版本。真实域名所有权、线上状态码、CDN 行为、现场性能、搜索收录和商业收益,都要等获得授权并接入真实环境后分别验证。

本章参考 ​

资料核验日期:2026-10-14。框架文档随版本更新,实际项目应锁定依赖;下面是协议与设计依据,不表示已完成账户内操作。

保留各书来源与许可 · 示例运行条件以正文为准