LoginSignup
2
1

More than 3 years have passed since last update.

D言語でQiita API

Posted at

はじめに

D言語でのQiita APIの使用例を示したいと思います。
Qiita APIや他のAPIを利用する際にも必要になる、libcurlJSON処理の参考になればと思います。

今回使った Qiita API

GET /api/v2/itemsを使用しました。
Qiita API v2ドキュメントより、抜粋します。

GET /api/v2/items
記事の一覧を作成日時の降順で返します。

page
    ページ番号 (1から100まで)
    Example: 1
    Type: string
    Pattern: /^[0-9]+$/
per_page
    1ページあたりに含まれる要素数 (1から100まで)
    Example: 20
    Type: string
    Pattern: /^[0-9]+$/
query
    検索クエリ
    Example: "qiita user:Qiita"
    Type: string

APIから得られるJSONの戻り値は、以下のイメージです。

[
    {
        "rendered_body":"",
        "body":"",
        "coediting":"",
        "comments_count":"",
        "created_at":"",
        "group":"",
        "id":"",
        "likes_count":"",
        "private":"",
        "reactions_count":"",
        "tags":[{"name":"", "versions":[]}]
        "title":"",
        "updated_at":"",
        "url":"",
        "user":
        {
            "description":""
            "facebook_id":""
            "followees_count":
            "followers_count":
            "github_login_name":""
            "id":""
            "items_count":
            "linkedin_id":""
            "location":""
            "name":""
            "organization":""
            "permanent_id":""
            "profile_image_url":""
            "team_only":
            "twitter_screen_name":""
            "website_url":""
        },
        "page_views_count":""
    }
]

事前準備(JSON処理の補足説明)

JSON形式をパターン分けて、実装例を書いてみました。
これらのパターンを組み合わせれば、いろんなJSON形式を処理できます。

json1.d
import std.json;
import std.stdio;

void main()
{
    string s = `{ "name" : "black", "value" : 0 }`;
    JSONValue j = parseJSON(s);
    writeln(s);
    writeln(j["name"].type);    // string
    writeln(j["name"]);         // "black"
    writeln(j["value"].type);   // integer
    writeln(j["value"]);        // 0
    writeln();

    s = `{ "key1" : { "key2" : "value" } }`;
    j = parseJSON(s);
    writeln(s);
    writeln(j["key1"].type);    // object
    writeln(j["key1"]["key2"]); // "value"
    writeln();

    s = `[ { "key" : "value1" }, { "key" : "value2" } ]`;
    j = parseJSON(s);
    writeln(s);
    writeln(j.type);            // array
    JSONValue[] jarr = j.array();
    foreach ( jv ; jarr ){
        writeln(jv["key"]);     // "value1" "value2"
    }
    writeln();

    s = `
    {
        "royalblue" : "#4169e1",
        "darkgreen" : "#006400",
        "deeppink"  : "#ff1493"
    }`;
    j = parseJSON(s);
    writeln(s);
    writeln(j.type);            // object
    foreach ( string key, value; j ){
        writefln("%-9s : %s", key, value);  // not sorted
    }
}
実行結果
D:\Dev>dmd -m64 json1.d

D:\Dev>json1
{ "name" : "black", "value" : 0 }
string
"black"
integer
0

{ "key1" : { "key2" : "value" } }
object
"value"

[ { "key" : "value1" }, { "key" : "value2" } ]
array
"value1"
"value2"


        {
                "royalblue" : "#4169e1",
                "darkgreen" : "#006400",
                "deeppink"  : "#ff1493"
        }
object
darkgreen : "#006400"
royalblue : "#4169e1"
deeppink  : "#ff1493"

1つ目のパターンは、項目名("name"や"value")を指定して、値("black"や0)を得る、基本パターンです。
parseJSONを使うことで、JSONの解析結果がJSONValueに格納されます。
.typeを使えば、値の型を得ることができます。
実装例では、stringintegerobjectarrayが得られています。

2つ目のパターンは、階層構造(.typeobject)になっている場合に値を得る例です。
j["key1"]["key2"]という風に項目を指定することができます。

3つ目のパターンは、配列構造(.typearray)になっている場合に値を得る例です。
実装例では、JSONValue[] jarr = j.array()を使って、ループで値を得ています。

4つめのパターンは、仮に項目名がわからなくても、ループ処理foreach ( string key, value; j )で項目名、値を得られることを示しています。

ソースコード

qiitaapi.d
import std.conv;
import std.json;
import std.net.curl;
import std.stdio;
import std.uri;

void main()
{
    listQiitaItems(getQiitaItems("tag:dlang", 5));
    listQiitaItems(getQiitaItems("tag:D言語", 5));
}

JSONValue[] getQiitaItems(string option, int maxpage)
{
    writeln(option);
    if ( option != "" ){
        option = "query=" ~ option.encodeComponent ~ "&";
    }
    string sUrl = "https://qiita.com/api/v2/items?" ~ option ~ "per_page=100&page=";
    writeln(sUrl);
    auto http = HTTP();
    JSONValue[] jarr;
    for ( int i = 1; i <= maxpage; i++ ){
        JSONValue[] j = parseJSON(cast(string)get(sUrl ~ i.to!string, http)).array;
        if ( j.length == 0 ){
            break;
        }
        jarr ~= j;
    }
    return ( jarr );
}

void listQiitaItems(JSONValue[] jarr)
{
    foreach ( i, j; jarr ){
        writefln("No.%3d", i + 1);
        writefln("title  : %s", j["title"]);
        writefln("user-id: %s", j["user"]["id"]);
        write(   "tags   : ");
        foreach ( j1; j["tags"].array ){
            writef("%s ", j1["name"]);
        }
        writeln();
        writefln("LGTM   : %s", j["likes_count"]);
        writefln("comment: %s", j["comments_count"]);
        writeln();
    }
}

getQiitaItems

getQiitaItems関数で、libcurlを使用しています。
libcurl get関数
QiitaAPIでの利用制限を考慮して、maxpage5に指定しています。

利用制限
認証している状態ではユーザごとに1時間に1000回まで、認証していない状態ではIPアドレスごとに1時間に60回までリクエストを受け付けます。

検索結果はAPIの呼び出し1回ごとに最大100件です。100件を超える場合を想定してループ処理になっています。

実行結果

実行結果
D:\Dev>dmd -m64 qiitaapi.d
D:\Dev>qiitaapi > res.txt
res.txt
tag:dlang
https://qiita.com/api/v2/items?query=tag%3Adlang&per_page=100&page=
No.  1
title  : "Window10にWSL2+Ubuntuを導入し、GDC、DMD、LDCを使ってみた"
user-id: "devmynote"
tags   : "dlang" "D言語" "Windows10" "WSL2" 
LGTM   : 1
comment: 0

No.  2
title  : "D言語で迷路を再現(ドルアーガの塔)"
user-id: "devmynote"
tags   : "dlang" "D言語" "クロージャ" "乱数" "迷路" 
LGTM   : 1
comment: 0

No.  3
title  : "dub v1.23.0のx86_omfについて"
user-id: "mono_shoo"
tags   : "dlang" 
LGTM   : 5
comment: 0

・・・ 省略 ・・・

No.399
title  : "template for getting a field name of class or struct"
user-id: "repeatedly"
tags   : "Dlanguage" "dlang" 
LGTM   : 1
comment: 0

tag:D言語
https://qiita.com/api/v2/items?query=tag%3AD%E8%A8%80%E8%AA%9E&per_page=100&page=
No.  1
title  : "Window10にWSL2+Ubuntuを導入し、GDC、DMD、LDCを使ってみた"
user-id: "devmynote"
tags   : "dlang" "D言語" "Windows10" "WSL2" 
LGTM   : 1
comment: 0

・・・ 省略 ・・・

No. 99
title  : "D言語のビルドツール DUB"
user-id: "kazoo04"
tags   : "D言語" 
LGTM   : 20
comment: 0

この記事を投稿する前の実行結果となります。
この記事がtag:dlangで400番目の、tag:D言語で100番目の記事になる予定です。
キリ番ゲットしちゃいました。:wink:

参考情報

Qiita API v2ドキュメント
std.net.curl 使用例
std.json 使用例

D言語 Library Reference

std.net.curl(英語)
std.json(英語)

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1