Sitemap 產生器 SEO 完整教學:XML 結構、優先級、Google 提交
寫給:每天看 GSC 收錄報表的 SEO、想知道 priority / changefreq 是不是真的影響排名的工程師、第一次架部落格不知道為什麼 Google 不收錄的個人站長。
Sitemap 是 2005 年 Google / Yahoo / Microsoft 聯合制定的 sitemaps.org 標準,讓搜尋引擎更快、更完整地發現網站所有頁面。但 sitemap 不是萬靈丹——填錯 priority 沒效、忘了拆 sitemap index 會被無視、IndexNow 才是 2026 年快速收錄的新主流。本文 14 分鐘把 sitemap.xml 規格、實作、Google / Bing 提交流程、常見陷阱一次講透。
1. Sitemap 是什麼
Sitemap 是一個 XML 檔案,列出網站希望被搜尋引擎索引的所有 URL:
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://example.com/</loc>
<lastmod>2026-06-05</lastmod>
<changefreq>weekly</changefreq>
<priority>1.0</priority>
</url>
<url>
<loc>https://example.com/about</loc>
<lastmod>2026-05-20</lastmod>
</url>
</urlset>
搜尋引擎 crawler 會:
- 透過
robots.txt找到 sitemap.xml - 解析 sitemap 取得所有 URL
- 對 URL 排程爬取與索引
1.1 為什麼需要 sitemap
| 場景 | 沒 sitemap 結果 |
|---|---|
| 新網站 | crawler 不知道有哪些頁面 |
| 內部連結少的孤立頁面 | 永遠不被發現 |
| JavaScript 重度渲染 | crawler 解析慢,可能跳過 |
| 大量頁面(10000+) | 完整爬取要數週 |
| 多語系 | 語系切換 URL 不被理解 |
有 sitemap:搜尋引擎可在數小時內取得完整 URL 列表,加速索引。
1.2 sitemap 規格上限
- 單檔上限:50000 URLs 或 50MB(未壓縮)
- 超過上限:用 sitemap index 拆多個檔
- 壓縮:可用 gzip(檔名
sitemap.xml.gz) - 編碼:UTF-8
- URL 必須:absolute(含
https://)
2. 5 個核心觀念
2.1 sitemap.xml 標準結構
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>必填,URL 地址</loc>
<lastmod>選填,最後修改時間 ISO 8601</lastmod>
<changefreq>選填,更新頻率</changefreq>
<priority>選填,相對重要性 0.0-1.0</priority>
</url>
</urlset>
只 <loc> 必填,其他都選填但建議寫。
2.2 priority / changefreq 的真相
這兩個欄位 Google 2020 年起明確說「忽略」。Google 公開:
"Google ignores
priorityandchangefreqvalues when reading sitemaps."
但 Bing / Yandex / Baidu 仍部分使用。實務建議:
- 寫進 sitemap 不會扣分
- 對 Google 無幫助
- 對其他引擎可能有小幫助
- 真正影響排名是內容品質 + 連結
2.3 lastmod 是關鍵
跟 priority 相反,<lastmod> Google 確實使用作為排程提示:
- lastmod 是「真實的修改時間」→ crawler 優先重爬
- lastmod 寫死或灌水 → Google 演算法降低信任
<lastmod>2026-06-05T10:00:00+08:00</lastmod>
<!-- 或簡化版 -->
<lastmod>2026-06-05</lastmod>
強烈警告:不要每次部署都把所有頁 lastmod 改成「今天」。Google 偵測到後會視為 spam 提示,降低整個 sitemap 信任度。
2.4 Sitemap Index(拆檔)
URL 多時必須拆:
<!-- sitemap.xml(索引檔) -->
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap>
<loc>https://example.com/sitemap-pages.xml</loc>
<lastmod>2026-06-05</lastmod>
</sitemap>
<sitemap>
<loc>https://example.com/sitemap-blog.xml</loc>
<lastmod>2026-06-05</lastmod>
</sitemap>
<sitemap>
<loc>https://example.com/sitemap-products.xml</loc>
<lastmod>2026-06-05</lastmod>
</sitemap>
</sitemapindex>
拆檔策略:
- 按類型(pages / blog / products)
- 按更新頻率(每日更新 / 月度更新)
- 按語系(zh-TW / en / ja)
2.5 多語系 hreflang
Sitemap 可標出每個 URL 的多語系版本:
<url>
<loc>https://example.com/zh-TW/about</loc>
<xhtml:link rel="alternate" hreflang="zh-TW" href="https://example.com/zh-TW/about" />
<xhtml:link rel="alternate" hreflang="en" href="https://example.com/en/about" />
<xhtml:link rel="alternate" hreflang="ja" href="https://example.com/ja/about" />
<xhtml:link rel="alternate" hreflang="x-default" href="https://example.com/en/about" />
</url>
x-default 是「未匹配任何語系時的 fallback」,通常指向英文版。
xmlns:xhtml="http://www.w3.org/1999/xhtml" 要加到 root:
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xhtml="http://www.w3.org/1999/xhtml">
3. 實戰範例
範例 1:Python 從檔案列表產 sitemap
from datetime import datetime
from pathlib import Path
BASE = "https://example.com"
def generate_sitemap(pages):
lines = ['<?xml version="1.0" encoding="UTF-8"?>',
'<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">']
for page in pages:
lastmod = datetime.fromtimestamp(Path(page).stat().st_mtime).strftime("%Y-%m-%d")
lines.append(" <url>")
lines.append(f" <loc>{BASE}/{page}</loc>")
lines.append(f" <lastmod>{lastmod}</lastmod>")
lines.append(" </url>")
lines.append("</urlset>")
return "\n".join(lines)
pages = ["about", "contact", "blog/post-1"]
with open("sitemap.xml", "w") as f:
f.write(generate_sitemap(pages))
範例 2:Node.js 從 Next.js 動態產
// app/sitemap.ts (Next.js 14+)
import { MetadataRoute } from "next";
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const posts = await fetchAllPosts();
return [
{ url: "https://example.com/", lastModified: new Date(), priority: 1.0 },
{ url: "https://example.com/about", lastModified: new Date(), priority: 0.8 },
...posts.map(p => ({
url: `https://example.com/blog/${p.slug}`,
lastModified: new Date(p.updatedAt),
changeFrequency: "weekly" as const,
priority: 0.7,
})),
];
}
Next.js 自動產 /sitemap.xml。
範例 3:bash + curl 從網站列出 URL
# 用 wget 爬取整站
wget --spider --recursive --no-verbose --output-file=urls.log https://example.com
grep -oP 'URL:\K[^ ]+' urls.log | sort -u > urls.txt
# 轉成 sitemap
{
echo '<?xml version="1.0" encoding="UTF-8"?>'
echo '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'
while read url; do
echo " <url><loc>$url</loc></url>"
done < urls.txt
echo '</urlset>'
} > sitemap.xml
範例 4:產 sitemap index
def generate_sitemap_index(sitemaps):
lines = ['<?xml version="1.0" encoding="UTF-8"?>',
'<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">']
for sm in sitemaps:
lines.append(" <sitemap>")
lines.append(f" <loc>https://example.com/{sm['file']}</loc>")
lines.append(f" <lastmod>{sm['lastmod']}</lastmod>")
lines.append(" </sitemap>")
lines.append("</sitemapindex>")
return "\n".join(lines)
sitemaps = [
{"file": "sitemap-pages.xml", "lastmod": "2026-06-05"},
{"file": "sitemap-blog.xml", "lastmod": "2026-06-05"},
]
with open("sitemap.xml", "w") as f:
f.write(generate_sitemap_index(sitemaps))
範例 5:自動 ping Google + Bing
import requests
def ping_search_engines(sitemap_url):
endpoints = [
f"https://www.google.com/ping?sitemap={sitemap_url}",
f"https://www.bing.com/ping?sitemap={sitemap_url}",
]
for ep in endpoints:
try:
resp = requests.get(ep, timeout=10)
print(f"{ep}: {resp.status_code}")
except Exception as e:
print(f"{ep}: {e}")
ping_search_engines("https://example.com/sitemap.xml")
2026 年更新:Google 2023 年停止接受 ping。改用 Google Search Console API 或直接相信 GSC 排程。Bing 仍接受 ping。
4. 進階技巧
4.1 IndexNow(推薦 2026 主流)
IndexNow 是 Microsoft + Yandex 推出的新標準,比 sitemap 快得多——頁面變更時主動推給搜尋引擎:
import requests, hashlib
KEY = "abc123def456..." # 32+ char 隨機字串
# 註冊 key(放網站 /KEY.txt)
# https://example.com/abc123def456.txt 內容就是 KEY
def submit_url(url):
payload = {
"host": "example.com",
"key": KEY,
"urlList": [url],
}
resp = requests.post("https://api.indexnow.org/indexnow", json=payload)
print(resp.status_code)
submit_url("https://example.com/new-post")
支援 Bing / Yandex / Naver / Seznam。Google 暫不支援(但 GSC 變更頻繁的網站可看到收錄加速間接好處)。
4.2 robots.txt 註冊 sitemap
User-agent: *
Allow: /
Sitemap: https://example.com/sitemap.xml
Sitemap: https://example.com/sitemap-images.xml
任何 crawler 看到 robots.txt 就會發現 sitemap。可以列多個 sitemap。
4.3 動態 sitemap(避免每次部署 lastmod 變動)
CMS 系統建議:
- 每篇文章獨立 lastmod = 文章最後編輯時間
- sitemap.xml 每天重生一次(cron)
- 沒改的頁面 lastmod 不動
# cron 每天 03:00 重產
0 3 * * * cd /var/www && python3 generate_sitemap.py
4.4 圖片 sitemap
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">
<url>
<loc>https://example.com/blog/post-1</loc>
<image:image>
<image:loc>https://example.com/img/cover.jpg</image:loc>
<image:title>封面圖</image:title>
</image:image>
</url>
</urlset>
幫助 Google Images 索引圖片。
4.5 影片 sitemap
<url>
<loc>https://example.com/videos/intro</loc>
<video:video xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">
<video:thumbnail_loc>https://example.com/img/intro-thumb.jpg</video:thumbnail_loc>
<video:title>介紹影片</video:title>
<video:description>30 秒產品介紹</video:description>
<video:content_loc>https://example.com/videos/intro.mp4</video:content_loc>
<video:duration>30</video:duration>
</video:video>
</url>
讓影片在 Google Video 搜尋出現。
5. 常見錯誤與解法
錯誤 1:lastmod 全寫今天
症狀:sitemap 提交後排名反降。 根因:Google 偵測到 spam pattern。 解法:lastmod 用真實檔案修改時間。
錯誤 2:sitemap 含 404 頁面
症狀:GSC 報告大量 "Submitted URL not found (404)"。 根因:刪除頁面後忘了從 sitemap 移除。 解法:部署時自動掃 404 從 sitemap 移除。
錯誤 3:sitemap 含 noindex 頁面
症狀:GSC 報告 "Submitted URL marked 'noindex'"。 根因:邏輯衝突——你說 index 又說 noindex。 解法:noindex 頁面不放 sitemap。
錯誤 4:sitemap 超過 50000 URL 沒拆
症狀:搜尋引擎只索引前 50000,剩下永遠看不到。 根因:忘了拆 index。 解法:拆 sitemap index。
錯誤 5:sitemap 用相對路徑
症狀:搜尋引擎無視。
根因:規格要求 absolute URL。
解法:所有 <loc> 含 https://example.com/...。
6. 用 SuperTools 線上版完成相同任務
不想寫產生器?打開 SuperTools Sitemap 工具:
- 三種輸入:URL 列表 / 上傳 CSV / 爬取網站
- 拆 index:超過 50000 自動拆
- 多語系 hreflang:填 zh-TW / en / ja 自動 alternate
- lastmod 自動填:從 URL HEAD response 抓 Last-Modified header
- 驗證:規格錯誤即時提示
- 下載:xml / gz
- GSC 提交指引:附 step-by-step 截圖
工具 client-side,URL 列表不上傳(只在你瀏覽器產生 XML)。
實際使用流程:
- 從 Next.js / Hugo 拿 URL 列表
- 開 supertools.tw/seo/sitemap-gen 貼上
- 勾選「Auto lastmod from HEAD」
- 下載 sitemap.xml + sitemap.xml.gz
- 上傳到網站 root + 在 GSC 提交
立即使用 SuperTools Sitemap 工具:https://supertools.tw/seo/sitemap-gen
7. 其他語言實作
Python(sitemap-generator)
# pip install ultimate-sitemap-parser
from usp.tree import sitemap_tree_for_homepage
tree = sitemap_tree_for_homepage("https://example.com")
for page in tree.all_pages():
print(page.url)
Node.js(sitemap)
import { SitemapStream, streamToPromise } from "sitemap";
const sm = new SitemapStream({ hostname: "https://example.com" });
sm.write({ url: "/about", changefreq: "weekly", priority: 0.8 });
sm.end();
const xml = (await streamToPromise(sm)).toString();
Go(sitemap)
import "github.com/snabb/sitemap"
sm := sitemap.New()
sm.Add(&sitemap.URL{Loc: "https://example.com/", ChangeFreq: sitemap.Weekly})
sm.WriteTo(os.Stdout)
Hugo(內建)
# config.yaml
sitemap:
changefreq: weekly
priority: 0.5
filename: sitemap.xml
Hugo 自動產 /sitemap.xml。
Bash
# 從 access log 抓 URL
awk '{print $7}' access.log | sort -u > urls.txt
# 用 awk 包成 XML
awk 'BEGIN{print "<?xml ...?>"; print "<urlset ...>"} {print "<url><loc>https://example.com" $0 "</loc></url>"} END{print "</urlset>"}' urls.txt > sitemap.xml
8. FAQ
Q1:priority 和 changefreq 還要寫嗎? Google 忽略但不會扣分。寫了給其他引擎參考。
Q2:sitemap 多久重產一次? 靜態網站:每次 build。CMS:每天 cron。流量大網站:每小時。
Q3:sitemap.xml 要放哪?
網站 root(https://example.com/sitemap.xml)。robots.txt 要 reference。
Q4:分頁列表(/blog?page=2)要不要進 sitemap? 不需要。Google 透過內部連結爬。
Q5:IndexNow 真的有用嗎? Bing / Yandex 收錄明顯加速。Google 不接,但對整體爬取頻率有間接幫助。
9. 實戰案例研究
案例 1:3000 篇文章站 sitemap 修法後流量翻倍
某內容站 3000 篇文章,原本:
- 單一 sitemap.xml 含全部
- 所有 lastmod 寫
2026-01-01(部署日) - robots.txt 沒 reference sitemap
- GSC 報告「Discovered - currently not indexed」1800 篇
修法(3 步驟):
- 拆 sitemap index(按月份分檔)
- lastmod 改用真實檔案修改時間
- robots.txt 加
Sitemap: https://... - 接 IndexNow,每次發新文 ping Bing/Yandex
結果(3 個月):
- 收錄頁面從 1200 → 2800
- 自然流量 +120%
- Bing 收錄速度從 3 週 → 1 小時
教訓:sitemap 三要素:拆檔、真 lastmod、connect。
案例 2:lastmod 灌水反被降權
某新聞網站每天部署一次,sitemap 把所有頁面的 lastmod 都改成「今天」,期望 Google 多爬。
結果:
- 1 個月後 Google 偵測 spam pattern
- 整個網站排名下降 40%
- GSC manual action 警告
修法:
- 全面取消「自動更新 lastmod」
- 只在文章真實編輯時更新 lastmod
- 等 3 個月恢復信任後排名才回來
教訓:lastmod 灌水比不寫更糟。
案例 3:多語系 hreflang 漏標導致語系亂跳
某跨國 SaaS 4 語系(zh-TW/en/ja/ko),sitemap 沒寫 hreflang alternate。
問題:
- Google 在韓國搜尋結果顯示英文版(不是韓文版)
- 日本 user 從 Google 點進去看到中文版
- 跨語系 user 體驗極差
修法:每個 URL 在 sitemap 加 hreflang alternate:
<url>
<loc>https://example.com/ko/about</loc>
<xhtml:link rel="alternate" hreflang="ko" href="https://example.com/ko/about" />
<xhtml:link rel="alternate" hreflang="zh-TW" href="https://example.com/zh-TW/about" />
<xhtml:link rel="alternate" hreflang="en" href="https://example.com/en/about" />
<xhtml:link rel="alternate" hreflang="ja" href="https://example.com/ja/about" />
<xhtml:link rel="alternate" hreflang="x-default" href="https://example.com/en/about" />
</url>
3 個月後各語系自然到位,跨國 user 滿意度大幅提升。
教訓:多語系站必標 hreflang,否則 Google 全靠猜。
10. 結論 + 延伸閱讀
Sitemap 是 SEO 的基本入場券,但更重要的是把 sitemap 與 IndexNow、Google Search Console 結合,並且保持 lastmod 真實性。下次新增頁面後,先到 SuperTools 線上工具產 sitemap,再用 IndexNow 主動推給 Bing / Yandex,把收錄時間從數週縮到數小時。三條黃金法則:lastmod 真實不灌水、多語系必含 hreflang、IndexNow 是 2026 收錄加速器。
延伸閱讀: