@@ -0,0 +1,187 @@
|
||||
# 黄果短剧全页面索引策略分析
|
||||
|
||||
## 输入信息与假设
|
||||
|
||||
- 分析范围:当前本地 Go 项目的全部页面路由、模板 `meta robots`、公共渲染层、`robots.txt` 和 sitemap 路由。
|
||||
- 未提供线上域名,无法验证生产环境最终 HTML、HTTP 状态、真实 canonical 和 sitemap 内容;以下结论以代码为准。
|
||||
- “需要索引”表示页面有独立搜索意图、稳定公开内容和唯一 canonical,建议输出 `index,follow` 并进入 sitemap。
|
||||
- “不需要索引”表示登录/用户私有页、站内搜索、操作页、接口、重复 URL、错误页或低价值工具页,建议输出 `noindex` 或返回正确的 3xx/4xx。
|
||||
- 分页页只要内容真实存在、URL 唯一并使用自引用 canonical,建议保持可索引。Google 官方也明确建议分页 URL 各自使用 canonical,而不是全部 canonical 到第一页。
|
||||
|
||||
## 总体判断
|
||||
|
||||
当前索引方向属于 **Mixed(基本方向正确,但存在明显一致性问题)**:
|
||||
|
||||
- 公开内容页基本为 `index,follow`。
|
||||
- 搜索、账户、反馈、404 基本为 `noindex`。
|
||||
- 但全站模板普遍输出两条 `meta robots`;登录/注册页更同时输出 `noindex,follow` 和 `index,follow`。
|
||||
- `robots.txt` 又禁止抓取登录、搜索和账户页面,搜索引擎可能无法读取页面里的 `noindex`。Google 官方说明:被 `robots.txt` 阻止的页面,爬虫看不到 `noindex`,URL 仍可能只凭外链被索引。
|
||||
- 空标签、空分类、无效专题、应用空列表和上游接口失败时,多个页面仍会返回 `200 + index,follow`,存在 soft 404 和索引膨胀风险。
|
||||
|
||||
## 一、明确需要索引的页面
|
||||
|
||||
以下页面有明确、稳定的搜索价值,建议 `index,follow`,只把 canonical URL 放入 sitemap。
|
||||
|
||||
| 页面类型 | 路由 | 建议 | 当前代码 | 条件与说明 |
|
||||
|---|---|---|---|---|
|
||||
| 首页 | `/` | 索引 | `index,follow` | 核心入口,必须索引 |
|
||||
| 短剧主列表 | `/list/ai-short-play/` 及合法筛选页 | 索引 | `index,follow` | 合法的有限筛选页可索引;任意 slug 会被 canonical 重定向 |
|
||||
| AI 成人剧集 | `/series/`、合法筛选及分页 | 索引 | `index,follow` | 内容真实存在时索引 |
|
||||
| 标签聚合页 | `/tag/` | 索引 | `index,follow` | 应展示标签导航或有价值的聚合内容 |
|
||||
| 有效标签详情 | `/tag/:slug/` 及有效分页 | 索引 | `index,follow` | 标签存在、列表非空、TDK/正文可区分时索引 |
|
||||
| 排行榜 | `/rank/`、合法榜单类型及分页 | 索引 | `index,follow` | 有独立榜单意图;分页使用自引用 canonical |
|
||||
| 今日更新 | `/today-update/` 及有效分页 | 索引 | `index,follow` | 有稳定的“今日更新/最新短剧”搜索意图 |
|
||||
| 有效分类详情 | `/category/:slug/` 及有效分页 | 索引 | `index,follow` | 分类必须真实存在且有内容 |
|
||||
| 专题总览 | `/topic/` 及有效分页 | 索引 | `index,follow` | 作为专题导航入口 |
|
||||
| 有效专题详情 | `/topic/:slug/` 及有效分页 | 索引 | `index,follow` | 专题必须存在,具有独立介绍与内容集合 |
|
||||
| 下载 APP | `/download-app/` | 索引 | `index,follow` | 官方下载意图明确;仅保留一个官方 canonical URL |
|
||||
| 福利应用 | `/application/` | 索引 | `index,follow` | 当前有分类介绍和应用说明;空列表时不应索引 |
|
||||
| 短剧详情 | `/detail/:slug/` | 索引 | `index,follow` | 最重要的内容承接页;不存在时已经返回 404 |
|
||||
| 关于我们 | `/about-us/` | 索引 | `index,follow` | 品牌实体与可信度页面 |
|
||||
| 帮助中心 | `/help-center/` | 索引 | `index,follow` | FAQ/帮助内容真实且公开时有搜索价值 |
|
||||
|
||||
路由证据见 `app/router/gin.go:127-255`;公开页面模板 robots 见 `app/templates/page/*.html`。
|
||||
|
||||
## 二、需要条件判断后再索引的页面
|
||||
|
||||
这些页面不应无条件 `index,follow`,需要 handler 根据内容状态设置 `noindex`、404、410 或 503。
|
||||
|
||||
| 页面类型 | 路由 | 推荐规则 | 当前风险 |
|
||||
|---|---|---|---|
|
||||
| 播放/章节页 | `/play/:slug/`、`/play/:slug/:chapterId/` | 章节真实存在、页面有唯一标题、可播放视频和足够正文时索引;无效章节返回 404;只有付费壳、无视频或与详情页高度重复时 `noindex,follow` | 当前只验证短剧存在,章节请求失败时仍可能用短剧数据渲染 `200 + index,follow`;所有章节描述还复用短剧简介 |
|
||||
| 回家的路 | `/home-road/` | 若它是唯一官方最新地址发布页且内容长期维护,可索引;多个镜像域名只索引一个 canonical,其余 canonical/noindex | 多域名/导航站场景容易形成重复或 doorway 页面 |
|
||||
| 官方导航 | `/nav/`;导航独立服务的 `/`、`/nav/`、`/dh/` | 只索引一个官方导航 URL;内容站副本和独立导航站副本之间必须明确 canonical,其余 noindex 或 301 | 当前各入口都可能输出 `index,follow`,代码未体现跨域唯一索引版本 |
|
||||
| 通用富文本 | `/richtext/:title/` | 仅白名单中的公开、唯一、完整内容索引;协议、内部说明、重复帮助内容等 noindex 或 301 到固定语义路由 | 当前 `IsIndexablePath` 将全部 `/richtext/*` 视为可索引,容易暴露任意 CMS 内容和重复页 |
|
||||
| 用户协议 | `/user-agreement/` | 一般不需要搜索流量,建议 `noindex,follow`;若业务要求公开检索也可保留索引 | 当前 `index,follow` |
|
||||
| 隐私政策 | `/privacy-policy/` | 一般建议 `noindex,follow`,保留用户访问但不占索引配额 | 当前 `index,follow` |
|
||||
| 标签/分类/专题第 1 页 | `/tag/:slug/`、`/category/:slug/`、`/topic/:slug/` | 不存在必须 404;存在但内容过少可 `noindex,follow`;达到内容阈值再 index | 当前只对“分页越界”处理 404,第 1 页空结果仍可能 200 可索引 |
|
||||
| 所有公开列表空状态 | list/series/rank/today-update/topic/application | 合法但暂时为空可 noindex;上游故障应优先返回 503,不能把接口异常伪装成长期 `200` 空页面 | 多个 `Fetch...OrEmpty` 吞掉上游错误并继续输出可索引页面 |
|
||||
|
||||
## 三、明确不需要索引的 HTML 页面
|
||||
|
||||
| 页面类型 | 路由 | 建议 | 当前代码 |
|
||||
|---|---|---|---|
|
||||
| 登录 | `/login/`、`/login/return/*` | `noindex,follow`,不进 sitemap | handler 设置 `noindex=true`,但 `index.html` 又固定输出 `index,follow`;且 robots.txt 禁止抓取 |
|
||||
| 注册 | `/register/` | `noindex,follow`,不进 sitemap | 同登录页,存在冲突 robots 标签 |
|
||||
| 个人中心 | `/user-center/` | `noindex,nofollow`,不进 sitemap | 已输出 `noindex,nofollow`,但 robots.txt 同时禁止抓取 |
|
||||
| 充值 | `/deposit/`、`/deposit/:tab/` | `noindex,nofollow` | 已 noindex;robots.txt 同时禁止抓取 |
|
||||
| 收藏 | `/collect/...` | `noindex,nofollow` | 已 noindex;robots.txt 同时禁止抓取 |
|
||||
| 观看历史 | `/history/...` | `noindex,nofollow` | 已 noindex;robots.txt 同时禁止抓取 |
|
||||
| 账号设置 | `/setting/` | `noindex,nofollow` | 已 noindex;robots.txt 同时禁止抓取 |
|
||||
| 编辑资料 | `/edit-profile/` | `noindex,nofollow` | 已 noindex;robots.txt 同时禁止抓取 |
|
||||
| 修改密码 | `/edit-password/` | `noindex,nofollow` | 已 noindex;robots.txt 同时禁止抓取 |
|
||||
| 站内搜索 | `/search/`、`/search/:keyword/...` | `noindex,follow` | 模板已 noindex,但 robots.txt 禁止抓取,爬虫可能看不到 noindex |
|
||||
| 问题反馈 | `/feedback/` | `noindex,nofollow` | 已 noindex;robots.txt 同时禁止抓取 |
|
||||
| 404/无效页面 | 未匹配路由、无效详情/分页 | 正确返回 HTTP 404/410,并 `noindex,follow` | 统一 404 模板已 noindex;部分无效聚合页仍可能返回 200 |
|
||||
| 空富文本入口 | `/richtext/` | 返回 404 并禁止索引 | 当前因标题为空而进入统一 404,方向正确 |
|
||||
| UI 弹窗片段 | `/ui/dialog/:name` | 不索引;建议响应头 `X-Robots-Tag: noindex`,并从 robots.txt 禁止抓取 | 当前未设置索引响应头,robots.txt 也没有 `/ui/` 规则 |
|
||||
| 健康检查 | `/healthz` | 不索引;建议 `X-Robots-Tag: noindex` | 当前只是 200 JSON,无索引响应头,也未在 robots.txt 禁止 |
|
||||
|
||||
## 四、重复 URL:自身不索引,只让目标 URL 索引
|
||||
|
||||
| 重复/历史路由 | 当前行为 | 建议 |
|
||||
|---|---|---|
|
||||
| `/tag-list/...` | handler 301 到 `/tag/...` | 正确;不要进入 sitemap |
|
||||
| `/more/...` | handler 301 到 `/topic/...` | 正确;不要进入 sitemap |
|
||||
| `/list/ai-series/...` | 301 到 `/series/...` | 正确;不要进入 sitemap |
|
||||
| 查询参数版分页/筛选 URL | 多数 handler 会重定向到路径式 canonical | 保持 301,只提交最终 canonical |
|
||||
| 非规范 slug/ID URL | detail/category/topic 等尝试跳转规范 slug | 保持 301;旧 URL 不进入 sitemap |
|
||||
|
||||
## 五、非 HTML 路由和资源的索引策略
|
||||
|
||||
| 路由/资源 | 是否需要搜索索引 | 推荐控制方式 |
|
||||
|---|---|---|
|
||||
| `/api/*` | 不需要 | 保持 robots.txt 限制抓取;对可直接访问的 JSON 响应统一增加 `X-Robots-Tag: noindex` |
|
||||
| `/h5/*`、`/enkey`、`/newenkey` | 不需要 | 保持 robots.txt 禁止;视频/密钥响应可加 `X-Robots-Tag: noindex` |
|
||||
| `/robots.txt`、`/sitemap.xml`、`/sitemaps/*.xml` | 需要允许抓取,但不作为普通网页参与排名 | 返回正确状态和 Content-Type;无需放进 sitemap |
|
||||
| Google/百度/Bing/IndexNow 验证文件 | 需要允许验证爬虫访问,不需要普通搜索索引 | 保持可访问;可选 `X-Robots-Tag: noindex`,不得放入 sitemap |
|
||||
| `/favicon.*`、`/static/*` | 允许抓取以支持页面渲染和搜索展示,不作为 HTML 页面索引 | 不要整体 Disallow 静态 CSS/JS/图片 |
|
||||
|
||||
## 六、分页页是否索引
|
||||
|
||||
建议有效分页页继续 `index,follow`,包括:
|
||||
|
||||
- `/list/.../page/:page/`
|
||||
- `/series/.../page/:page/`
|
||||
- `/tag/.../page/:page/`
|
||||
- `/rank/.../page/:page/`
|
||||
- `/today-update/page/:page/`
|
||||
- `/category/.../page/:page/`
|
||||
- `/topic/.../page/:page/`
|
||||
|
||||
必须满足:
|
||||
|
||||
1. 每一页有唯一 URL。
|
||||
2. 每一页使用自引用 canonical,不能全部 canonical 到第 1 页。
|
||||
3. 分页越界返回 404。
|
||||
4. 上一页/下一页使用真实 `<a href>`,保证爬虫发现深层内容。
|
||||
5. 不需要为了分页强制写完全不同的 title/description;Google 可以识别分页序列,但加“第 N 页”更利于人工排查和结果辨识。
|
||||
|
||||
## 七、当前实现的优先级问题
|
||||
|
||||
### 高优先级
|
||||
|
||||
1. **robots.txt 与 noindex 冲突**
|
||||
- 范围:登录、注册、搜索、账户、反馈页面。
|
||||
- 证据:`app/templates/page/robots.txt:14-25` 同时禁止这些路径,而页面模板又输出 `noindex`。
|
||||
- 影响:爬虫被挡住后无法读取 `noindex`,URL 仍可能以无摘要形式出现在结果中。
|
||||
- 修复:若目标是“绝不进入搜索结果”,允许抓取这些 HTML URL并保留 `noindex`;私密内容本身必须通过鉴权保护,不能依赖 robots.txt。
|
||||
|
||||
2. **登录/注册页存在相反 robots 指令**
|
||||
- 范围:`/login/*`、`/register/`。
|
||||
- 证据:`app/api/web/index.go:35-36` 设置 `noindex`,`seoCommon.html:12` 输出 `noindex,follow`,但 `index.html:10` 又输出 `index,follow`。
|
||||
- 影响:虽然 Google通常采用更严格规则,但重复冲突不利于跨搜索引擎一致性和测试。
|
||||
- 修复:全站只保留一个由公共模板控制的 robots 标签。
|
||||
|
||||
3. **空内容和接口故障页仍可索引**
|
||||
- 范围:标签、分类、专题、榜单、今日更新、应用等聚合页。
|
||||
- 影响:soft 404、低质量索引、抓取预算浪费。
|
||||
- 修复:区分“不存在”“合法为空”“上游故障”;分别返回 404、`200 + noindex`、503。
|
||||
|
||||
### 中优先级
|
||||
|
||||
4. **播放页无条件索引**:应按章节存在性、可播放性和内容唯一性控制。
|
||||
5. **任意富文本均可索引**:应建立可索引白名单或后台 `indexable` 字段。
|
||||
6. **导航页可能多域重复**:主站 `/nav/` 与独立导航站需确定唯一 canonical。
|
||||
7. **法律页面默认索引**:若无自然搜索目标,用户协议和隐私政策改为 `noindex,follow`。
|
||||
|
||||
### 低优先级
|
||||
|
||||
8. **全站重复 meta robots**:`seoCommon.html` 与每个页面模板各输出一条,应统一到公共模板。
|
||||
9. **本地未发现 sitemap XML 文件**:路由读取 `./templates/page/sitemaps`,当前仓库扫描未找到生成产物;需确认部署流程会生成并正确挂载,否则 `/sitemap.xml` 可能 404。
|
||||
|
||||
## 八、建议的最终索引矩阵
|
||||
|
||||
| 策略 | 页面 |
|
||||
|---|---|
|
||||
| `index,follow` | 首页、有效短剧/剧集列表、有效标签、排行榜、今日更新、有效分类、专题总览与有效专题、下载 APP、非空福利应用、短剧详情、关于我们、帮助中心、有效分页 |
|
||||
| 条件 `index` | 播放章节、回家的路、官方导航、通用富文本、稀疏标签/分类/专题 |
|
||||
| `noindex,follow` | 登录、注册、站内搜索、用户协议、隐私政策、合法但暂时空的公开聚合页 |
|
||||
| `noindex,nofollow` | 个人中心、充值、收藏、历史、设置、编辑资料、修改密码、反馈 |
|
||||
| 301 | `/tag-list/*`、`/more/*`、`/list/ai-series/*`、查询参数和旧 slug 变体 |
|
||||
| 404/410 | 不存在的内容、无效 slug、越界分页 |
|
||||
| 503 | 上游故障导致无法生成正常内容的公开页面 |
|
||||
| `X-Robots-Tag: noindex` | `/ui/dialog/*`、`/healthz`、可直接访问的 API/非 HTML 工具响应 |
|
||||
|
||||
## 参考依据
|
||||
|
||||
- [Google:使用 noindex 阻止编入索引](https://developers.google.com/search/docs/crawling-indexing/block-indexing)
|
||||
- [Google:robots meta 与 X-Robots-Tag 规范](https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag)
|
||||
- [Google:robots.txt 不是阻止网页进入索引的机制](https://developers.google.com/search/docs/crawling-indexing/robots/intro)
|
||||
- [Google:分页与增量加载最佳实践](https://developers.google.com/search/docs/specialty/ecommerce/pagination-and-incremental-page-loading)
|
||||
|
||||
## 实施结果(2026-09-08)
|
||||
|
||||
已按上述矩阵完成以下代码调整:
|
||||
|
||||
- 全站 robots meta 收口到 `seoCommon.html`,每个 HTML 页面只输出一条规则。
|
||||
- 登录、注册、搜索、账户、充值、收藏、历史、设置、编辑资料、修改密码、反馈和 404 已明确设置 noindex。
|
||||
- 用户协议、隐私政策和任意通用富文本默认 `noindex,follow`;关于我们、帮助中心继续索引。
|
||||
- `/richtext/关于我们/` 等重复地址会 301 到固定语义路由;页脚也直接生成语义路由。
|
||||
- 空短剧列表、空剧集、空标签、空分类、空榜单、空今日更新、空专题和空福利应用自动 `noindex,follow`。
|
||||
- 明确请求但不存在的播放章节返回 404;无法取得默认章节的播放页设置 noindex。
|
||||
- `/api/*`、`/ui/*`、`/healthz`、媒体代理与密钥响应增加 `X-Robots-Tag: noindex, nofollow`。
|
||||
- `robots.txt` 不再阻止登录、搜索和账户 HTML,使爬虫能够读取页面的 noindex;继续限制非 HTML 接口与媒体工具路由。
|
||||
- `robots.txt` 合并为一个 `User-agent: *` 规则组,避免原先的 Disallow 只落在最后一个特定爬虫分组下。
|
||||
|
||||
仍需由部署配置决定的事项:主站 `/nav/`、独立导航站首页和 `/home-road/` 跨域时,哪一个域名作为唯一 canonical;代码无法在没有目标域名配置的情况下安全替用户做这个选择。
|
||||
Binary file not shown.
@@ -0,0 +1,98 @@
|
||||
# 黄果短剧页面 TDK 来源分析
|
||||
|
||||
## 分析范围与口径
|
||||
|
||||
- 分析对象:当前本地 Go 项目的页面路由、SSR handler、公共渲染层和页面模板。
|
||||
- 未提供线上域名,因此结论代表代码的运行逻辑,不代表某一线上环境当前接口里一定配置了 TDK。
|
||||
- “动态获取”指 TDK 至少可从上游接口返回的 `seoInfo`、公共配置、导航 SEO 或内容字段生成。
|
||||
- “写死”指模板内直接写固定文本,或 handler 传入固定常量;列表数据虽然动态,但未用于 TDK 的页面仍算写死。
|
||||
- “混合”指部分字段动态、部分字段写死,或接口失败后回退到模板常量。
|
||||
|
||||
## 总体结论
|
||||
|
||||
项目不是简单的“动态 / 写死”两类,而是四种实现:
|
||||
|
||||
1. **后台 TDK 动态优先,模板常量兜底**:首页、标签、排行榜、今日更新、分类详情、专题详情等。
|
||||
2. **依赖公共导航 SEO,页面业务接口本身不返回 TDK**:短剧列表、AI 剧集、福利应用、回家的路。
|
||||
3. **根据内容或路由参数动态拼装**:短剧详情、播放、搜索、富文本。
|
||||
4. **模板固定写死**:账户相关页、反馈页、下载页默认配置、404 的 D/K 等。
|
||||
|
||||
公共渲染层会读取 `/api/app/translation/category/list` 的导航项 `seoInfo`,按当前路径或 `navActive` 覆盖页面原有 `seoInfo`;字段级优先级是“导航 SEO > 页面 SEO > 模板兜底”。证据见 `app/api/web/render.go:25-54`、`app/service/translationser/list.go:13-55` 和 `app/service/translationser/view.go:154-185`。
|
||||
|
||||
## 一、完整 TDK 可动态获取的页面
|
||||
|
||||
这些页面的 T、D、K 都存在动态来源;动态字段为空或接口失败时,模板会回退到固定文案。
|
||||
|
||||
| 页面 / 路由 | T 来源 | D 来源 | K 来源 | 主要接口与说明 |
|
||||
|---|---|---|---|---|
|
||||
| 首页 `/` | 首页 `seoInfo.title`,导航 SEO 可覆盖;再回退公共配置和固定标题 | 首页 `seoInfo.description`,导航 SEO可覆盖;再回退公共配置/固定文案 | 首页 `seoInfo.keywords`,导航 SEO 可覆盖;再回退公共配置/固定词 | `/api/app/playlet/home`;`/api/app/config/info`;`/api/app/translation/category/list`。见 `app/api/web/index.go:20-38`、`app/templates/page/index.html:7-9` |
|
||||
| 登录 `/login/`、注册 `/register/` | 与首页相同 | 与首页相同 | 与首页相同 | 两者复用 `index.html` 和首页接口,并没有登录/注册专属 TDK。handler 虽设置内部 `noindex` 标志,但模板的 robots 仍固定输出 `index,follow`。见 `app/api/web/index.go:15-38`、`app/templates/page/index.html:10` |
|
||||
| 标签列表/详情 `/tag/...` | 标签接口 SEO 标题或标签名 + 分页 | 标签接口 SEO 描述;否则用标签名拼装 | 标签接口 SEO 关键词;否则标签名 + 固定词 | `/api/app/playlet/tag/list`;导航 SEO 仍可覆盖。见 `app/api/web/tag_list.go`、`app/templates/page/tagList.html:7-9` |
|
||||
| 排行榜 `/rank/...` | 排行榜接口 SEO + 榜单筛选值 | 排行榜接口 SEO + 榜单筛选值 | 排行榜接口 SEO + 榜单筛选值 | `/api/app/playlet/rank`;导航 SEO 优先。见 `app/api/web/rank.go`、`app/templates/page/rank.html:7-9` |
|
||||
| 今日更新 `/today-update/...` | 接口 SEO 或固定标题 | 接口 SEO 或固定文案 | 接口 SEO 或固定词 | `/api/app/playlet/today-update`;导航 SEO 优先。见 `app/api/web/today_update.go`、`app/templates/page/todayUpdate.html:7-9` |
|
||||
| 分类详情 `/category/:slug/...` | 分类接口 SEO;否则分类名 + 分页 | 分类接口 SEO;否则 handler 固定分类介绍 | 分类接口 SEO;否则分类名 + 固定词 | `/api/app/playlet/recommend/list`;导航 SEO 可覆盖。见 `app/api/web/category_detail.go`、`app/templates/page/categoryDetail.html:7-9` |
|
||||
| 专题详情 `/topic/:slug/...` | 专题列表接口 SEO;否则专题名称 | 专题列表接口 SEO;否则固定专题介绍 | 专题列表接口 SEO;否则专题名 + 固定词 | `/api/app/playlet/list` 提供 `seoInfo`,`/api/app/theme/list` 提供专题名;导航 SEO 可覆盖。见 `app/api/web/more.go`、`app/templates/page/more.html:7-18` |
|
||||
| 官方导航 `/nav/`;导航独立服务的 `/`、`/nav/`、`/dh/` | `seoNavInfo.dhTitle` / `dhSiteName` | `seoNavInfo.dhDescription` | `seoNavInfo.dhKeyworld` | `/api/app/config/info`;失败时固定文案。见 `app/templates/page/nav.html:7-9`、`app/service/configser/types.go:118-124` |
|
||||
|
||||
## 二、条件动态:只依赖导航 SEO 的页面
|
||||
|
||||
这些页面不是从自身内容接口取得 TDK,而是依靠公共导航接口中与当前路由匹配的 `seoInfo`。如果后台导航没有配置 SEO,最终就是模板固定文案。
|
||||
|
||||
| 页面 / 路由 | 实际情况 | 动态来源 | 固定兜底 |
|
||||
|---|---|---|---|
|
||||
| 短剧列表 `/list/...` | 三个字段都支持动态;筛选项还会追加到 T/D/K | `/api/app/translation/category/list` 的导航 SEO | `短剧` 标题及模板内固定描述、关键词。业务接口 `/api/app/playlet/operate/list` 的响应结构没有 `seoInfo`,handler 也显式传入空 `SeoInfo`。见 `app/api/web/list.go:34-53`、`app/service/playletser/types.go:168-176` |
|
||||
| AI 成人剧集 `/series/...` | 三个字段都支持动态;筛选项会追加到 T/D/K | 导航 SEO | 业务接口同样没有页面级 `seoInfo`,handler 没有传 `seoInfo`。见 `app/api/web/series.go:20-39`、`app/templates/page/series.html:7-9` |
|
||||
| 福利应用 `/application/` | 三个字段都支持动态,但应用列表接口不参与 TDK | 导航 SEO | `福利应用` + 模板固定 D/K。见 `app/api/web/application.go`、`app/templates/page/application.html:7-14` |
|
||||
| 回家的路 `/home-road/` | 三个字段都支持动态,但 `config/info.seoInfo` 并未传给模板的 `.seoInfo` | 导航 SEO | handler 固定标题,模板固定 D/K。见 `app/api/web/home_road.go`、`app/templates/page/homeRoad.html:7-9` |
|
||||
| 下载 APP `/download-app/` | 模板具备 `.seoInfo` 动态入口,但 handler 不传;默认导航项被标记为下载项,会被导航 SEO 匹配逻辑跳过 | 仅当后台把它配置成可匹配的普通站内导航 URL 时才可能动态 | 通常落到模板固定的下载 APP TDK。见 `app/router/gin.go:202-207`、`app/templates/page/downloadApp.html:7-12`、`app/service/translationser/view.go:159-166` |
|
||||
|
||||
## 三、内容字段或路由规则动态拼装的页面
|
||||
|
||||
这些页面会变化,但不一定使用后台专门配置的完整 TDK。
|
||||
|
||||
| 页面 / 路由 | T | D | K | 判定 |
|
||||
|---|---|---|---|---|
|
||||
| 短剧详情 `/detail/:slug/` | 优先 `detail.SeoInfo.Title`,否则短剧名;站点名也可由接口 SEO/公共配置动态取得 | **不读取 `detail.SeoInfo.Description`**;只要 `detail` 存在,就使用短剧 `Desc`,为空则按短剧名拼固定句式 | **不读取 `detail.SeoInfo.Keywords`**;由短剧名、题材名、标签名和固定词拼装 | 内容动态拼装,不是完整后台 TDK。见 `app/api/web/detail.go:17-30`、`app/templates/page/detail.html:7-11` |
|
||||
| 播放 `/play/:slug/:chapterId?/` | 优先章节 SEO 标题,其次短剧 SEO 标题/短剧名,并拼集数 | **不读取已经合并好的 `.seoInfo.Description`**;只要 `playlet` 存在,就使用短剧 `Desc` 或固定播放句式 | **不读取已经合并好的 `.seoInfo.Keywords`**;由短剧名、题材、标签和固定词拼装 | 标题动态取 SEO,D/K 是内容字段拼装。见 `app/api/web/play.go:37-60`、`app/service/playletser/seo.go:252-277`、`app/templates/page/play.html:7-17` |
|
||||
| 搜索 `/search/:keyword/...` | 搜索词拼装 | 搜索词拼装固定句式 | 搜索词 + 固定词 | 路由参数动态,不读搜索接口的 SEO;页面为 `noindex,follow`。见 `app/api/web/search.go`、`app/templates/page/search.html:7-19` |
|
||||
| 通用富文本 `/richtext/:title/` | 上游富文本 `desc/title` | 用动态标题套固定句式 | 动态标题 + 固定词 | `/api/app/config/richtext/list` 只映射 `id/title/desc/content`,没有映射 `seoInfo`,所以不是后台独立 TDK。见 `app/service/configser/types.go:133-145`、`app/service/configser/richtext.go:48-82`、`app/templates/page/richtext.html:7-18` |
|
||||
| 专题列表 `/topic/`、分页 | handler 固定基础标题并按页码追加;公共导航 SEO 命中时也可覆盖标题 | 固定 | 固定 | T 动态/规则生成,D/K 写死。见 `app/api/web/theme_index.go`、`app/templates/page/themeIndex.html:7-9` |
|
||||
| 404 / 未找到页面 | handler 的错误标题可变化 | 固定 | 固定 | 只有 T 动态,D/K 写死;`noindex,follow`。见 `app/api/web/notfound.go`、`app/templates/page/404.html:7-13` |
|
||||
|
||||
## 四、路由层“动态富文本优先、静态模板兜底”的页面
|
||||
|
||||
以下四个固定路由会先请求 `/api/app/config/richtext/list`:有内容时使用 `richtext.html`,按上一节的规则动态拼装;接口失败或找不到内容时,改用各自的静态模板,TDK 全部写死。
|
||||
|
||||
| 路由 | 动态成功时 | 接口失败时静态模板 |
|
||||
|---|---|---|
|
||||
| `/about-us/` | 富文本标题驱动的规则 TDK | `aboutUs.html`:TDK 写死 |
|
||||
| `/user-agreement/` | 富文本标题驱动的规则 TDK | `userAgreement.html`:TDK 写死 |
|
||||
| `/privacy-policy/` | 富文本标题驱动的规则 TDK | `privacyPolicy.html`:TDK 写死 |
|
||||
| `/help-center/` | 富文本标题驱动的规则 TDK | `helpCenter.html`:TDK 写死 |
|
||||
|
||||
路由切换逻辑见 `app/api/web/richtext.go:26-50`。
|
||||
|
||||
## 五、TDK 写死的页面
|
||||
|
||||
这些模板不读取 `.seoInfo`,即使公共渲染层取得导航 SEO,也不会改变最终 TDK。
|
||||
|
||||
| 页面 / 路由 | TDK 情况 | 模板 |
|
||||
|---|---|---|
|
||||
| 个人中心 `/user-center/` | 全部写死 | `app/templates/page/userCenter.html:7-12` |
|
||||
| 金币/会员充值 `/deposit/...` | T 由 handler 固定传入,D/K 写死;整体仍属固定 TDK | `app/templates/page/deposit.html:7-9` |
|
||||
| 我的收藏 `/collect/...` | T 由 handler 固定传入,D/K 写死 | `app/templates/page/collect.html:7-9` |
|
||||
| 观看历史 `/history/...` | 全部写死 | `app/templates/page/history.html:7-9` |
|
||||
| 账号设置 `/setting/` | 全部写死 | `app/templates/page/setting.html:7-12` |
|
||||
| 编辑资料 `/edit-profile/` | 全部写死 | `app/templates/page/editProfile.html:7-12` |
|
||||
| 修改密码 `/edit-password/` | 全部写死 | `app/templates/page/editPassword.html:7-12` |
|
||||
| 问题反馈 `/feedback/` | 全部写死 | `app/templates/page/feedback.html:7-12` |
|
||||
|
||||
以上账户页多数设置了 `noindex,nofollow`,固定 TDK 对自然搜索影响较小。
|
||||
|
||||
## 关键风险与建议
|
||||
|
||||
1. **详情页和播放页丢弃后台 D/K**:handler 已经拿到 `seoInfo.description/keywords`,模板在存在 `detail/playlet` 时却绕过它们。若后台运营会配置详情和章节 SEO,这部分配置当前不会生效。
|
||||
2. **短剧列表和剧集列表没有页面接口 SEO**:二者完全依赖导航 SEO;导航未配置时所有筛选/分页页面主要使用相同兜底内容,仅筛选值可能由公共层追加。
|
||||
3. **富文本 `seoInfo` 未映射**:数据模型中虽然服务端领域模型可见 `SeoInfo`,Web 上游响应结构 `AppRichTextItemResp` 没有该字段,当前只能用标题套固定句式。
|
||||
4. **专题列表 D/K 固定**:分页页标题会变化,但 description 和 keywords 始终一致。
|
||||
5. **登录/注册复用首页 TDK,且 robots 标志不一致**:handler 设置了 `noindex=true`,但 `index.html` 固定输出 `index,follow`。这两个页面不仅 TDK 与页面功能不一致,还可能被搜索引擎索引。
|
||||
Binary file not shown.
@@ -0,0 +1,365 @@
|
||||
# jha-1045-hgdjnet-web SEO 收录审计报告
|
||||
|
||||
审计日期:2026-09-22
|
||||
审计范围:`app/template/pages`、公共模板、页面路由、TDK 注入链路、canonical/robots、JSON-LD、sitemap、独立导航服务,以及本地 SSR 最终响应。
|
||||
目标搜索引擎:Google、Bing、Yandex。
|
||||
|
||||
## 一、结论
|
||||
|
||||
当前项目已经具备较完整的 SSR SEO 基础设施,但**暂不建议按现状直接上线并开放全站抓取**。
|
||||
|
||||
- 32/32 个页面模板均有 `lang="zh-CN"`、`charset`、`viewport`、唯一 `<title>`、统一 SEO 公共片段、`<main>` 和一个 `<h1>`。
|
||||
- 主站公开页能输出绝对 canonical、robots、Open Graph、Twitter Card 和 JSON-LD;搜索、账户页与 404 的 noindex 策略基本正确。
|
||||
- 路径型筛选和分页 URL 已经取代页面链接中的查询参数,分页第 2 页以后具有独立 title、description 与 canonical。
|
||||
- 本轮已经阻止软 404、无限分页和重复筛选 URL 进入索引;仍有 5 项高优先级内容质量/结构化数据问题:跨栏目重复 TDK、品牌信息冲突、动态 URL 未进入 sitemap、Organization logo 结构化数据失效、`series-play` 播放页没有 VideoObject。
|
||||
|
||||
综合判断:
|
||||
|
||||
| 引擎 | 当前判断 | 主要风险 |
|
||||
|---|---|---|
|
||||
| Google | 收录边界已明确,但富媒体与页面质量仍需优化 | 重复标题、结构化数据与页面不一致、视频页标记缺失 |
|
||||
| Bing | 重复 URL 已禁止索引,但元数据区分度仍不足 | 相同 TDK、动态 sitemap 覆盖不足 |
|
||||
| Yandex | 与其他搜索引擎使用统一 robots 策略 | 非主域名统一 noindex;sitemap 覆盖仍不足 |
|
||||
|
||||
## 本轮收录策略优化结果
|
||||
|
||||
已将页面收录规则改为公开页白名单;未明确归类的新页面默认 `noindex,follow`,避免后续新增路由意外进入索引。
|
||||
|
||||
| 状态 | 页面类型与路由 |
|
||||
|---|---|
|
||||
| `index,follow` | 首页;关于、帮助与法律合规页;主列表默认排序;有效题材/媒体/专题/标签/榜单页;有效分页;短剧及视频播放详情页 |
|
||||
| `noindex,follow` | 站内搜索;独立导航页;列表/专题/标签排序变体;首页配置列表的时间/题材筛选变体;播放页推荐翻页;重复的默认参数路径;无效标签、专题、配置页;越界分页;404 |
|
||||
| `noindex,nofollow` | 登录、注册、个人中心、历史、收藏、已购、设置、充值、反馈等用户或交易页面 |
|
||||
| HTTP `X-Robots-Tag: noindex, nofollow` | API、M3U8、密钥和健康检查等非 HTML 工具接口 |
|
||||
|
||||
主域名使用配置接口动态返回的 `foreverUrlAddr`,不使用当前请求 Host、SEO canonical 或最新地址作为主域名回退。只有永久域名 Host 的公开白名单页面允许索引;CloudFront、旧域名及其他备用 Host 对所有搜索引擎统一输出:
|
||||
|
||||
```html
|
||||
<meta name="robots" content="noindex,nofollow">
|
||||
```
|
||||
|
||||
非主域名及主域名自身的 noindex 页面均不输出 canonical 或 JSON-LD。所有 noindex HTML 页面同时发送对应的 `X-Robots-Tag` 响应头。
|
||||
|
||||
## 二、审计方法与边界
|
||||
|
||||
本次完成:
|
||||
|
||||
1. 静态扫描 422 个项目文件和 32 个页面模板。
|
||||
2. 检查所有页面模板的 title、description、robots、canonical、H1–H6、main、图片 alt 和外链 rel。
|
||||
3. 跟踪 `seoInfo → 导航 SEO → 筛选条件 → 本地兜底` 的 TDK 获取与合并流程。
|
||||
4. 检查 JSON-LD 的生成分支及页面可见内容一致性。
|
||||
5. 临时启动本地 `25121` 主站和 `26813` 导航站,抽查最终 SSR 响应,而非只检查模板源码。
|
||||
6. 解析代表页面 JSON-LD;抽查 sitemap XML 通过 `xmllint` 语法校验。
|
||||
|
||||
限制:当前站点尚未上线,因此没有做搜索引擎控制台、线上 CDN、真实爬虫日志与 Google Rich Results Test 的线上 URL 校验。本轮使用配置接口动态返回的永久域名及不同 Host 请求本地 SSR 服务,验证了主域名、CloudFront 和旧域名的最终输出。
|
||||
|
||||
## 三、页面类型矩阵
|
||||
|
||||
| 页面类型 | 代表路由 | robots/canonical | H 标签 | JSON-LD | 结论 |
|
||||
|---|---|---|---|---|---|
|
||||
| 首页 | `/` | `index,follow`;绝对自 canonical | 1 个 H1 | Organization、WebSite、WebPage、ItemList | 基础通过;品牌/H1 与 TDK 不一致 |
|
||||
| 短剧列表 | `/list/...` | 默认排序与有效筛选 index;排序变体、无效实体和越界分页 noindex | 1 个 H1 | CollectionPage、BreadcrumbList、ItemList | 收录边界已清理;仍需解决 TDK 重复 |
|
||||
| 视频列表 | `/series/...` | 默认排序与有效筛选 index;排序变体、无效实体和越界分页 noindex | 1 个 H1 | CollectionPage、BreadcrumbList、ItemList | 收录边界已清理;JSON-LD 名称仍有双品牌风险 |
|
||||
| 专题/榜单/标签 | `/topic`、`/topic-detail/...`、`/rank/...`、`/tags/...` | 有效实体/榜单 index;纯排序、无效实体和越界分页 noindex | 1 个 H1 | CollectionPage、BreadcrumbList、ItemList | 收录边界已清理;部分 TDK 仍重复 |
|
||||
| 更多列表 | `/more-list/...`、`/more-series-list/...` | 有效配置基础页及分页 index;筛选变体、无效配置 noindex | 1 个 H1 | WebPage、ItemList | 无效 config ID 已 noindex;仍建议改为 CollectionPage |
|
||||
| 短剧播放 | `/play/:slug/:chapterID` | index;内容 canonical | 1 个 H1 | WebPage、BreadcrumbList、TVSeries、VideoObject、TVEpisode | 标记较完整;title 可能被通用上游 SEO 覆盖 |
|
||||
| 视频播放 | `/series-play/:slug` | index;内容 canonical | 1 个 H1 | 仅 Organization、WebSite、WebPage | 缺少 VideoObject 和结构化面包屑 |
|
||||
| 关于/帮助/法律页 | `/about`、`/help`、`/terms` 等 | index;自 canonical | 1 个 H1 | WebPage、BreadcrumbList;帮助页另有 FAQPage | 品牌文案与动态站点名冲突 |
|
||||
| 搜索页 | `/search/:q/...` | `noindex,follow`;不输出 canonical/JSON-LD | 1 个 H1 | 无 | 策略正确 |
|
||||
| 登录/账户/充值/反馈 | `/login`、`/profile`、`/favorites` 等 | `noindex,nofollow`;不输出 canonical/JSON-LD | 1 个 H1 | 无 | 策略正确 |
|
||||
| 404 | 任意不存在内容页 | HTTP 404;`noindex,follow` | 1 个 H1 | 无 | 正确 |
|
||||
| 独立导航站 | `26813 /`、`/nav/`、`/dh/` | 统一 `noindex,follow`;无 canonical | 1 个 H1 | 无 | 已统一禁止索引 |
|
||||
|
||||
## 四、高优先级问题
|
||||
|
||||
### P0-1:越界分页和不存在的聚合对象仍返回 200,但已禁止索引
|
||||
|
||||
本轮已在统一 SEO 层接入 `PageOutOfRange`,并为标签、专题、首页配置和分类实体增加有效性标记。越界分页、无效实体及纯排序变体现在均返回 `noindex,follow`、`X-Robots-Tag: noindex, follow`,且不输出 canonical/JSON-LD,不再进入索引。
|
||||
|
||||
这些 URL 目前仍可能返回 HTTP 200;后续若需要进一步消除软 404,建议对已确认不存在的实体和越界分页直接返回 HTTP 404。
|
||||
|
||||
优化前实际响应:
|
||||
|
||||
| URL | HTTP | robots | canonical |
|
||||
|---|---:|---|---|
|
||||
| `/list/all/0/1/page/999999` | 200 | index,follow | 自指向第 999999 页 |
|
||||
| `/series/all/all/1/page/999999` | 200 | index,follow | 自指向第 999999 页 |
|
||||
| `/topic/page/999999` | 200 | index,follow | 自指向第 999999 页 |
|
||||
| `/tags/biaoqianceshi/page/999999` | 200 | index,follow | 自指向第 999999 页 |
|
||||
| `/tags/definitely-not-existing-seo-audit` | 200 | index,follow | 自 canonical |
|
||||
| `/topic-detail/definitely-not-existing-seo-audit` | 200 | index,follow | 自 canonical |
|
||||
| `/more-list/999999999` | 200 | index,follow | 自 canonical |
|
||||
| `/list/definitely-not-existing-seo-audit` | 200 | index,follow | 自 canonical |
|
||||
|
||||
其中越界分页的 UI 页码会被分页组件钳制到真实末页,但 canonical 仍保留请求中的极大页码。例如标签第 999999 页最终 title 变为“第2页”,canonical 却仍是 `/page/999999`。这会生成任意数量的近重复、软 404 URL。
|
||||
|
||||
正确行为:
|
||||
|
||||
1. 数据拉取后,调用现有 `PageOutOfRange(page, pageSize, totalCount)`。
|
||||
2. 第 2 页及以后越界时直接返回 HTTP 404 + `noindex,follow`,不输出 canonical 和 JSON-LD。
|
||||
3. tag/topic/config/theme 无法解析或上游明确返回无数据时返回 404。
|
||||
4. 枚举型路径参数必须白名单校验;无效筛选不能自 canonical 成新的可收录页面。
|
||||
5. `/play/不存在` 和 `/series-play/不存在` 当前已正确返回 404,可沿用同一模式。
|
||||
|
||||
### P0-2:多个公开栏目输出完全相同的 TDK
|
||||
|
||||
当前优先级是:页面接口 `seoInfo` 优先,导航 SEO 补空,筛选条件追加,最后才使用本地兜底。这个模型本身合理,但没有判断上游返回的是否只是全站通用 SEO。
|
||||
|
||||
本地最终响应中,下列页面输出了相同的 title 和 description:
|
||||
|
||||
- `/`
|
||||
- `/list`
|
||||
- `/topic`
|
||||
- `/rank`
|
||||
- `/recently-added`
|
||||
- `/popular-recommend`
|
||||
|
||||
它们均使用当前上游返回的“麻豆官网|麻豆传媒官方站 最新华语AV免费看”及同一段首页描述。另有:
|
||||
|
||||
- `/rank/2` 与 `/popular-recommend/2` 的 title 和 description 完全相同,仅 canonical 不同。
|
||||
- `/play/chongchongceshiduanju` 的 H1 是“虫虫测试短剧”,但 `<title>` 被章节 `seoInfo.title` 覆盖成全站通用标题并追加数字。
|
||||
|
||||
Google 明确建议每个页面使用简洁、描述性、非模板化重复的 title;Bing 也会使用 title、OG 和显著正文综合生成结果标题;Yandex 的标题与摘要同样取自 title、description、正文和结构化数据。当前重复与冲突会导致搜索引擎重写标题、降低页面区分度。
|
||||
|
||||
建议:
|
||||
|
||||
1. 非首页页面不要无条件接受“全站通用 title/description”。增加通用 SEO 检测:若与首页 SEO 完全相同,则回退到页面类型 TDK。
|
||||
2. 每个主栏目设置独立模板:栏目名/筛选名/页码 + 简短站点名;description 描述该栏目实际内容。
|
||||
3. 播放页将 `ResolvePlayPageTitle` 的结果写回最终 `seoInfo.Title`,避免随后又被原始章节 SEO 覆盖。
|
||||
4. `/rank/:type` 与 `/popular-recommend/:type` 必须体现不同页面意图,不能只追加相同榜单名称。
|
||||
5. 对上游 SEO 建立验收条件:非空、包含当前实体或栏目主题、不是首页 TDK、长度合理、与可见 H1 不矛盾。
|
||||
|
||||
### P0-3:动态品牌与硬编码“黄果短剧”混用
|
||||
|
||||
当前上游配置的站点名是“麻豆传媒”,但项目中仍有 141 处“黄果/黄果短剧”硬编码。最终页面出现多套品牌信号:
|
||||
|
||||
- 首页 `<title>`、Organization、WebSite 是“麻豆传媒”,H1 是“黄果短剧”。
|
||||
- `/series` `<title>` 为“剧集与动画 - 黄果短剧”,JSON-LD `WebPage.name` 被再次追加成“剧集与动画 - 黄果短剧 - 麻豆传媒”。
|
||||
- `/about`、`/help`、法律页的 title 使用“麻豆传媒”,description/H1/正文仍为“黄果短剧”。
|
||||
- 独立导航页根路径:`<title>` 是“麻豆官网…”,OG/Twitter 是“黄果短剧 · 官方导航”,H1 是“麻豆传媒官方导航站…”,JSON-LD WebPage 又使用“黄果短剧”。
|
||||
|
||||
这不只是品牌展示问题,也会让 title、H1、OG、JSON-LD 互相矛盾。Google 和 Bing 都会综合这些来源重新判断页面标题与站点实体。
|
||||
|
||||
建议:
|
||||
|
||||
1. 先明确该部署到底是“黄果短剧”还是“麻豆传媒”。
|
||||
2. 可复用白标项目应统一使用 `siteName`/配置品牌变量,避免在 handler、模板、fallback、JSON-LD 中写死品牌。
|
||||
3. 法律文本、帮助 FAQ、邮箱域名、图片 alt、App 文案也必须跟随同一品牌配置,不能只改 head。
|
||||
4. JSON-LD 不应对已经带旧品牌的名称再次追加新品牌。
|
||||
|
||||
### P0-4:sitemap 仅包含 13 个静态栏目 URL
|
||||
|
||||
当前 sitemap XML 语法有效、使用绝对 URL、robots.txt 也正确声明了 Sitemap,但只列出 13 个固定地址:主页、主栏目和静态说明页。
|
||||
|
||||
缺失:
|
||||
|
||||
- 所有 `/play/...` 和 `/series-play/...` 内容页;
|
||||
- `/tags/...`、`/topic-detail/...`;
|
||||
- 可收录的 `/more-list/...`、`/more-series-list/...`;
|
||||
- 有独立搜索意图的筛选页与分页页;
|
||||
- `<lastmod>`;
|
||||
- 视频 sitemap 或视频扩展字段。
|
||||
|
||||
对以动态视频详情为核心的网站,只依赖站内链接发现会降低新内容发现速度,并让孤立或深层内容更难被抓取。Google 建议 sitemap 放入希望出现在搜索结果中的 canonical URL;Yandex 也建议 Sitemap 反映当前站点结构。
|
||||
|
||||
建议按类型生成 sitemap index:
|
||||
|
||||
- `sitemap-static.xml`
|
||||
- `sitemap-playlets.xml`
|
||||
- `sitemap-videos.xml`
|
||||
- `sitemap-topics-tags.xml`
|
||||
|
||||
只收录 200、index、canonical 的真实 URL;`lastmod` 必须来自真实更新时间。视频内容可增加 Google 支持的视频 sitemap 扩展。
|
||||
|
||||
### P0-5:Organization.logo 指向 404,且声明尺寸与文件不符
|
||||
|
||||
JSON-LD 当前生成:
|
||||
|
||||
```text
|
||||
https://{site}/favicon.png
|
||||
```
|
||||
|
||||
实际本地响应:
|
||||
|
||||
- `/favicon.png` → 404 HTML
|
||||
- `/static/favicon.png` → 200 `image/png`
|
||||
- 实际 PNG 尺寸为 132×132,但 JSON-LD 声明 512×512
|
||||
|
||||
Google 要求 Organization logo URL 可抓取、可索引,且至少 112×112。现有文件尺寸达最低要求,但 URL 与声明尺寸错误。
|
||||
|
||||
建议将 `url`/`contentUrl` 改为真实 `/static/favicon.png`,宽高写真实值;更理想的是提供专用 512×512 品牌 logo 文件,并确认生产 CDN 返回 200 和正确 MIME。
|
||||
|
||||
### P0-6:`series-play` 视频播放页没有 VideoObject
|
||||
|
||||
短剧播放页能在数据完整时输出:
|
||||
|
||||
- WebPage
|
||||
- BreadcrumbList
|
||||
- TVSeries
|
||||
- VideoObject
|
||||
- TVEpisode
|
||||
|
||||
但 `/series-play/:slug` 实际只输出 Organization、WebSite、WebPage,即使页面存在可见播放器、封面、标题、时长和视频地址,也没有 VideoObject。
|
||||
|
||||
Google 的视频富媒体文档要求 VideoObject 至少包含唯一 `name`、`thumbnailUrl` 和 `uploadDate`;推荐提供 `contentUrl` 或 `embedUrl`、description、duration。当前 `VideoInfoResp` 没有可靠发布时间字段,因此需要先补齐上游字段或数据映射,再生成合规 VideoObject,不能虚构日期。
|
||||
|
||||
短剧 VideoObject 的现状较好,但锁定内容的实测对象未输出 `contentUrl`/`embedUrl`。这不是必填错误,但会降低 Google 获取视频文件与视频搜索展示的能力。
|
||||
|
||||
## 五、中优先级问题
|
||||
|
||||
### P1-1:独立导航服务入口已统一禁止索引
|
||||
|
||||
`DHInit` 暴露 `/`、`/nav/`、`/dh/`。本轮通过页面数据中的 `isNavPage` 统一覆盖为 `noindex,follow`,不再输出 canonical 和 JSON-LD;即使请求 Host 恰好为主域名也不会误收录。
|
||||
|
||||
优化前行为为:
|
||||
|
||||
- `/`:200、index,但 canonical 指向主站首页,而不是导航站自身;
|
||||
- `/nav/`、`/dh/`:200、index,却没有 canonical 和 JSON-LD;
|
||||
- 导航服务的 `/robots.txt`、`/sitemap.xml` 返回 404。
|
||||
|
||||
如果导航站需要独立收录,应为导航域名配置独立 origin、统一 title/description/OG/H1/JSON-LD,并只保留一个规范入口;未上线阶段可直接删除多余别名或令其 404。若导航站不需要收录,则三个入口统一 noindex,不要一部分 index、一部分无 canonical。
|
||||
|
||||
### P1-2:公共 header 的 H2 出现在页面 H1 之前
|
||||
|
||||
32 个页面模板自身都只有一个 H1,页面内部 H1→H2→H3 层级基本合理。但公共 header 在正文 H1 之前渲染“搜索历史”“热门搜索”两个 H2,因此多数最终 HTML 的第一个标题标签是 H2,而不是页面主题 H1。
|
||||
|
||||
这些只是下拉菜单标签,建议改为 `<p>`/`<div>`,保留可访问性属性即可。这样最终 heading outline 从页面 H1 开始,更符合 Bing 对逻辑标题层级的建议,也避免搜索引擎误判页面主题。
|
||||
|
||||
### P1-3:Breadcrumb JSON-LD 与可见面包屑不完全一致
|
||||
|
||||
- 多数列表/法律/帮助页没有可见面包屑,却生成 BreadcrumbList。
|
||||
- 短剧播放页可见路径是“首页 → 短剧 → 剧名 → 第 N 集”,JSON-LD 缺少“短剧”层级。
|
||||
- `series-play` 有可见面包屑,却没有 BreadcrumbList。
|
||||
|
||||
Google 的通用结构化数据规则要求标记代表页面真实、可见的主要内容。建议由同一个 breadcrumb ViewModel 同时渲染 HTML 与 JSON-LD,防止两份逻辑漂移。
|
||||
|
||||
### P1-4:`more-*` 集合页仍标记为普通 WebPage
|
||||
|
||||
`/more-list/...` 与 `/more-series-list/...` 有真实列表和 ItemList,但 `isCollectionPath` 没包含这两个前缀,因此输出 WebPage。不是语法错误,但改为 CollectionPage 更准确。
|
||||
|
||||
## 六、已通过项
|
||||
|
||||
### 模板与语义标签
|
||||
|
||||
- 32/32 页面模板有 `<!doctype html>`、`lang="zh-CN"`、charset、viewport、title、统一 SEO 片段、main、H1。
|
||||
- 每个页面模板静态结构只有一个 H1。
|
||||
- 290 个 `<img>` 均有 alt 属性。
|
||||
- 44 个 `target="_blank"` 链接均包含 `rel="sponsored nofollow noopener"`。
|
||||
- 主要内容由 SSR 输出,不依赖客户端 JavaScript 才能产生 title、description、H1、canonical 或 JSON-LD。
|
||||
|
||||
### robots 与 canonical
|
||||
|
||||
- 主站 `robots.txt` 返回 200,允许抓取 HTML,同时屏蔽 API、播放器工具和健康检查路径。
|
||||
- 搜索页 `noindex,follow`,账户/登录/充值等私有页 `noindex,nofollow`。
|
||||
- 404 返回真实 HTTP 404 与 `noindex,follow`。
|
||||
- 所有 noindex 页面均不输出 canonical 和 JSON-LD,避免信号冲突。
|
||||
- 正常公开页使用绝对 canonical,去除 query 和 fragment。
|
||||
- 路径型分页第 2 页具有自 canonical、独立页码 TDK、prev/next。
|
||||
- API/媒体工具响应统一带 `X-Robots-Tag: noindex, nofollow`。
|
||||
|
||||
### JSON-LD
|
||||
|
||||
- 使用 Google 推荐的 JSON-LD 格式,并由 `json.Marshal` 生成;抽查页面均可正常解析为 JSON。
|
||||
- 首页与列表页能输出 WebSite/Organization/WebPage 或 CollectionPage/ItemList。
|
||||
- 帮助页 FAQPage 的问题和答案与页面可见内容一致。
|
||||
- 短剧播放页仅在有真实封面和发布日期时输出 VideoObject,没有伪造必填字段。
|
||||
- 结构化数据中的 URL 基本使用绝对 canonical URL。
|
||||
|
||||
### URL 结构
|
||||
|
||||
- 页面筛选、搜索与分页主链接已经使用二级路径形式。
|
||||
- 模板中未发现业务 HTML 链接继续使用 `?filter=`、`?page=` 等查询式页面 URL;发现的 `?v=` 均为静态资源版本号。
|
||||
|
||||
## 七、TDK 获取链路评价
|
||||
|
||||
当前实现:
|
||||
|
||||
```text
|
||||
接口 seoInfo
|
||||
↓ 缺失字段补齐
|
||||
导航配置 SEO
|
||||
↓
|
||||
当前筛选/排序维度差异化
|
||||
↓
|
||||
页面类型本地 fallback
|
||||
↓
|
||||
追加品牌、页码
|
||||
```
|
||||
|
||||
优点:入口集中、字段归一化、分页差异化明确,避免模板各自生成冲突标签。
|
||||
|
||||
主要缺口:
|
||||
|
||||
1. 上游字段只判断“是否非空”,不判断“是否属于当前页面”。
|
||||
2. `seoInfo.CanonicalURL` 被解析和保留,但最终 canonical 完全由本地路由重建;如果这是刻意的安全策略,应删除或注释清楚该未生效字段,避免后台运营误以为可配置页面 canonical。
|
||||
3. 品牌 fallback 写死“黄果短剧”,与动态 `WebSiteName` 不一致。
|
||||
4. 部分 handler 先生成了正确页面 title,随后仍把原始 `seoInfo` 交给公共层,导致正确 title 被再次覆盖。
|
||||
5. meta keywords 已输出,但 Google 不使用它作为排名信号;不能用 keywords 的完整度代替 title/description 的唯一性与准确性。
|
||||
|
||||
建议把最终 TDK 规则收口为:
|
||||
|
||||
```text
|
||||
实体/栏目专属 SEO(通过相关性校验)
|
||||
> 页面本地语义模板 + 动态品牌
|
||||
> 全站配置兜底
|
||||
```
|
||||
|
||||
首页允许使用全站 SEO;非首页如果上游 TDK 与首页完全相同,应自动降级到页面本地模板。
|
||||
|
||||
## 八、建议实施顺序
|
||||
|
||||
### 上线前必须完成
|
||||
|
||||
1. 所有无效实体、无效 slug/config ID、越界分页返回 404/noindex。
|
||||
2. 修复跨栏目重复 TDK 与播放页 title 覆盖。
|
||||
3. 统一品牌来源,清理 head、H1、正文、OG、JSON-LD 的多品牌冲突。
|
||||
4. 修复 Organization logo URL 和尺寸。
|
||||
5. 为 `series-play` 添加合规 VideoObject;先补真实 uploadDate。
|
||||
6. sitemap 纳入动态 canonical 内容 URL。
|
||||
|
||||
### 上线前建议完成
|
||||
|
||||
7. 已完成:导航站全部入口统一 `noindex,follow`,不输出 canonical/JSON-LD。
|
||||
8. 调整公共 header 的 H2,保证正文 H1 是页面第一个主题标题。
|
||||
9. 统一 HTML 与 JSON-LD 面包屑数据源。
|
||||
10. 将 `more-*` 页面标记为 CollectionPage。
|
||||
|
||||
### 上线后验证
|
||||
|
||||
1. Google Search Console:URL Inspection、Page indexing、Video indexing、Rich results。
|
||||
2. Bing Webmaster Tools:Site Scan、URL Inspection、Sitemaps、IndexNow。
|
||||
3. Yandex Webmaster:Page check、Searchable pages、Sitemap、Duplicate pages。
|
||||
4. 持续监控 404/软 404、重复 title/description、已发现未收录、视频缩略图抓取失败。
|
||||
|
||||
## 九、验收标准
|
||||
|
||||
- 任意不存在实体或越界分页:HTTP 404,robots noindex,无 canonical/JSON-LD。
|
||||
- 每个可收录 URL:唯一且与 H1/正文一致的 title、description。
|
||||
- 同一页面:title、H1、OG、Twitter、JSON-LD 使用同一品牌与页面主题。
|
||||
- 每个 canonical:200、可抓取、可索引、无跳转链、同域绝对 URL。
|
||||
- sitemap:只包含真实 200/index/canonical URL,并覆盖所有核心内容页。
|
||||
- Organization logo:200 图片响应、正确 MIME、可抓取、尺寸声明真实。
|
||||
- 所有视频观看页:满足 VideoObject 必填属性;可用时提供 contentUrl 或 embedUrl。
|
||||
- 仅主站公开白名单页面可索引;导航站全部入口稳定输出 noindex。
|
||||
|
||||
## 十、官方规则参考
|
||||
|
||||
- [Google:标题链接最佳实践](https://developers.google.com/search/docs/appearance/title-link)
|
||||
- [Google:结构化数据通用规范](https://developers.google.com/search/docs/appearance/structured-data/sd-policies)
|
||||
- [Google:VideoObject 结构化数据](https://developers.google.com/search/docs/appearance/structured-data/video)
|
||||
- [Google:视频 SEO 最佳实践](https://developers.google.com/search/docs/appearance/video)
|
||||
- [Google:Organization 结构化数据](https://developers.google.com/search/docs/appearance/structured-data/organization)
|
||||
- [Google:创建和提交 Sitemap](https://developers.google.com/search/docs/crawling-indexing/sitemaps/build-sitemap)
|
||||
- [Bing Webmaster Guidelines](https://www.bing.com/webmasters/help/webmaster-guidelines-30fba23a)
|
||||
- [Bing:标题生成与一致性建议](https://blogs.bing.com/webmaster/June-2014/How-Does-Bing-Choose-The-Title-For-My-Web-Page)
|
||||
- [Bing:重复内容与搜索可见性](https://blogs.bing.com/webmaster/December-2025/Does-Duplicate-Content-Hurt-SEO-and-AI-Search-Visibility)
|
||||
- [Yandex:Canonical URLs](https://yandex.com/support/webmaster/en/robot-workings/canonical)
|
||||
- [Yandex:Title and description](https://yandex.com/support/webmaster/en/search-results/title-and-description)
|
||||
- [Yandex:Sitemap files](https://yandex.com/support/webmaster/en/indexing-options/sitemap)
|
||||
|
||||
## 十一、构建与校验记录
|
||||
|
||||
- `go test ./app/...`:通过;项目 app、router、web、SEO service 等包可编译。
|
||||
- `go test ./...`:失败,原因是仓库既有 `pub/models` 缺少 `videoweb/app/api/proto`,以及 `pub/storage` 引用未定义的 proxy 符号;与本次 SEO 审计无关。
|
||||
- sitemap XML:`xmllint --noout` 通过。
|
||||
- 本轮已完成页面收录白名单、无效实体/越界分页 noindex、导航页 noindex,以及基于动态永久域名的非主域名统一 noindex 规则。
|
||||
Reference in New Issue
Block a user