從 XML sitemap 拉出 URL,可以用命令列管線(curl、grep、sed、awk 或 xmllint),也可以用瀏覽器型解析器;哪種比較適合,取決於你在稽核時更重視自動化、隱私,還是嚴格的協定驗證。用熟悉的工具拼成的命令列管線可以抓回 sitemap、把其中的 loc 值攤平成清單,但它會把檔案的每個位元組都寫到磁碟、去重與命名空間處理都得自己寫腳本,而且名單可用之前還得手動清理。瀏覽器型解析器則把流程整個翻過來:你把 sitemap XML 貼進編輯器、在本機執行萃取,立刻得到一份依首次出現順序排列、已去重的 URL 清單,並在最前面回報根型別、唯一筆數與移除的重複筆數。兩種做法都不會聯絡搜尋引擎;HTTP 狀態、canonical、robots 與索引狀態的檢查,仍舊屬於另外對線上網站進行的工作。改變的只是誰來處理實體解碼、命名空間前綴、主機正規化,以及 2,048 字元的 loc 上限——是你的 shell 管線,還是瀏覽器解析器。

常見的 Sitemap URL 萃取命令列做法
命令列萃取通常從下載開始。curl 或 wget 從某個 URL 把 sitemap 檔抓回來,而 cat 或 zcat 則處理你磁碟上已有的檔案,在解析器之外先把 .gz 格式的 sitemap 解壓縮。接著要選哪個定位工具,就看你最信任哪一個。
最簡單的管線是用 grep 抓 loc 的起始標籤,寄望下一行就放著 URL:
curl -s https://example.com/sitemap.xml | grep -oE 'https?://[^<]+'
當 sitemap 使用預設命名空間,而且 loc 獨立成一行時,這個模式可以運作;可是一旦檔案裡出現像 sm:loc 這種命名空間、註解、與內容同行的 XML 宣告,或自我閉合的 loc 標籤,它就會立刻失效。改用 grep -oE '<loc>[^<]+' 這類更嚴的樣式可以提高準確率;換成 sed -n 's/.*<loc>\(.*\)<\/loc>.*/\1/p' 或 awk '/<loc>/{gsub(/.*<loc>|<\/loc>.*/,""); print}' 則加上更多結構。但這些工具都無法解碼 XML 實體、無法把主機標準化為小寫、無法去除預設埠號,也無法依序列化後的 URL 去重——它們只是印出文字。
對在意協定遵循程度的網站來說,xmllint --xpath '//*[local-name()="loc"]/text()' sitemap.xml 是最接近真正解析器的命令列做法。它會處理命名空間、忽略註解、辨識協定定義的兩種根型別,但去重、主機正規化與 2,048 字元上限,仍得交給你下游的腳本。
命令列做法在哪裡會失效
命令列管線雖然強大,卻會把資料裡的每一個漏洞都攤在執行腳本的人面前。只要實際上線的 sitemap 偏離最單純的教科書形狀,失敗模式就會冒出來。
- 命名空間前綴。網站輸出 sm:urlset、sm:url 與 sm:loc 仍然能通過 xmllint 與任何現代解析器,但寫死 <loc> 的陽春 grep 會回傳空清單,而且看起來像是沒事。
- 實體解碼。像 & 這種標準 XML 實體在 URL 裡只該解碼一次,不能解兩次。直接印出原始文字的管線會把 & 送進你的試算表,污染之後所有請求。
- 重複變體。同一個頁面可能以 HTTP 與 HTTPS、有沒有結尾斜線、主機大小寫混用、或帶有明確預設埠號的方式出現。grep 與 awk 不會察覺這些重複;你會在更晚之後才發現——當清單對不上你的 canonical URL 時。
- 超過上限的輸入。當 sitemap 突破 50,000 筆 URL 的門檻,或單一筆超過協定規定的 2,048 字元 loc 上限時,多數命令列管線不會丟出結構化錯誤——它只會繼續印下去,或無預期地截斷。
- DTD 宣告與自訂實體。以 <!DOCTYPE> 開頭或定義自訂實體的 sitemap,可能讓 xmllint 整個炸掉,或被 sed 誤讀,因為兩者都預期輸入是可預期的 token 切法。
每一個漏洞都能再補一行 shell 來解決;但每多一行,稽核就多一個依賴——依賴操作者對協定熟到能預期失敗。當團隊在審視這份工作成果時,這份清單很難自圓其說:審閱者根本無法判斷重複項是有意被移除,還是從頭到尾根本沒印第二次。
Sitemap URL Extractor 的做法
Sitemap URL Extractor 採取不同的立場。它只接受一種輸入——從單一 urlset 或 sitemapindex 文件貼上的 XML 文字——也只產出一種輸出:一份逐行排列、已去重的 URL 清單,可直接送進剪貼簿、試算表或重新導向稽核。因為解析器完全在你的瀏覽器裡執行,XML 從不離開你的裝置——這在 sitemap 列出上線前 URL、staging 主機或私有子網域時格外重要。
在底層,解析器會先剝掉檔首的位元組順序標記、XML 宣告與註解,拒絕 DTD 與自訂實體宣告,接著走訪封閉的 urlset/url/loc 或 sitemapindex/sitemap/loc 結構。它接受協定定義的兩種根型別,包含一致的可選命名空間前綴,且只解碼五個預先定義的 XML 實體與合法的十進位或十六進位 Unicode 純量參照。任何它解析不出的東西——巢狀 loc 標記、未知實體、不完整的項目、格式錯誤的根元素——都會讓整次執行失敗,並給出指向出問題的 loc 或項目的編號位置,這樣可以回頭修正來源,而不是被悄悄略過。
接著每個解碼後的值會交給瀏覽器的 WHATWG URL 實作來解析——就是驅動網址列的同一個序列化器——它會把主機轉小寫、移除預設埠號,並在需要時對非 ASCII 的路徑字元做 percent-encoding。含有憑證、片段、原始空白字元、格式錯誤的 percent 跳脫、反斜線、相對路徑與非 HTTP 協定的 URL 都會被拒絕;而且每個序列化後的 URL 都必須落在協定規定的 2,048 字元上限之內。序列化後值相同的 URL 視為重複,只會回傳第一筆,因此輸出會保留來源中首次出現的順序。
貼上、萃取、複製:三步工作流程
Sitemap URL Extractor 遵循三個操作步驟,直接對應到已驗證的產品合約:
- 把單一 urlset 或 sitemapindex 文件的完整 XML 文字貼進編輯器。用任何文字編輯器開啟你存好的 sitemap 檔案,全選,再貼進輸入框。如果檔案是 .gz,請先用 gunzip 或你的編輯器先解壓縮;這個小工具不會自己抓 URL,也不會讀取壓縮檔。
- 萃取出直接的 loc 值,並檢視根型別、唯一筆數、重複筆數與完整輸出。執行萃取後讀取回報的數字:偵測到哪種根結構、接受了多少筆唯一 URL、移除了多少筆經過正規化的重複項。完整且已去重的清單會在下方以每行一個 URL 的方式呈現,順序與來源中首次出現的順序一致。
- 複製這份每行一個 URL 的清單,然後視需要另外進行線上狀態、canonical、robots 與索引狀態的檢查。用複製按鈕把清單放進剪貼簿,再送入爬蟲檢查清單、試算表、重新導向稽核或搬遷審查。把這份輸出當成更大規模稽核中的證據,而不是索引狀態的證明,並搭配對實際頁面進行的 HTTP、canonical、robots 與索引狀態檢查。
每一步都在用戶端強制執行;不會上傳、不會抓取、也不會展開任何東西。
命令列 vs 瀏覽器工具:並排比較
下表把兩種做法,按稽核人員實際會問的問題對齊比較。
| 考量項目 | 命令列管線 | 瀏覽器型 Sitemap URL Extractor |
|---|---|---|
| 輸入來源 | 透過 curl 或 wget 下載,或讀取已存檔案 | 僅接受貼上的 XML 文字 |
| 網路曝露 | XML 會下載到磁碟或經由 shell 管線傳遞 | 不發出任何網路請求;解析完全在本機瀏覽器內進行 |
| 命名空間處理 | 取決於使用的 regex 或 xmllint xpath | 一致地辨識預設與帶前綴的命名空間 |
| 實體解碼 | 除非另寫腳本,否則直接印出原始文字 | 解碼五個具名實體與合法的數值參照 |
| 重複項處理 | 由操作者撰寫去重邏輯;大小寫與埠號變體常會漏網 | 透過 WHATWG URL 序列化,依首次出現順序去重 |
| 大小上限 | 取決於 shell 記憶體與命令列限制 | 50,000 筆唯一 URL 及五百萬個 UTF-16 字碼單元;超出時直接失敗而非截斷 |
| 錯誤回報 | 空輸出、部分輸出或堆疊追蹤 | 指向出問題的 loc 或項目的明確編號位置 |
| 輸出 | 需要下游清理的原始行 | 每行一個 URL,並回報根型別與筆數 |
| 索引或 HTTP 檢查 | 未執行 | 未執行;清單供另一輪線上稽核使用 |
Choosing the Right Method for Your Audit
The honest answer to command line versus online is that neither is universally better. The choice tracks the job: who is running it, where the file lives, and what the output has to defend.
Reach for a command-line pipeline when the sitemap is already on disk, the audit is one of dozens you run automatically against a fleet of properties, and the operator understands the protocol well enough to write the namespace and dedup logic from scratch. Scripted extraction also wins when you need to chain the URL list directly into the next stage of automation — a crawl queue, a redirect map generator, or a log diff — without ever copying into a clipboard.
Reach for a browser-based parser such as the Sitemap URL Extractor when the XML contains information you do not want to send to a server, when a teammate who is not a shell user has to verify the list, or when the audit needs a defensible answer to how many duplicates were removed. A browser parser also makes sense as a quick sanity check before a command-line job runs at scale, because the rules it enforces — absolute HTTP or HTTPS locs only, the 2,048-character cap, no DTDs, namespace-aware parsing, dedupe by WHATWG serialization — match the protocol rather than a chosen regex.
Whichever method you use, remember that an extracted URL only confirms that a valid loc appeared in the pasted structure and passed the disclosed validation. It is not evidence that the page is crawlable, canonical, valuable, or indexed, and the Google sitemap documentation describes sitemaps as discovery hints rather than indexing guarantees. Use the list to drive the next round of live checks, and treat any disagreement between the sitemap and your canonical inventory as a signal worth investigating rather than as a bug to suppress.
If you're weighing options, Generate a URL List From a Pattern: A Practical Guide covers this in detail.
If you're weighing options, Does llms.txt Replace robots.txt or sitemap.xml? Explained covers this in detail.