xin9le.net

Microsoft の製品/技術が大好きな Microsoft MVP な管理人の技術ブログです。

XSitemaps - SEO のためのサイトマップファイルを作る

業務で (主に) EC サイトの実装 / 運営をしているのですが、EC サイトと言えば SEO!お客様が来ないことには商売にならないので、検索エンジンを上手に操って流入を確保することは非常に重要です。ということで、ページのクローリングを制御するために Google Search Console などを使うわけですが、そこで必要になるのがサイトマップファイルです。サイトマップファイルにはいくつか種類があるのですが、主に XML 形式が使われるのだと思います。ファイル仕様は sitemaps.org をご覧ください。

f:id:xin9le:20200112015442j:plain

サイトマップファイルを生成するライブラリは C# / .NET の世界にもいくつか転がっているのですが、どれも微妙に気が利いてなく、社内でもプロジェクト毎に独自に実装を持っていたりして自分的に全く気に入らなかったので、せっかくなのでと思って車輪の再発明をしました。それが今回ご紹介する XSitemaps です。.NET Standard 1.1 以上をサポートしているので、.NET Framework 4.5 でも利用できます。ただ XML ファイルを作るだけとあって幅広い。

主な機能

以下は主にサポートしている機能の一覧です。見る人が見ると案外痒い所に手が届くようになっている...と思います(たぶん。というのも、サイトマップファイルには以下のような地味に面倒な仕様 / 制限があります。

  • 1 ファイルに含められる URL は最大 50,000 件
  • 50 MB 以下

もしこの制限に引っ掛かったときはサイトマップファイルを適切に分割し、サイトマップインデックスファイルを作ってあげなければなりません。これを簡単に調整できないと困ってしまうわけです。XSitemaps はこの辺りの制約に対して、

  • サイトマップファイルを指定の URL 件数単位で分割
  • インデントの有無の調整
  • GZIP 形式でのファイル圧縮 (= 仕様で認められている)

を自然な形でサポートしているので、そこが推しポイントというか便利なところです。

使い方

サイトマップファイル (Sitemap.xml) は以下のような感じで作ります。Sitemap.Serialize()Stream に書き込むこともできますし、byte[] で返すこともできます。

// URL から Sitemap を作る
var modifiedAt = DateTimeOffset.Now;
var urls = new[]
{
    new SitemapUrl("https://blog.xin9le.net", modifiedAt, ChangeFrequency.Daily, priority: 1.0),
    new SitemapUrl("https://blog.xin9le.net/entry/rx-intro"),
    new SitemapUrl("https://blog.xin9le.net/entry/async-method-intro", frequency: ChangeFrequency.Weekly),
};
var sitemaps = Sitemap.Create(urls, maxUrlCount: 2);  // 2 件ごとに分割

// ファイル出力
for (var i = 0; i < sitemaps.Length; i++)
{
    var desktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
    var path = Path.Combine(desktop, $"Sitemap_{i}.xml");
    using (var stream = new FileStream(path, FileMode.CreateNew))
    {
        // 地味に気の利いたオプション
        var options = new SerializeOptions
        {
            EnableIndent = true,
            EnableGzipCompression = false,
        };
        sitemaps[i].Serialize(stream, options);
    }
}

// Sitemap_0.xml
/*
<?xml version="1.0" encoding="utf-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>https://blog.xin9le.net</loc>
    <lastmod>2020-01-12T00:07:12.2351485+09:00</lastmod>
    <changefreq>daily</changefreq>
    <priority>1</priority>
  </url>
  <url>
    <loc>https://blog.xin9le.net/entry/rx-intro</loc>
    <changefreq>never</changefreq>
    <priority>0.5</priority>
  </url>
</urlset>
*/

// Sitemap_1.xml
/*
<?xml version="1.0" encoding="utf-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>https://blog.xin9le.net/entry/async-method-intro</loc>
    <changefreq>weekly</changefreq>
    <priority>0.5</priority>
  </url>
</urlset>
*/

そして、サイトマップインデックスファイル (SitemapIndex.xml) は以下のような感じです。全然難しくない!

// 分割されたファイル情報から SitemapIndex を作る
var modifiedAt = DateTimeOffset.Now;
var info = new[]
{
    new SitemapInfo("https://example.com/Sitemap_0.xml", modifiedAt),
    new SitemapInfo("https://example.com/Sitemap_1.xml"),
};
var index = new SitemapIndex(info);

// ファイル出力
var desktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
var path = Path.Combine(desktop, $"SitemapIndex.xml");
using (var stream = new FileStream(path, FileMode.CreateNew))
{
    var options = new SerializeOptions
    {
        EnableIndent = true,
        EnableGzipCompression = false,
    };
    index.Serialize(stream, options);
}

/*
<?xml version="1.0" encoding="utf-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <sitemap>
    <loc>https://example.com/Sitemap_0.xml</loc>
    <lastmod>2020-01-12T00:13:24.4802279+09:00</lastmod>
  </sitemap>
  <sitemap>
    <loc>https://example.com/Sitemap_1.xml</loc>
  </sitemap>
</sitemapindex>
*/

まとめ

SEO はエンジニアからすると比較的縁遠いものかもしれませんが、流入を気にする Web サービスの運営においては重要なことなので、もしサイトマップファイルを作ることがあれば使ってみてください。