用 Laravel 簡單製作 Sitemap

JokerLinly發表於2017-03-20

幾年前,搜尋引擎就已經鼓勵人們提交的 Sitemap 來幫助搜尋引擎索引你的網站。直到現在,研究如何提交 Sitemap 這件事情依舊很值得學習。

為了翻譯好原文,我花了一點時間研究了 Sitemap,並把我知道的整理出來。

什麼是 Sitemap

Google 為其作了定義:

Sitemap 是一個檔案,在其中列出網站的網頁,告訴 Google 和其他搜尋引擎你的網站內容的組織情況。 當 Googlebot 等搜尋引擎網路抓取工具讀取到這個檔案,就會更智慧地抓取你的網站。

他們還概述了一些為什麼你要提交這個檔案的原因:

  • 如果你的網站很大,Google 網頁抓取工具可能會忽略一些新的或最近更新的網頁。
  • 你的網站有大量的內容頁存檔,這些內容頁彼此隔離或完全沒有相互關聯。如果你的網站網頁不會自然地相互引用,則可以在 Sitemap 中列出這些網頁,以確保 Google 不會忽略某些網頁。
  • 如果你的網站是新的,而且指向網站的連結不多。Googlebot 和其他網路抓取工具會隨著連結從一個網頁到另一個網頁來抓取網路。因此,如果沒有其他網站連結到你的網頁,Google 可能很難發現你的網頁。
  • 如果你的網站使用大量富 AJAX 或 Flash 內容的頁面,則不容易被 Googlebot 發現。但如果是顯示在 Google 新聞中,或使用其他與 Sitemap 相容的註釋。Google 就可以根據需要將 Sitemap 中的其他資訊納入搜尋範圍。

你的網站可能不符合上述難以抓取的原因,但我覺得,就算只是出於網站安全的考慮,提交一個 Sitemap 也是值得的。

Sitemap 協議

在官方 Sitemaps 網站上,它列出了構建 Sitemap 所需的所有資訊。下面是 XML 格式的基本示例:

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
   <url>
      <loc>http://www.example.com/</loc>
      <lastmod>2005-01-01</lastmod>
      <changefreq>monthly</changefreq>
      <priority>0.8</priority>
   </url>
</urlset> 

如你所見,Sitemap 只是一個 XML 檔案,而且每個網站頁面都有一個 <url>

單個 XML 檔案大約可以容納 50,000 條記錄,但是你也可以將它們分成多個檔案,並利用索引檔案指向其他檔案。當然官網也有簡單的示例介紹:

<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
   <sitemap>
      <loc>http://www.example.com/sitemap1.xml.gz</loc>
      <lastmod>2004-10-01T18:23:17+00:00</lastmod>
   </sitemap>
   <sitemap>
      <loc>http://www.example.com/sitemap2.xml.gz</loc>
      <lastmod>2005-01-01</lastmod>
   </sitemap>
</sitemapindex>

在每個 <loc> 內,它指向包含 <url> 專案的 XML 檔案,如第一個示例中所示。

本教程使用了索引樣式,用來自不同表的記錄,自定義每個 URL 列表,從而無需進行額外的處理。

構建 Sitemap 控制器

我的 Sitemap 會有兩個主要部分,分別是部落格文章、部落格類別和播客列表。 每個部分都會在屬於自己的檔案中,並且有索引將指向它們。

首先,用下面的指令建立 Sitemap 的控制器:

php artisan make:controller SitemapController

現在開啟這個檔案,我們建立一個 Sitemap 索引。

建立 Sitemap 索引

下面是建立一個新的索引方法,這個方法會生成所需的 XML:

public function index()
{
  $post = Post::active()->orderBy('updated_at', 'desc')->first();
  $podcast = Podcast::active()->orderBy('updated_at', 'desc')->first();

  return response()->view('sitemap.index', [
      'post' => $post,
      'podcast' => $podcast,
  ])->header('Content-Type', 'text/xml');
}

釋出和播客查詢需要在索引檢視中生成最後修改的時間戳,這樣才能讓抓取工具知道是否新增了新的內容。

另外,header() 這個返回樣式可能甚少用到,我在這裡解釋下:它返回一個響應物件,分配檢視的同時把 header 設定為 text/xml 。 如果你只返回一個 view() ,就無法訪問到 XML 檔案。

接下來,我們的 sitemap.index 檢視檔案將如下所示:

<?php echo '<?xml version="1.0" encoding="UTF-8"?>'; ?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
    <sitemap>
        <loc>https://laravel-news.com/sitemap/posts</loc>
        <lastmod>{{ $post->publishes_at->tz('UTC')->toAtomString() }}</lastmod>
    </sitemap>
    <sitemap>
        <loc>https://laravel-news.com/sitemap/categories</loc>
        <lastmod>{{ $post->publishes_at->tz('UTC')->toAtomString() }}</lastmod>
    </sitemap>
    <sitemap>
        <loc>https://laravel-news.com/sitemap/podcasts</loc>
        <lastmod>{{ $podcast->publishes_at->tz('UTC')->toAtomString() }}</lastmod>
    </sitemap
</sitemapindex>

在這個檢視裡,我只是採取我自定義的 publishes_at 時間戳,使用 Carbon  設定時區為 UTC,最後使用 Carbon Atom 字串將格式正確化。

建立 Sitemap URL 檔案

下一步是建立每個 URL 的檔案。 在 SitemapController 控制器裡寫三個相似的新方法。 如下:

public function posts()
{
    $posts = Post::active()->where('category_id', '!=', 21)->get();
    return response()->view('sitemap.posts', [
        'posts' => $posts,
    ])->header('Content-Type', 'text/xml');
}

public function categories()
{
    $categories = Category::all();
    return response()->view('sitemap.categories', [
        'categories' => $categories,
    ])->header('Content-Type', 'text/xml');
}

public function podcasts()
{
    $podcast = Podcast::active()->orderBy('updated_at', 'desc')->get();
    return response()->view('sitemap.podcasts', [
        'podcasts' => $podcast,
    ])->header('Content-Type', 'text/xml');
}

接著建立一個檢視檔案 sitemap.posts :

<?php echo '<?xml version="1.0" encoding="UTF-8"?>'; ?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
    [@foreach](https://learnku.com/users/5651) ($posts as $post)
        <url>
            <loc>https://laravel-news.com/{{ $post->uri }}</loc>
            <lastmod>{{ $post->publishes_at->tz('UTC')->toAtomString() }}</lastmod>
            <changefreq>weekly</changefreq>
            <priority>0.6</priority>
        </url>
    @endforeach
</urlset>

同樣地複製好其他檢視之後就寫路由:

Route::get('/sitemap', 'SitemapController@index');
Route::get('/sitemap/posts', 'SitemapController@posts');
Route::get('/sitemap/categories', 'SitemapController@categories');
Route::get('/sitemap/podcasts', 'SitemapController@podcasts');

你可能注意到我選擇不使用 XML 副檔名,這不是必須的。不過如果你喜歡,可以新增副檔名到路由:

Route::get('/sitemap.xml', 'SitemapController@index');

最後只需調整檢視以指向正確的位置。

小結

用 Laravel 寫 Sitemap 並不是很難,特別是當你的網站結構像我的一樣簡單。 如果你想自動化整個程式,用這個包 也是比較方便的。

當然還可以建立有 影像視訊 的 Sitemap,甚至你還可以建立自己的 XSL 樣式表

以上內容翻譯改編自 Eric L. Barnes 的 Building a Search Engine Friendly Sitemap XML with Laravel

Stay Hungry, Stay Foolish.

相關文章