お試し 技術

WordPress RestAPIをさわってみる

今回はWordPress RestAPIを使って全投稿データをCSVに書き出すようにしてみます
動作環境は以下です

バージョン
OSWIn 11 Pro
C#.Net 8.0
WordPress6.5.2

アプリケーションパスワードを準備する

今回はアプリケーションパスワード認証でRestAPIを使用するため、以下のサイトが参考になります。以下のサイトはGAS(Google Apps Script)での実装する際に必要となる手順(サーバーのREST APIのアクセス制限を無効にする方法)がありますが今回は必要ありません。国内からのアクセスを想定しているためです

参考サイト
WordPress REST APIを有効化する方法※2022年版│Programming ZERO
WordPress REST APIを有効化する方法※2022年版│Programming ZERO

本記事ではWordPressの自動記事投稿や記事情報の自動取得を可能にする「WordPress REST API」を利用 ...

続きを読む

Getメソッド関数を実装する

対象URLに対してGetする箇所を関数かしておきます

private string _apiKey = @"前の項目で取得したアプリケーションパスワード(文字列の間にある空欄ありのままで)";
private string _userName = "前の項目でアプリケーションパスワードを設定したユーザー名";
private string _hostName = "WordPressのサイトURL"; // 本サイトの場合は「https://nasuton.net/blog」となる

/// <summary>
/// 対象URLに対してGetリクエストを送信する
/// </summary>
/// <param name="url">GETメソッドのURL</param>
/// <returns>レスポンス結果</returns>
private async Task<HttpResponseMessage> GetAPIAsync(string url)
{
    HttpResponseMessage response;

    using (var httpClient = new HttpClient())
    {
        using (var request = new HttpRequestMessage(new HttpMethod("GET"), url))
        {
            // Basic 認証のヘッダを追加
            var base64authorization = Convert.ToBase64String(Encoding.ASCII.GetBytes($"{_userName}:{_apiKey}"));
            request.Headers.TryAddWithoutValidation("Authorization", $"Basic {base64authorization}");

            response = await httpClient.SendAsync(request);
        }
    }
    return response;
}

タグ情報を取得する

まずはタグ情報を取得します。今回はId、タグのURL、タグの表示名を取得するようにしています。
また、初期値では1回のリクエストで10個ずつしか取得できないので、全部取得できるように繰り返しリクエストを投げています

/// <summary>
/// WordPressのタグ情報を格納するクラス
/// </summary>
public class WPTag_Response
{
    public WPTag_Response() { }

    [JsonPropertyName("id")]
    public int? Id { get; set; }

    [JsonPropertyName("link")]
    public string? Link { get; set; }

    [JsonPropertyName("name")]
    public string? Name { get; set; }
}

/// <summary>
/// 全てのタグを取得する
/// </summary>
/// <returns>取得した全てのタグ情報</returns>
public List<WPTag_Response> GetAllTags()
{
    var allTags = new List<WPTag_Response>();
    var url = $"{_hostName}/wp-json/wp/v2/tags";
    var response = GetAPIAsync(url).Result;
    // Headerから総ページ数を取得
    var wp_totalPages = int.Parse(response.Headers.GetValues("X-WP-TotalPages").First());
    allTags.AddRange(JsonSerializer.Deserialize<List<WPTag_Response>>(response.Content.ReadAsStringAsync().Result));

    // 2ページ目以降のデータを取得
    if(wp_totalPages > 1)
    {
        for (int i = 2; i < wp_totalPages + 1; i++)
        {
            url = $"{_hostName}/wp-json/wp/v2/tags" + $"?page={i}";
            response = GetAPIAsync(url).Result;
            allTags.AddRange(JsonSerializer.Deserialize<List<WPTag_Response>>(response.Content.ReadAsStringAsync().Result));
        }
    }

    return allTags;
}

カテゴリ情報を取得する

続いて、カテゴリ情報を取得します。こちらはId、カテゴリのURL、カテゴリの表示名を取得するようにしています。
こちらも先ほどのタグ同様に1回のリクエストで10個ずつしか取得できないので、全部取得できるように繰り返しリクエストを投げています

/// <summary>
/// WordPressのカテゴリ情報を格納するクラス
/// </summary>
public class WPCategory_Response
{
    public WPCategory_Response() { }

    [JsonPropertyName("id")]
    public int? Id { get; set; }

    [JsonPropertyName("link")]
    public string? Link { get; set; }

    [JsonPropertyName("name")]
    public string? Name { get; set; }
}

/// <summary>
/// 全てのカテゴリを取得する
/// </summary>
/// <returns>取得したすべてのカテゴリ情報</returns>
public List<WPCategory_Response> GetAllCategories()
{
    var allCategories = new List<WPCategory_Response>();
    var url = $"{_hostName}/wp-json/wp/v2/categories";
    var response = GetAPIAsync(url).Result;
    // Headerから総ページ数を取得
    var wp_totalPages = int.Parse(response.Headers.GetValues("X-WP-TotalPages").First());
    allCategories.AddRange(JsonSerializer.Deserialize<List<WPCategory_Response>>(response.Content.ReadAsStringAsync().Result));

    if (wp_totalPages > 1)
    {
        // 2ページ目以降のデータを取得
        for (int i = 2; i < wp_totalPages + 1; i++)
        {
            url = $"{_hostName}/wp-json/wp/v2/categories" + $"?page={i}";
            response = GetAPIAsync(url).Result;
            allCategories.AddRange(JsonSerializer.Deserialize<List<WPCategory_Response>>(response.Content.ReadAsStringAsync().Result));
        }
    }

    return allCategories;
}

投稿情報を取得する

今回は投稿情報(固定ページは含まない)だけを取得しています。こちらはId、投稿日時(公開日時?)、投稿の表示名、投稿のURL、カテゴリのId、タグのIdを取得するようにしています。

/// <summary>
/// WordPressの投稿データを格納するクラス
/// </summary>
public class WPPOST_Response
{
    public WPPOST_Response() { }

    [JsonPropertyName("id")]
    public int? Id { get; set; }

    [JsonPropertyName("date")]
    public string? Date { get; set; }

    [JsonPropertyName("title")]
    public WP_TitleRendered? rendered { get; set; }

    [JsonPropertyName("link")]
    public string? Link { get; set; }

    [JsonPropertyName("categories")]
    public List<int>? Categories { get; set; }

    [JsonPropertyName("tags")]
    public List<int>? Tags { get; set; }
}

/// <summary>
/// WordPressのタイトルを格納するクラス
/// </summary>
public class WP_TitleRendered
{
    public WP_TitleRendered() { }

    [JsonPropertyName("rendered")]
    public string? Title { get; set; }
}

/// <summary>
/// 全ての投稿を取得する
/// </summary>
/// <returns>取得した投稿データリスト</returns>
public List<WP_PostData> GetAllPosts()
{
    var postDatas = new List<WP_PostData>();
    var allPosts = new List<WPPOST_Response>();
    var allTags = GetAllTags();
    var allCategories = GetAllCategories();

    var url = $"{_hostName}/wp-json/wp/v2/posts";
    var response = GetAPIAsync(url).Result;
    // Headerから総ページ数を取得
    var wp_totalPages = int.Parse(response.Headers.GetValues("X-WP-TotalPages").First());
    allPosts.AddRange(JsonSerializer.Deserialize<List<WPPOST_Response>>(response.Content.ReadAsStringAsync().Result));

    if(wp_totalPages > 1)
    {
        // 2ページ目以降のデータを取得
        for (int i = 2; i < wp_totalPages + 1; i++)
        {
            url = $"{_hostName}/wp-json/wp/v2/posts" + $"?page={i}";
            response = GetAPIAsync(url).Result;
            allPosts.AddRange(JsonSerializer.Deserialize<List<WPPOST_Response>>(response.Content.ReadAsStringAsync().Result));
        }
    }

    foreach (var post in allPosts)
    {
        var postData = new WP_PostData
        {
            Id = post.Id,
            Date = DateTime.Parse(post.Date).ToString("yyyy/MM/dd HH:mm:ss"),
            Title = WebUtility.HtmlDecode(post.rendered.Title),    // HTMLエンコードされた文字列をデコード
            Link = post.Link,
            Categories = new List<string>(),
            Tags = new List<string>()
        };

        foreach (var categoryId in post.Categories)
        {
            var category = allCategories.Find(c => c.Id == categoryId);
            postData.Categories.Add(category.Name);
        }

        foreach (var tagId in post.Tags)
        {
            var tag = allTags.Find(t => t.Id == tagId);
            postData.Tags.Add(tag.Name);
        }

        postDatas.Add(postData);
    }

    return postDatas;
}

取得したデータの一部はそのままでは使えないのでタグとカテゴリをIdではなく表示名にし、投稿タイトルもHTMLエンコードしている可能性があるのでそれをデコードしています

CSVファイルに書き出す

これまでに取得したデータをCSVファイルとして実際に書き出します。タグとカテゴリは複数ある場合があるのでそれを「|」で区切っています

/// <summary>
/// CSVファイルにWordPressの投稿データを書き込む
/// </summary>
/// <param name="postDatas">投稿データリスト</param>
public void WP_PostDataCSV_Write(List<WP_PostData> postDatas)
{
    string csvPath = AppSetting.GetString("csvPath");
    using (var writer = new StreamWriter(csvPath, false, Encoding.UTF8))
    {
        // ヘッダーを書き出し
        writer.WriteLine("Id,Date,Title,Link,Categories,Tags");

        // データを書き出し
        foreach (var post in postDatas)
        {
            writer.WriteLine($"{post.Id},{post.Date},{post.Title},{post.Link},{string.Join("|", post.Categories)},{string.Join("|", post.Tags)}");
        }
    }
}

最後に

今回は投稿データとカテゴリ、タグの情報を取得するだけでしたがほかにも色々とできるようなので以下のドキュメント(英語で書かれています)を参考に実装してみてください

ドキュメント
REST API Handbook | Developer.WordPress.org
REST API Handbook | Developer.WordPress.org

The WordPress REST API provides an interface for application ...

続きを読む

また、今回作成したコードもGitHubにアップしていますので参考にしてみてください

サンプル
BlogSampleCodeProjects/WPRestAPI at main · nasuton/BlogSampleCodeProjects · GitHub
BlogSampleCodeProjects/WPRestAPI at main · nasuton/BlogSampleCodeProjects · GitHub

Project for sample code used in the blog.(Blogで記載しているサンプルコード ...

続きを読む

-お試し, 技術
-,