はてなブックマークの人気エントリーを C# の Azure Functions で取得する

# はじめに

本稿は、はてなブックマークの人気エントリーを Azure Functions で取得する方法の紹介です。
言語は C# です。

# はてなブックマークのRSS

はてなブックマークの人気エントリーと新着エントリーを取得する方法としてRSSがあります。
今回は、ITエンジニア向けの情報を取得したいので「テクノロジー」というカテゴリを対象にします。
人気エントリーは以下です。
http://b.hatena.ne.jp/hotentry/it.rss
新着エントリーは以下です。
http://b.hatena.ne.jp/entrylist/it.rss

その他のカテゴリのRSSについては以下の記事を参照ください。

https://sprint-life.hatenablog.com/entry/2014/01/15/203535

はてなブックマークのRSSは、RSS 1.0 です。
中身を見ていくと、item という要素ごとに、ブックマークされたページの詳細なデータが入っています。
今回、利用するデータは、下図の赤枠部分とします。
それぞれの値は、おそらく以下の意味であると解釈しました(公式な説明が見つからず)。
title：対象ページのタイトル
link：対象ページのURL
description：対象ページの本文の冒頭の150～200文字くらい
dete：ブックマークが登録された日時(たぶん)
bookmarkcount：ブックマーク数
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403606/c9a3ad0a-0cf7-da1c-65fc-7c991789e568.png)

# C# での RSS 1.0 の取得方法

.NET では Atom 1.0 と RSS 2.0 なら [SyndicationFeed クラス](https://learn.microsoft.com/ja-jp/dotnet/api/system.servicemodel.syndication.syndicationfeed?view=dotnet-plat-ext-6.0&viewFallbackFrom=net-6.0)で簡単に取得できます。

しかし、RSS 1.0 を取得するには、少し手間がかかります。
C# で RSS 1.0 を取得したいというニーズが少ないせいか、日本語で解説してくれる記事は少ないですが、以下の2つの記事で詳しく解説してくれていました(感謝)。

https://atmarkit.itmedia.co.jp/fdotnet/easyxml/easyxml05/easyxml05_03.html

https://csharp.keicode.com/topics/xml-selectnodes-namespace.php

今回は、上記の実装方法を用いて、はてなブックマークのテクノロジーの人気エントリーを取得するソースコードを書きます。

まず、事前準備として RSS の中の Item 要素ごとのデータを格納するためのクラスとして、FeedItemクラスを定義します。

```c#
internal class FeedItem
{
    public string Title { get; set; } 
    public string Link { get; set; }
    public string Description { get; set; }
    public DateTime Date { get; set; }
    public int BookmarkCount { get; set; }
}
```

そして RSS から取得したデータを、FeedItemクラスに格納して返すメソッドを、以下のように書きます。

```c#
// 引数のurlに、RSSのURLが入ってくる想定
private static IEnumerable<FeedItem> ReadRSS(string url)
{
    // RSSのデータをXmlDocumentクラスを用いて読み込む
    var xml = new XmlDocument();
    xml.Load(url);

    // RSS 1.0 の要素を取得するための事前準備
    var nsmgr = new XmlNamespaceManager(xml.NameTable);
    nsmgr.AddNamespace("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
    nsmgr.AddNamespace("rss", "http://purl.org/rss/1.0/");
    nsmgr.AddNamespace("dc", "http://purl.org/dc/elements/1.1/");
    nsmgr.AddNamespace("hatena", "http://www.hatena.ne.jp/info/xmlns#");

    // item要素を格納するためにFeedItemクラスのリストを作成
    var items = new List<FeedItem>();

    // すべてのitem要素を取得する
    foreach (XmlElement node in xml.SelectNodes("/rdf:RDF/rss:item", nsmgr))
    {
        // titleやlinkなどの値を取得する
        var title = node.SelectNodes("rss:title", nsmgr)[0].InnerText;
        var link = node.SelectNodes("rss:link", nsmgr)[0].InnerText;
        var description = node.SelectNodes("rss:description", nsmgr)[0].InnerText;
        var date = DateTime.Parse(node.SelectNodes("dc:date", nsmgr)[0].InnerText);
        var bookmarkCount = int.Parse(node.SelectNodes("hatena:bookmarkcount", nsmgr)[0].InnerText);

        // 取得した値をもとにFeedItemを作成してリストに追加
        items.Add(new FeedItem()
            {
                Title = title,
                Link = link,
                Description = description,
                Date = date,
                BookmarkCount = bookmarkCount
            });
    }

    // FeedItemのリストを返す
    return items;
}

```
上記のコードを実行すれば、はてなブックマークの人気エントリーをFeedItemクラスのリストに格納することができます。

# Azure Functions で Web API として返す

Azure Functions の Web API の作成方法は、Visial Studio で新しいプロジェクトを作成する下図の画面で、Azure Functions を選択してプロジェクトを作成するだけです。
トリガーの種類は「httpトリガー」を選びます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403606/ccbe6d83-5d69-1370-b02c-23f541769a0d.png" width=75%>

詳細は、以下の公式ページを参照ください。

https://learn.microsoft.com/ja-jp/azure/azure-functions/functions-create-your-first-function-visual-studio?tabs=in-process

プロジェクトを作成した時点で、Web API として機能するための雛形のメソッドは作成されています。
あとは、そのメソッドの中身を、書き換えるだけです。
さきほど紹介した ReadRSS メソッドを呼び出した後に、json形式に変換して返すメソッドを以下に書きます。

```c#
[FunctionName("hatenarss")]
public static async Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
    ILogger log)
{
    // はてなブックマークのテクノロジーの人気エントリーのRSSのURL
    string url = @"https://b.hatena.ne.jp/hotentry/it.rss";

    // RSSから、IEnumerable<FeedItem> 型のリストを取得する
    var feedItems = ReadRSS(url);

    // IEnumerable<FeedItem> を json形式に変換して返す
    string jsonResult = JsonConvert.SerializeObject(feedItems);
    return new OkObjectResult(jsonResult);
}
```

上記の Azure Functions の Web API を実行すると、以下のようなJSON形式でデータが取得できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403606/64ad75c0-7a1a-1e86-0d6b-1defc3d9ed24.png)

# まとめ

はてなブックマークの人気エントリーを C# を用いた Azure Functions の Web API で JSON 形式で取得する方法の紹介しました。

ちなみに私は、エンジニアリングマネージャーとして「ハピネスチームビルディング」と名付けたチームの皆で主体的に楽しく成長する活動を実施しています。
ITエンジニア向け情報誌「Software Design」で連載している内容を以下で公開していますので、よろしければ、そちらも参照ください。

https://note.com/kojimadev/n/nbe692f9b3cec

Twitterでも開発に役立つ情報を発信しています → [@kojimadev](https://twitter.com/kojimadev)