# 1272-SEONexus 老模板蜘蛛日志与代码映射交接文档 - 2026-04-16 ## 目的 这份文档是在 `1271` 的基础上继续往前走一步: - 不再只停留在日志现象 - 而是把当前蜘蛛日志现象,映射到项目里最可能对应的代码位置 这样主 Codex 接手时,可以直接从关键入口开始排查,而不是重新全仓翻一遍。 ## 和前置文档的关系 - `1269`:定义第一阶段目标 - `1270`:定义协作边界 - `1271`:沉淀蜘蛛日志观察结论 - `1272`:把观察结论映射到代码入口 ## 当前最关键的代码位置 ### 1. 路由层 主要文件: - [router.php](/www/wwwroot/VideoSource2/code/app/home/config/router.php) 关键点: - `robots`、`sitemap`、`rss`、`sitemap_index`、`sitemap-main`、`sitemap-videos-*` 都在这里注册 - `videoGpt1` 分支里额外注册了大量历史详情页/播放页兼容路由 - 这些兼容路由正好和日志里高频出现的旧路径高度一致 直接对应的日志现象: - `/voddetail/...|301` - `/vodplay/...|301` - `/video-info/...|301` - `/video-play/...|301` - `/video-show/...|301` - `/shipin/...|301` 结论: > 这批深页历史入口并不是“无路由直接 404”,而是已经被路由层接住了。日志里大量 `301 -> 200` 的前提条件之一,就是这里的兼容路由在工作。 ### 2. URL 规范输出层 主要文件: - [UrlBuilder.php](/www/wwwroot/VideoSource2/code/app/common/helper/UrlBuilder.php) - [VideoService.php](/www/wwwroot/VideoSource2/code/app/services/VideoService.php) 关键点: - `UrlBuilder::detail()` 默认走 `voddetail/{strPinyin}-{intVId}` - `UrlBuilder::play()` 默认走 `vodplay/{strPinyin}-{intVId}-{strPlayType}-{intPlayIndex}` - `VideoService::getVideoInfoUrl()` / `getVideoPlayUrl()` 在 `videoGpt1` 下优先走 `UrlBuilder` 直接对应的日志现象: - 当前仍有大量 `voddetail` / `vodplay` 命中 - 同时又能看到 `video-info` / `video-play` / `video-show` 命中 结论: > 当前项目里“规范输出路径”和“兼容接入路径”是两层结构。`UrlBuilder` 更像主输出,`router.php` 里的兼容列表负责兜住历史入口。 ## 和首页 `/|301` 最相关的代码点 ### 1. DomainModel 的 host 归一口径 主要文件: - [DomainModel.php](/www/wwwroot/VideoSource2/code/app/model/DomainModel.php) 关键点: - 存在 `canonical_mode` - 存在 `play_index_mode` - 多处会对 host 做 `preg_replace('/^www\\./', '', ...)` 这说明: - 系统里已经有“规范 host / canonical 策略”的概念 - 但从日志看,裸域和 `www` 仍然同时被抓,说明这套策略没有完全在前台最终输出和真实访问上闭环 ### 2. SiteContext 的域名识别口径 主要文件: - [SiteContext.php](/www/wwwroot/VideoSource2/code/app/services/SiteContext.php) 关键点: - `getTemplate()` 用的是 `Request->rootDomain()` - 然后用 root domain 去取 `DomainModel` 对应判断: - 这有利于让 `www.xxx.com` 和 `xxx.com` 落到同一个站点配置 - 但这本身不会自动消除首页 `301` - 它更多解决的是“能不能识别到站点”,不是“是否直达最终规范 host” 结论: > 日志里大量 `/|301` 更可能是前台实际访问入口、host 规范和模板/链接输出之间还没有完全统一,而不只是域名识别不到。 ## 和深页 `301` 最相关的代码点 ### 1. 兼容路由列表 主要文件: - [router.php](/www/wwwroot/VideoSource2/code/app/home/config/router.php:166) 这里显式注册了大量历史深页入口,包括: - `voddetail` - `vodinfo` - `vod` - `video-info` - `video-detail` - `video` - `shipin` - `vodplay` - `video-play` - `video-show` - `shipin-play` - `shipin-bofang` 这和日志完全对上了。 结论: > 现在看到的大量深页 `301`,很可能正是“旧入口先接住,再跳到当前 family 主输出 URL”的结果。 ### 2. VideoService 的主输出链接 主要文件: - [VideoService.php](/www/wwwroot/VideoSource2/code/app/services/VideoService.php:80) 关键点: - 详情页和播放页主输出都优先走 `UrlBuilder` - 如果站点 family 不是历史路径样式,那么历史外链进来后出现一次 `301` 是符合当前结构的 这也解释了为什么: - `yagyjt.com` 已经能深抓 - 但 `detail|301` / `play|301` 仍然很高 结论: > 代码结构上,深页 301 并不奇怪;真正值得主 Codex 继续排的是:哪些 `301` 是必要兼容,哪些 `301` 已经可以进一步压缩。 ## 和 canonical / robots 最相关的代码点 ### 1. SiteStyle 的 SEO meta 构建 主要文件: - [SiteStyle.php](/www/wwwroot/VideoSource2/code/app/common/helper/SiteStyle.php:1800) 关键点: - `detectPageType()` 目前只明确识别: - `home` - `voddetail/*` -> `detail` - `vodplay/*` -> `play` - `search` - 部分 `rank` - 部分 `category` - `buildSeoMeta()` 里: - detail 默认 `index,follow` - play 默认 `noindex,follow` - play canonical 会回指 detail ### 2. 当前存在的明显风险 `guessDetailUrlFromVideo()` 目前是硬编码回: - `/voddetail/{slug}-{id}` - 或 `/voddetail/{id}` 这意味着: - 如果站点当前主 family 并不以 `voddetail` 作为规范详情路径 - 或者主输出已经切到别的 detail pattern - 那么模板 canonical 就可能和当前主输出路径不完全一致 这是当前最值得主 Codex 重点核对的一点。 ### 3. DomainModel 配置和模板输出暂未明显打通 虽然 `DomainModel` 已有: - `canonical_mode` - `play_index_mode` 但从当前代码检索结果看: - 这些配置主要存在于模型默认值、标准化、bootstrap 汇总 - 前台模板 meta 生成仍主要靠 `SiteStyle::buildSeoMeta()` - 而 `SiteStyle::buildSeoMeta()` 没有明显读取 `DomainModel` 的这两个配置 结论: > 现在“配置层有 canonical/play_index 策略”和“前台模板真实输出什么 canonical/robots”之间,存在未完全打通的风险。 ## 和 sitemap 最相关的代码点 ### 1. 前台 sitemap 读取 主要文件: - [SiteContext.php](/www/wwwroot/VideoSource2/code/app/services/SiteContext.php:505) 关键点: - `getSiteMapByCode()` 只是按约定文件名读取 `storage/SiteMap/{domain}/...` - 如果文件不存在,直接返回 `404` 这说明: - `sitemap*.xml` 的稳定性,既依赖路由,也依赖离线文件是否实际生成成功 ### 2. sitemap 生成逻辑 主要文件: - [SiteMapLogic.php](/www/wwwroot/VideoSource2/code/app/task/logic/SiteMapLogic.php) - [VideoSiteMapLogic.php](/www/wwwroot/VideoSource2/code/app/task/logic/VideoSiteMapLogic.php) 关键点: - 两处生成逻辑里多次直接写: - `https://www.{$DomainModel->d_domain}/...` - `VideoSiteMapLogic` 生成视频详情页时,会优先读当前 `url_family['detail']['pattern']` - 但最终 host 仍然是硬拼 `https://www.` + domain 这和日志里的 host 分裂现象是高度相关的。 结论: > 如果站点真实规范 host 不是 `www`,或者前台访问并没有完全锁在 `www`,那么 sitemap 长期输出 `https://www.xxx.com/...` 本身就可能持续制造首页和深页的规范化跳转。 ## 和“非 404 而是随机回落”的代码点 主要文件: - [VideoService.php](/www/wwwroot/VideoSource2/code/app/services/VideoService.php:760) 关键点: - `getVideoByVId()` 在直接按 `v_id` 查不到时,会进入 `resolveFallbackVideoByRequest()` - `resolveFallbackVideoByRequest()` 会: - 先看绑定表 - 再随机采样可播放视频 - 再做兜底有序回落 - 命中后会把“请求的旧 id”绑定到“随机或兜底找到的新视频 id” 这说明: - 某些旧深链并不一定直接 404 - 也可能被系统兜底绑定到别的视频,再输出一个可访问页面 对应日志判断: - 这能解释为什么一部分历史深链现在表现成 `301 -> 200` - 但也意味着 canonical 和真实内容语义一致性要特别小心 ## 给主 Codex 的代码排查优先级 ### 1. 先查 host 规范是否被多处硬编码成 `www` 优先看: - `SiteMapLogic.php` - `VideoSiteMapLogic.php` - 任何模板里直接拼域名的位置 原因: - 这最直接对应日志里的 `/|301` - 也最直接对应裸域 / `www` 分裂 ### 2. 再查 canonical 是否仍硬编码成 `/voddetail/...` 优先看: - `SiteStyle::buildSeoMeta()` - `SiteStyle::guessDetailUrlFromVideo()` 原因: - 当前 detail/play 主输出已经有 family 概念 - canonical 仍硬编码 `voddetail` 风险较大 ### 3. 再查历史兼容路由是否仍有可压缩空间 优先看: - `app/home/config/router.php` 的 legacy compat 段 原因: - 这直接对应日志里大量 `video-info` / `video-play` / `video-show` / `shipin` 的命中 - 主线要判断哪些入口必须保留,哪些入口可以进一步合并或缩短跳转链 ### 4. 最后查 fallback 视频绑定是否会放大“错链也 200” 优先看: - `VideoService::resolveFallbackVideoByRequest()` 原因: - 这条链对“减少 404”有帮助 - 但如果过度回落,也可能把错误深链转成语义不一致的 `200` ## 给主 Codex 的一句话交接 如果主 Codex 要开始从实现层排这轮蜘蛛问题,最值得先看的不是模板样式,而是: > `router.php` 的历史兼容入口、`SiteStyle` 的 canonical 输出、`VideoSiteMapLogic/SiteMapLogic` 的 `www` host 拼接、以及 `VideoService` 的 fallback 回落链。