Flask 博客 SEO 工程补强:结构化数据、分页 canonical 与 noindex 协同清单

很多 Flask 博客把 SEO 做到 sitemap.xmlcanonicalhreflang 就停下来了,但长期维护阶段真正容易出问题的是第二层:分页都 canonical 到第一页、搜索页既写 noindex 又被 robots.txt 禁抓、文章页有 JSON-LD 却没有 breadcrumb 层级。

基础可用:先划清哪些页该收,哪些页别收

真正值得长期索引的,通常只有文章详情页、核心分类页、少量高质量标签页和有独立价值的作者页。登录、后台、用户中心、搜索结果和空列表页,不应该参与收录竞争。

分页页码最容易误配。只要第 2 页、第 3 页承载的是不同文章集合,它们就不是第一页的重复页。更稳的做法是:

  1. 第 1 页 canonical 到干净 URL。
  2. ?page=2?page=3 各自输出自己的 canonical。
  3. 分页导航保留真实 <a href> 链接,别只靠前端事件。
{% if pagination.page > 1 %}
  {% block canonical_url %}{{ page_url('category_page', pagination.page, {'slug': category.slug}) }}{% endblock %}
{% else %}
  {% block canonical_url %}{{ abs_url_for('category_page', slug=category.slug) }}{% endblock %}
{% endif %}

搜索页还有一个常见坑:模板里写了 noindex,followrobots.txt 又写 Disallow: /search。如果你依赖 noindex,搜索页至少要允许被抓到。

生产加固:结构化数据只给高价值页

页面分层之后,再补强结构化数据。文章详情页最实用的是 BlogPostingArticle JSON-LD:headlinedescriptiondatePublisheddateModifiedauthormainEntityOfPageimage

def article_schema(article):
    return {
        "@context": "https://schema.org",
        "@type": "BlogPosting",
        "headline": article.title,
        "description": article.summary,
        "datePublished": (article.published_at or article.created_at).isoformat(),
        "dateModified": (article.updated_at or article.published_at or article.created_at).isoformat(),
        "author": {"@type": "Person", "name": article.author.nickname},
        "mainEntityOfPage": abs_article_public_url(article),
    }

如果站点已经有“首页 -> 分类 -> 文章”的固定路径,下一步优先补 BreadcrumbList。相反,noindex 搜索页和薄内容标签页就没必要堆结构化数据。

性能与安全:把抓取成本和索引信号一起管住

SEO 工程不是无限放开抓取,而是把“可索引”和“可抓取但不索引”分开管理。标签页如果只有一两篇文章,通常更适合保留链接关系,但用 noindex,follow 控制收录。

搜索页则要兼顾抓取成本。允许搜索页可抓,不等于放任参数无限扩散。至少要做三件事:

  • 限制空查询和超长关键词。
  • 给搜索结果和列表页保留真实分页链接,避免深层文章只能靠前端加载。
  • 单独观察 /search/tag/<slug>/category/<slug>?page=n 的访问日志。

这里的取舍很现实:允许爬虫读取 noindex 搜索页,会多一点抓取成本;但换来的是更一致的信号。

自动化与维护:把校验塞进发布流程

长期维护型博客最怕模板改动后 SEO 悄悄退化。发布后至少固定检查三类页面:

curl -s https://stepnex.cn/category/tech?page=2 | rg "canonical|robots|application/ld\+json"
curl -s https://stepnex.cn/search?q=flask | rg "robots|canonical"
curl -s https://stepnex.cn/robots.txt

巡检顺序我建议固定为:

  1. 文章详情页看 canonical、JSON-LD、更新时间和封面图是否一致。
  2. 分类第 2 页看 canonical 是否还错误指向第 1 页。
  3. 搜索页看 noindex 是否存在,同时确认 robots.txt 没把它挡死。
  4. Search Console 看“具有适当规范页的替代页”“已排除(noindex)”“已抓取但未编入索引”是否符合预期。
  5. 访问日志里看搜索页和标签页是否异常增多。

复盘清单

  • 文章详情页是否有自洽的 canonical、结构化数据和可访问封面图。
  • 分类、标签、作者分页是否为每个页码输出独立 canonical。
  • 搜索页如果依赖 noindexrobots.txt 是否已经放开对应路径。
  • 低价值列表页是否使用 noindex,follow,而不是粗暴 canonical 到首页或第一页。
    把这些点理顺后,Flask 博客的 SEO 才算从“堆标签”进入“站点结构管理”,能减少错误收录和返工。