DragonRster`s Void
Banner Image
目录
脚本详解:generate-sitemap.ps1

让 Google 和 Bing 知道你的每一页


generate-sitemap.ps1 是构建流程的最后一步。它生成一个符合 Sitemap Protocol 0.9 标准的 XML 文件,告诉搜索引擎这个网站有哪些页面、每个页面最后更新时间是什么。虽然代码量不到 45 行,但它完成了 SEO 基础设施中最基础的一环。

1. Sitemap 协议简介

Sitemap Protocol 是 2005 年由 Google、Yahoo、Microsoft 联合推出的标准[1]。它定义了一个简单的 XML 格式,列出网站的所有 URL 及其元数据:


<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>https://www.dragonrster.cn/</loc>
    <lastmod>2026-04-28</lastmod>
  </url>
  <url>
    <loc>https://www.dragonrster.cn/blog-build-script.html</loc>
    <lastmod>2026-04-28</lastmod>
  </url>
  <!-- 更多 url... -->
</urlset>

每个 <url> 有两个字段:

  • <loc>(必填):页面的完整 URL,包括协议和域名
  • <lastmod>(可选但建议):页面的最后修改日期,格式为 YYYY-MM-DD
  • 协议还支持 <changefreq>(更新频率)和 <priority>(优先级),但本站的 sitemap 目前不使用——对于一个小型博客来说,所有页面平等对待即可[2]

    2. 代码逐段解析

    初始化:

    
    $projectRoot = Split-Path -Parent (Split-Path -Parent $MyInvocation.MyCommand.Path)
    $pagesDir = Join-Path $projectRoot "src\content\pages"
    
    $urls = @()
    $urls += [pscustomobject]@{
        Loc = 'https://www.dragonrster.cn/'
        LastMod = (Get-Date).ToString('yyyy-MM-dd')
    }
    

    首页(/)是硬编码添加的,因为它没有对应的 content-*.html 文件,不能被下面的文件扫描逻辑捕获。首页的 lastmod 使用当前日期——因为每次构建首页都会更新(侧边栏内容变化)。

    博客页面扫描:

    
    $blogDir = Join-Path $pagesDir 'blog'
    if (Test-Path $blogDir) {
        $blogFiles = Get-ChildItem (Join-Path $blogDir 'content-*.html')
            | Sort-Object Name
        foreach ($file in $blogFiles) {
            $baseName = $file.BaseName -replace '^content-', ''
            $loc = "https://www.dragonrster.cn/blog-$baseName.html"
            $lastMod = $file.LastWriteTime.ToString('yyyy-MM-dd')
            $urls += [pscustomobject]@{
                Loc = $loc
                LastMod = $lastMod
            }
        }
    }
    

    扫描逻辑的几个要点:

  • 只扫描中文博客目录(blog/),不包括 blog/en/ 下的英文文章
  • 文件名 content-{slug}.html → URL /blog-{slug}.html
  • 使用 $file.LastWriteTime 而非内容元数据中的日期——因为文件的修改时间反映了内容实际的最后更新时间
  • 文件按名称排序,确保 sitemap 中的 URL 顺序稳定
  • 3. 输出位置与命名

    sitemap 输出到项目根目录(而非 dist/):

    
    $sitemapPath = Join-Path $projectRoot 'sitemap.xml'
    Set-Content -Path $sitemapPath -Value $sitemap -Encoding UTF8
    

    这是因为 sitemap.xml 按约定必须放在网站的根目录。搜索引擎爬虫(如 Googlebot)会在爬取网站时首先查找 /sitemap.xml/robots.txt。如果 sitemap 放在 dist/ 子目录中,爬虫将无法自动发现它[3]

    同样放在根目录的配置文件还包括 robots.txt——不过那是一个静态文件,不需要脚本生成。

    4. 当前限制与改进方向

    当前版本有几个结构性的限制:

  • 缺少英文页面。 只扫描了 blog/ 目录,英文文章(blog/en/)没有被收录。这意味着 Google 可能不会索引英文版页面。修复方法很简单:增加对 blog/en/ 的遍历,生成 https://www.dragonrster.cn/en/blog-*.html 格式的 URL
  • 缺少归档和标签页。 archive.htmltags.html 也是重要的页面,应该被收录。需要在 $urls 数组中显式添加它们
  • 缺少草稿过滤。 当前版本不检查 draft: true 元数据——如果草稿文件存在于 blog/ 目录中,它们的 URL 也会被添加到 sitemap。不过因为 build.ps1 会跳过草稿,这些 URL 指向的页面不存在,搜索引擎会得到 404
  • 硬编码域名。 dragonrster.cn 直接写在代码中,如果域名变更,需要修改源代码。最佳实践是从配置文件或环境变量中读取[4]
  • 这些都是"第二版"的待办事项。对于当前站点规模(不到 20 篇文章),这些限制的实际影响很小。

    5. 搜索引擎发现流程

    一个完整的搜索引擎发现流程是这样的:

    
    1. 爬虫访问 robots.txt        → 检查是否有抓取限制
    2. 爬虫访问 /sitemap.xml      → 获取所有 URL 和最后修改时间
    3. 爬虫按 lastmod 优先级抓取  → 最近更新的页面优先被抓取
    4. 爬虫解析 HTML 内容         → 提取正文、标题、链接
    5. 页面进入索引               → 出现在搜索结果中
    

    sitemap 不保证收录——它只是一个建议。搜索引擎有权忽略某些页面,也有权抓取 sitemap 中没有列出的页面(如果它们被其他页面链接到)。但提供一个准确、最新的 sitemap 能显著加快新内容的收录速度[5]

    6. 为什么不用动态生成

    有些网站用 CGI 或 PHP 动态生成 sitemap(每次请求时扫描数据库),本站选择了静态生成。原因:

  • 文章数量少,每次构建时花 0.1 秒生成一个静态 XML 完全可接受
  • 静态文件可以被 Web 服务器缓存,不消耗 CGI 进程
  • 搜索引擎爬虫可能每天访问 sitemap,动态生成会导致不必要的服务器负载
  • 与整个站点的"纯静态"理念一致——只要可能,预先生成而非运行时计算
  • 这是一贯的设计哲学:静态优先,CGI 作为最后手段

    小结

    generate-sitemap.ps1 是五个脚本中最短的一个,但它的作用不容小觑——它是网站对外的"名片",告诉搜索引擎这个角落的存在。在 2026 年,一个没有 JavaScript、纯表格布局的 90s 风格网站能被 Google 搜索到,sitemap 功不可没。

    从代码角度看,它是五个脚本中最不需要维护的——只要文件命名约定不变,它就能持续正确地工作。这种"一次写对,长期运行"的特性,正是好工具的标志[6]


    [1]Sitemap Protocol 最初由 Google 在 2005 年 6 月推出(名为"Google Sitemaps"),同年 11 月被 Yahoo 和 Microsoft 采纳,形成了联合标准 sitemaps.org。2007 年,Ask.com 和 IBM 也加入了支持。

    [2]<priority> 的取值范围是 0.0 到 1.0,默认值 0.5。它告诉搜索引擎哪些页面更重要——但现代搜索引擎基本忽略这个字段,因为它们有自己的 PageRank 类算法来评估页面重要性。

    [3]sitemap 的自动发现机制还有一个补充方式:在 robots.txt 中添加 Sitemap: https://www.dragonrster.cn/sitemap.xml 行。本站的 robots.txt 可以添加这一行以提高可发现性。

    [4]实际上,更优雅的做法是从 web_server.py 的配置或环境变量中读取域名。但在 PowerShell 脚本中,硬编码对于个人博客来说并不是大问题。

    [5]Google 的官方文档指出,sitemap 对于"新网站"和"有大量动态内容的网站"特别有用。对于一个月更几次的个人博客,sitemap 的实际作用有限——但"有总比没有好"。

    [6]还有一个隐藏的优势:因为 sitemap 在构建时生成、在项目根目录输出,它也被 git 纳入了版本控制(通过 git add 后提交)。在 GitHub 上可以直接看到 sitemap.xml 的历史变化,这在调试 SEO 问题时非常有用。


    « 脚本详解:generate-rss.ps1 —— RSS 2.0 订阅源生成 返回主页 脚本详解:build.ps1 »
    English

    搜索

    最新文章

    » 脚本详解:build.ps1
    » 脚本详解:gener...
    » 脚本详解:gener...
    » 脚本详解:rebui...
    » 脚本详解:gener...

    » 文章归档


    本文标签

    教程 网站建设 脚本


    功能

    » RSS 订阅
    » GitHub 源码
    » 返回顶部
    » 文章归档


    DRAGONRSTER
    CC BY-NC-SA
    © 2004-2026 DragonRster • Made with HTML • 本站支持IE5.5+
    最佳浏览分辨率:1024x768 • 最后更新于 2026年04月29日 02:05:28