🦆

DuckDB で Web API を叩いて JSON をパースする話

2024/12/13に公開

前座

今日は12月13日の金曜日です。

そう、13日の金曜日。。。

だから、ジェイソン。。。 JSON に関する話をします!ウォー!

とはいえ、JSON で一本記事を書くのは難しかったので、DuckDB で JSON を触ってみた話(後編)をします。[1]

本題

今回は何をするの?

DuckDB でスクレイピングをします!

具体的には、WebAPI に対して、DuckDB からリクエストをして、その JSON 形式のレスポンスをテーブル化します!

実践の前の準備: 2 つ

(1)対象の Web API の説明

今回、Zenn の API を対象にします!
具体的なエンドポイントや仕様は公開されていないですが、Zenn をブラウザの開発者ツールで見られる範囲の API を叩いて検証します!

今回の対象のエンドポイントとしては、以下です。

自分(mackey0225)の記事を取得する
https://zenn.dev/api/articles?username=mackey0225

結果のイメージは以下です。

{
  "articles": [
    {
      "id": 339991,
      "post_type": "Article",
      "title": "Amazon Lightsail Containers は ARM アーキテクチャーとしてビルドしたコンテナイメージでは動かん!",
      "slug": "mackey0225-lightsail-containers-no-arm-support",
      "comments_count": 0,
      "liked_count": 1,
      "bookmarked_count": 0,
      "body_letters_count": 2748,
      "article_type": "tech",
      "emoji": "🤯",
      "is_suspending_private": false,
      "published_at": "2024-12-07T00:00:01.790+09:00",
      "body_updated_at": "2024-12-04T11:25:52.215+09:00",
      "source_repo_updated_at": "2024-12-04T11:25:52.207+09:00",
      "pinned": false,
      "path": "/babyjob/articles/mackey0225-lightsail-containers-no-arm-support",
      "user": {
        "id": 99469,
        "username": "mackey0225",
        "name": "mackey0225",
        "avatar_small_url": "https://res.cloudinary.com/zenn/image/fetch/s--1GExIj8D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/ad539edbaa.jpeg"
      },
      "publication": {
        "id": 122,
        "name": "babyjob",
        "display_name": "BABY JOB  テックブログ",
        "avatar_small_url": "https://res.cloudinary.com/zenn/image/fetch/s--5Rx15dd7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_80/https://storage.googleapis.com/zenn-user-upload/avatar/3a89844d01.jpeg",
        "avatar_url": "https://storage.googleapis.com/zenn-user-upload/avatar/3a89844d01.jpeg",
        "pro": false,
        "avatar_registered": true
      }
    },
    ...略...
    {
      "id": 333796,
      "post_type": "Article",
      ...略...
    }
  ],
  "next_page": 2
}

ポイントとしては、記事情報のリスト articles と次頁情報 next_page が並んでおり、必要な記事情報がネストしている点です。
この点については、あとでも説明しますが、DuckDB で読み込むときに一手間が必要になります。

(2)DuckDB でスクレイピングする方法

DuckDB で、先に説明したエンドポイントから情報を見る方法はシンプルです。

それは、FROM 句に read_json 関数を呼び、引数に URL を書くだけです!
はい、それだけです。

サンプルとしては、以下です。

SELECT * FROM read_json('https://zenn.dev/api/articles?username=mackey0225');

SQL 実行結果SQL 実行結果

結果は少し荒いですが、 本当に簡単です。
とくに、クライアントの設定や Cookie など意識せずにリクエストを投げられるものであれば、このような形で実行できます。

上の例では、SELECT 文にしていますが、テーブルに突っ込んで、様々なクエリで分析することができます。

いざ、実践!!

DuckDB を立ち上げて、以下の SQL を実行します!

SELECT 
    article.* 
FROM (
    SELECT 
        unnest(articles) as article 
    FROM 
        read_json_auto(
            'https://zenn.dev/api/articles?username=mackey0225', 
            ignore_errors=true
        )
);

上記のクエリを実行するとー、、、

SQL 実行結果SQL 実行結果

記事の一覧が表示できましたねー。

SQL の説明

本記事の前編にあたるDuckDB で 入れ子になっている JSON を UNNEST する話で紹介している unnest を使って、記事情報の配列を UNNEST して展開しています。
また、JSON を取得する関数を read_json_auto にすることで、スキーマ定義が不要になります。(非常に簡単!)

まとめ

今回、DuckDB で JSON 形式のレスポンスがある Web API に対して、スクレイピングする方法を簡単に紹介させていただきました。
個人的にも DuckDB は面白く、今回のような簡単にテーブルにしたり、SQL ライクなクエリでデータ分析したりするのが簡単にできます。

自分としてはまだまだ使いこなせていないので、また面白く便利な機能があれば、まとめていきたいです。[2]

脚注
  1. 前座は前編と全く同じです。 ↩︎

  2. 今月も他にAWS CloudShell に DuckDB を入れて、ALB のログを見てみたという記事も公開しているので、興味があれば見てもらえると嬉しいです。 ↩︎

BABY JOB  テックブログ

Discussion