博客换到 Typecho 1.3 之后,我一直想补上 SEO 能力:sitemap 站点地图 + 发布文章时主动推送搜索引擎收录。找了一圈现成插件,发现 Typecho 1.3 适配的 SEO 插件几乎空白——老插件(如 uSitemap)还停留在 1.2 时代的接口上,装上就 500。干脆自己写了一个,顺手开源了:TeoSeo。
为什么自己写一个 SEO 插件
先说需求,其实就三件事:
- 自动生成 sitemap.xml,让搜索引擎能发现全部文章
- 发布文章时主动推送,告诉搜索引擎"有新内容了"——百度主动推送 + IndexNow(Bing/Yandex/Naver/Seznam 一次提交)
- 能看到推送结果,推没推成功、为什么失败,一目了然
市面上的方案我试了一圈:
- uSitemap(1.2 时代知名插件):能生成 sitemap 和推送,但它依赖的
Widget_Interface_Do等旧接口在 Typecho 1.3 里已经移除,装上去后台直接 500,折腾半天还是放弃 - 主题自带 sitemap:我用的 Inaline 主题有个 sitemap 输出文件,能用,但推送、历史记录这些还是缺
结论:Typecho 1.3 是 2026 年的新版本,插件生态还停留在 1.2 的写法上,与其等别人适配,不如自己写一个。就这样,TeoSeo 诞生了。
TeoSeo 功能一览
自动生成 /sitemap.xml
插件激活时注册 /sitemap.xml 路由,动态生成符合 Sitemaps 0.9 协议的标准 XML:
- 首页:
changefreq=daily, priority=1.0 - 全部已发布文章:
weekly / 0.8 - 独立页面(可选):
monthly / 0.6
URL 不是硬编码拼出来的,而是走 Typecho 路由表生成——所以无论你把文章链接格式定制成 /archives/[cid]/、/[slug]/ 还是其他,生成的 sitemap URL 都永远正确。
发布文章即推送
插件挂在 Typecho 的 finishPublish 钩子上:后台发布文章的那一刻,自动向搜索引擎发起收录推送,全程零操作:
- IndexNow:微软 Bing 和 Yandex 联合推出的开放协议,一次提交,Bing / Yandex / Naver / Seznam / 360 等参与引擎全部生效
- 百度主动推送:调用百度搜索资源平台的普通收录接口
推送历史面板
每次推送的结果都会记录到数据库(时间 / 文章 / 目标 / 成功或失败 / 响应详情),后台左侧菜单有一个独立的 「TeoSeo → 推送历史」 面板页,最近 50 条一目了然。
这个功能上线当天就立了大功:测试时日志显示百度推送一直失败,报错 SSL: no alternative certificate subject name matches target host name——虚拟主机环境 PHP curl 的证书校验问题。没有推送历史,这种"悄悄失败"的 bug 可能永远发现不了。修复之后,百度推送的 JSON 响应(成功数和剩余配额)现在都清清楚楚躺在历史里。
安装与配置
安装
- 从 GitHub 下载:github.com/Astarry-1127/TeoSeo(或直接下 v1.0.3)
- 解压后把
TeoSeo目录上传到usr/plugins/ - 后台 → 插件 → 启用 TeoSeo,搞定
配置两个推送凭据
① IndexNow API Key(必应等):
在 Bing Webmaster 登录后生成,32 位字符串。协议要求站点根目录有一个 {key}.txt 验证文件(内容就是 key 本身),插件会在推送时自动尝试写入;如果主机目录不可写,手动放一个即可。
② 百度推送 Token:
百度搜索资源平台 → 普通收录 → 主动推送 里获取,一串字符(形如 B3fOjAhPQ1R5HQch)。填入插件设置页即可,留空则跳过百度推送。
设置页还有两个开关:sitemap 是否包含首页/独立页面,按需勾选。
验证
访问 https://你的域名/sitemap.xml 应返回标准 XML;robots.txt 里加一行声明:
Sitemap: https://你的域名/sitemap.xml效果实测
以下是在生产环境(blog.astarry.cn,西部数码虚拟主机 + Typecho 1.3.0 + PHP 8.2)的真实输出。
sitemap 生成

/sitemap.xml 直接返回标准的 Sitemaps 0.9 协议 XML,首页、文章条目、lastmod 修改时间一应俱全。
发布推送

用 curl 模拟插件发布文章时的推送动作:
- IndexNow:
HTTP 200,提交成功 - 百度:返回
{"success":1,"remain":7},成功推送 1 条,当日还剩 7 条配额
这些结果同样会写进后台的「推送历史」面板,发布文章后随时可以回来核对。
给插件开发者:Typecho 1.3 适配要点
写这个插件的最大收获,是把 Typecho 1.3 的插件机制摸了一遍。1.3 相比 1.2 有不少变化,想给 1.3 写插件的朋友可以参考:
1.3 移除/变化的接口
- 全局接口
Typecho_Plugin_Interface没有注册:1.3 的插件接口是命名空间版Typecho\Plugin\PluginInterface,但后台的插件信息解析器(parseInfo)却是靠源码里implements Typecho_Plugin_Interface这个名字识别插件的。解决办法:插件文件头自己定义兼容空接口:
if (!interface_exists('Typecho_Plugin_Interface', false)) {
interface Typecho_Plugin_Interface {}
}Helper、Widget类命名空间化:1.3 里要用\Utils\Helper、\Typecho\Widget,全局别名没有注册- 表单类仍然兼容:
Typecho_Widget_Helper_Form及 Element 系列在 1.3 后台可用,配置页不用改 - 发布钩子保留:
Typecho_Plugin::factory('Widget_Contents_Post_Edit')->finishPublish = [类, 方法]依然有效
插件面板(独立后台页面)
用 Helper::addPanel(1, 'TeoSeo/logs.php', 'TeoSeo', '推送历史', 'administrator') 注册,deactivate 时 removePanel 移除。面板文件放在插件目录里,通过 admin/extending.php?panel=... 加载,文件内用 include __TYPECHO_ROOT_DIR__ . __TYPECHO_ADMIN_DIR__ . 'header.php' 复用后台框架。
两个容易踩的坑
- 虚拟主机 PHP curl:推送类插件在共享主机上,
CURLOPT_SSL_VERIFYPEER关了还不够,必须连CURLOPT_SSL_VERIFYHOST一起关,否则百度接口的证书 hostname 校验恒失败(IndexNow 反而没事) $options->plugin('插件名')配置缺失会抛 500 异常:插件刚启用还没配置时,读取插件配置务必 try/catch 兜底,否则一个空配置就能让 sitemap 直接 500
开源与后续
- 代码仓库:github.com/Astarry-1127/TeoSeo,GPL-2.0 协议,与 Typecho 一致
- 目前 v1.0.3:sitemap + 双通道推送 + 推送历史,已在生产环境稳定运行
- 欢迎 issue / PR / 使用反馈
后续计划里,可能会加 TDK 自动生成(标题/描述/关键词的 SEO 优化)、结构化数据(Article/WebSite JSON-LD)等。如果你也有 Typecho 1.3 的 SEO 需求,或者正在为 1.3 写插件,欢迎来仓库聊聊。
评论 (0)
暂无评论,快来抢沙发吧!