robots.txt 怎麼寫?擋爬蟲與開放爬取的正確姿勢
robots.txt 是爬蟲造訪網站時 第一個讀的檔案。它管的是「哪些路徑可以下載」,也就是 索引流程 的第二關。大多數網站只需要這樣:
User-agent: *
Allow: /
Sitemap: https://example.com/sitemap.xml位置與生效範圍
| 規則 | 說明 |
|---|---|
| 必須放在 根目錄 | https://example.com/robots.txt |
| 逐主機生效 | 主網域與子網域各自需要一份 |
| 區分通訊協定與埠號 | http 與 https 視為不同來源 |
| 檔名固定小寫 | Robots.txt 不會被讀取 |
放在子目錄完全無效
https://example.com/blog/robots.txt 會被完全忽略。子目錄的規則要寫在根目錄那一份裡。
如果 blog.example.com 是獨立的子網域,那它需要自己的 https://blog.example.com/robots.txt。
四個指令
User-agent: Googlebot
Disallow: /admin/
Allow: /admin/public/
Sitemap: https://example.com/sitemap.xml| 指令 | 作用 |
|---|---|
User-agent | 下面的規則對哪個爬蟲生效,* 代表全部 |
Disallow | 不要下載這個路徑 |
Allow | 允許下載這個路徑(用來在封鎖區裡開洞) |
Sitemap | 網站地圖 的位置,必須是絕對網址 |
Sitemap 不屬於任何 User-agent 群組,放在檔案任何位置都生效。
分群寫法
一個 User-agent 加上它的規則構成一個群組,空行分隔:
# 給所有爬蟲
User-agent: *
Disallow: /admin/
Disallow: /api/
# 只給 Googlebot 的額外規則
User-agent: Googlebot
Disallow: /admin/
Disallow: /api/
Disallow: /internal/
Sitemap: https://example.com/sitemap.xml爬蟲只讀最符合自己的那一組
Googlebot 看到有專屬於它的群組時,只會讀那一組,完全忽略 * 的群組。所以專屬群組必須把通用規則 完整重寫一次,不會自動繼承。
這是最容易出錯的地方,上面的例子若把 Googlebot 群組裡的 /admin/ 與 /api/ 省略,對 Googlebot 來說那兩個路徑就變成開放的。
比對規則
前綴比對
路徑是 前綴比對,不需要寫完整:
Disallow: /admin這會擋住 /admin、/admin/、/admin/users,也會擋住 /administrator,因為它也以 /admin 開頭。要精確一點就加斜線:
Disallow: /admin/萬用字元
| 符號 | 意義 | 例 |
|---|---|---|
* | 任意長度的任意字元 | Disallow: /*.pdf$ |
$ | 路徑結尾 | Disallow: /*?$ |
# 擋掉所有 PDF
Disallow: /*.pdf$
# 擋掉所有帶查詢參數的網址
Disallow: /*?
# 擋掉特定參數
Disallow: /*?sort=衝突時誰贏
路徑比較長的那一條贏,與順序無關
Disallow: /admin/
Allow: /admin/public//admin/public/page.html 會 被允許,因為 /admin/public/ 比 /admin/ 長。
長度相同時採用 比較寬鬆 的規則,也就是允許爬取。
這個規則讓「封鎖整個目錄但開放其中一個子路徑」變得很簡單,不必列舉所有要封鎖的路徑。
封鎖不等於不收錄
這是 robots.txt 最大的誤解
Disallow 叫爬蟲 不要下載 這一頁,不是叫它 不要收錄。
如果有其他頁面(包含外部網站)連到那個網址,搜尋引擎仍可能把 網址本身 列進搜尋結果,只是因為讀不到內容而顯示空白摘要。
要真正阻止收錄必須用頁面層級的 noindex,而 noindex 需要爬蟲讀得到頁面,所以 這兩者不能同時用在同一個網址上。
| 目的 | 該用什麼 |
|---|---|
| 不想被收錄 | 允許爬取 + 頁面標 noindex |
| 不想浪費爬取預算 | Disallow(接受網址可能被列出) |
| 已收錄、想移除 | 先 noindex,移除後才考慮 Disallow |
常見的封鎖對象
User-agent: *
# 後台與 API
Disallow: /admin/
Disallow: /api/
# 站內搜尋結果(無限組合,浪費爬取預算)
Disallow: /search
Disallow: /*?q=
# 購物車與結帳流程
Disallow: /cart
Disallow: /checkout
# 排序與篩選參數產生的重複頁面
Disallow: /*?sort=
Disallow: /*?filter=
Sitemap: https://example.com/sitemap.xml不要封鎖樣式與程式碼
# 不要這樣做
Disallow: /assets/
Disallow: /*.css$
Disallow: /*.js$搜尋引擎需要載入 CSS 與 JavaScript 才能 正確渲染頁面 、判斷行動裝置友善度。封鎖它們會讓爬蟲看到一個沒有樣式的破版頁面。
圖片與 favicon 同理,封鎖了會影響圖片搜尋與搜尋結果的圖示。
依環境自動產生
不要靠人工維護
「上正式機時忘了改回來」與「部署測試機時把正式站封鎖掉」是兩種都很痛的意外。正確做法是 由建置流程依環境產生:
// scripts/gen-robots.mjs:建置完成後執行,把 robots.txt 寫進輸出目錄
import { writeFileSync } from 'node:fs';
import { resolve } from 'node:path';
const outDir = process.argv[2] ?? 'dist';
const domain = process.env.SITE_HOST;
const isProduction = process.env.NODE_ENV === 'production';
// 只有正式機開放檢索,其餘環境一律封鎖
const content = isProduction
? `User-agent: *
Allow: /
Sitemap: ${domain}/sitemap.xml
`
: `User-agent: *
Disallow: /
`;
writeFileSync(resolve(outDir, 'robots.txt'), content, 'utf-8');接在建置指令後面就好,不限框架:
{
"scripts": {
"build": "<您的建置指令> && node scripts/gen-robots.mjs dist"
}
}框架有鉤子就用鉤子
多數建置工具都提供建置結束的鉤子,也有框架直接支援動態產生(例如 Next.js 的 app/robots.ts)。 用哪一種都行,重點是 內容由環境變數決定,而不是靠人記得改檔案。
測試機還要補 noindex
測試機光靠 Disallow: / 不夠,前面說過封鎖不等於不收錄。在伺服器層補上回應標頭才萬無一失:
X-Robots-Tag: noindex檔案本身的注意事項
| 項目 | 要求 |
|---|---|
| 編碼 | UTF-8 |
| 大小 | 500KB 以內(超過的部分可能被忽略) |
| 註解 | 用 # 開頭 |
| 回傳狀態碼 | 必須是 200 或 404 |
回傳 5xx 會讓爬蟲暫停抓取整站
robots.txt 回傳伺服器錯誤時,部分爬蟲會保守地假設「規則不明,先不要抓」而暫停抓取整個網站。
所以這個檔案的可用性比它的內容更重要。沒有 robots.txt 而回傳 404 是完全安全的(等同全站開放),回傳 500 才是災難。
驗證
| 方式 | 怎麼做 |
|---|---|
| 直接開 | 瀏覽器輸入 您的網域/robots.txt |
| 單一網址測試 | Search Console 的網址檢查會顯示是否被封鎖 |
| 上線前檢查 | 建置後確認產出的內容符合當前環境 |
檢查清單
| 項目 | 標準 |
|---|---|
| 放在根目錄且可存取 | 必備 |
| 正式機為開放爬取 | 必備 |
| 非正式環境為全站封鎖 | 必備 |
有宣告 Sitemap(絕對網址) | 建議 |
| 沒有封鎖 CSS、JS、圖片 | 必備 |
沒有同時用 Disallow 與 noindex | 必備 |
專屬 User-agent 群組已重寫通用規則 | 必備 |
| 依環境自動產生而非人工維護 | 建議 |
常見問題
robots.txt 一定要放在根目錄嗎?
一定要,而且只在同一個主機名稱與通訊埠下生效。放在子目錄的檔案會被完全忽略。另外它是逐主機生效的,主網域與子網域各自需要一份。
Disallow 和 Allow 衝突時哪個贏?
路徑字串比較長的那一條贏,與撰寫順序無關。長度相同時採用比較寬鬆的規則,也就是允許爬取。所以要在封鎖的目錄裡開放某個子路徑,只要寫一條更精確的 Allow 就行。
封鎖了為什麼網址還出現在搜尋結果?
因為封鎖的是下載動作而不是收錄。若有其他頁面連到那個網址,搜尋引擎仍可能把網址列進結果,只是讀不到內容而顯示空白摘要。要真正阻止收錄必須改用頁面層級的 noindex 。
沒有 robots.txt 會怎樣?
等同於全站開放爬取,不會有負面影響。但建議還是放一份,一來可以宣告 網站地圖 的位置,二來方便日後需要封鎖特定路徑時直接修改。要注意檔案回傳伺服器錯誤時,部分爬蟲會保守地暫停抓取整站。
測試機要怎麼避免被收錄?
把 robots.txt 的內容依環境自動產生,非正式環境一律輸出全站封鎖,並在伺服器層補上 noindex 回應標頭。不要靠人工維護一份檔案,那遲早會出現上線忘了改回來的意外。