見出し画像

Go言語でニコニコ動画APIを叩いてみた

今回はGo言語でニコニコ動画のAPIを叩いて、出力まで行ってみたいと思います。
使用するAPIは以下になります。
https://site.nicovideo.jp/search-api-docs/snapshot

使用するリポジトリは以下になります。
https://github.com/seki19/go-niconico-api-call

今回は決め打ちで叩くURLを設定します。

https://api.search.nicovideo.jp/api/v2/snapshot/video/contents/search?q=初音ミク&targets=tagsExact&fields=contentId,title,viewCounter,startTime,thumbnailUrl,lengthSeconds&filters[categoryTags][0]=VOCALOID&_sort=-viewCounter&_offset=0&_limit=3&_context=apitest

上記のURLをpostmanやブラウザで叩くと以下のようなjsonが帰ってきます。

{
   "data": [
       {
           "startTime": "2011-09-17T19:00:28+09:00",
           "lengthSeconds": 244,
           "viewCounter": 14660500,
           "contentId": "sm15630734",
           "title": "『初音ミク』千本桜『オリジナル曲PV』",
           "thumbnailUrl": "https://nicovideo.cdn.nimg.jp/thumbnails/15630734/15630734.34480305"
       },
       {
           "startTime": "2010-08-19T22:25:45+09:00",
           "lengthSeconds": 200,
           "viewCounter": 12776301,
           "contentId": "sm11809611",
           "title": "【オリジナル曲PV】マトリョシカ【初音ミク・GUMI】",
           "thumbnailUrl": "https://nicovideo.cdn.nimg.jp/thumbnails/11809611/11809611"
       },
       {
           "startTime": "2010-05-18T10:46:14+09:00",
           "lengthSeconds": 217,
           "viewCounter": 12164686,
           "contentId": "sm10759623",
           "title": "初音ミク・巡音ルカ オリジナル曲 「ワールズエンド・ダンスホール」",
           "thumbnailUrl": "https://nicovideo.cdn.nimg.jp/thumbnails/10759623/10759623"
       }
   ],
   "meta": {
       "id": "8b9d42cf-b3e8-47a2-9722-cc92e60fc0c2",
       "totalCount": 153284,
       "status": 200
   }
}

以上のAPIをGoから叩いてみます。

ソースコード

package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"time"
)

type MusicData struct {
	StartTime     time.Time `json:"startTime"`
	LengthSeconds int       `json:"lengthSeconds"`
	ViewCounter   int       `json:"viewCounter"`
	ContentID     string    `json:"contentId"`
	Title         string    `json:"title"`
	ThumbnailURL  string    `json:"thumbnailUrl"`
}

type Response struct {
	Data []MusicData `json:"data"`
	Meta struct {
		ID         string `json:"id"`
		TotalCount int    `json:"totalCount"`
		Status     int    `json:"status"`
	} `json:"meta"`
}

func main() {
	resp, err := http.Get("https://api.search.nicovideo.jp/api/v2/snapshot/video/contents/search?q=" + url.QueryEscape("初音ミク") + "&targets=tagsExact&fields=contentId,title,viewCounter,startTime,thumbnailUrl,lengthSeconds&filters[categoryTags][0]=VOCALOID&_sort=-viewCounter&_offset=0&_limit=3&_context=apitest")

	if err != nil {
		log.Fatal(err)
	}

	// The client must close the response body when finished with it:
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatal(err)
	}

	var data Response

	if err := json.Unmarshal(body, &data); err != nil {
		log.Fatal(err)
	}

	for _, music := range data.Data {
		fmt.Println(music)
	}
}

型定義

type MusicData struct {
	StartTime     time.Time `json:"startTime"`
	LengthSeconds int       `json:"lengthSeconds"`
	ViewCounter   int       `json:"viewCounter"`
	ContentID     string    `json:"contentId"`
	Title         string    `json:"title"`
	ThumbnailURL  string    `json:"thumbnailUrl"`
}

type Response struct {
	Data []MusicData `json:"data"`
	Meta struct {
		ID         string `json:"id"`
		TotalCount int    `json:"totalCount"`
		Status     int    `json:"status"`
	} `json:"meta"`
}

APIのレスポンスをデコードする際に必要になるため、型を定義します。
APIのレスポンスから型を定義する際、以下のサイトがとても便利です。
https://mholt.github.io/json-to-go/

メイン処理

APIを叩く。

resp, err := http.Get("https://api.search.nicovideo.jp/api/v2/snapshot/video/contents/search?q=" + url.QueryEscape("初音ミク") + "&targets=tagsExact&fields=contentId,title,viewCounter,startTime,thumbnailUrl,lengthSeconds&filters[categoryTags][0]=VOCALOID&_sort=-viewCounter&_offset=0&_limit=3&_context=apitest")

[]byte型でレスポンスのBodyを取得する

body, err := ioutil.ReadAll(resp.Body)
if err != nil {
	log.Fatal(err)
}

jsonデコードを行う
Unmarshal関数については以下のサイトを参照
https://blog.golang.org/json

if err := json.Unmarshal(body, &data); err != nil {
	log.Fatal(err)
}

上で定義した型に定義されていない値は無視されます。
例えばですが、以下のようにMusicDataをTitleのみにしたとき、タイトルのみ取得できるようになります。

type MusicData struct {
	Title         string    `json:"title"`
}

main.goを実行すると以下が表示されると思います。(実行時によって内容が異なることがあります。)

{2011-09-17 19:00:28 +0900 +0900 244 14676244 sm15630734 『初音ミク』千本桜『オリジナル曲PV』 https://nicovideo.cdn.nimg.jp/thumbnails/15630734/15630734.34480305}
{2010-08-19 22:25:45 +0900 +0900 200 12790082 sm11809611 【オリジナル曲PV】マトリョシカ【初音ミク・GUMI】 https://nicovideo.cdn.nimg.jp/thumbnails/11809611/11809611}
{2010-05-18 10:46:14 +0900 +0900 217 12201469 sm10759623 初音ミク・巡音ルカ オリジナル曲 「ワールズエンド・ダンスホール」 https://nicovideo.cdn.nimg.jp/thumbnails/10759623/10759623}


所感

型を定義するって、楽しいいんだなぁ・・・(PHPer並の感想)

過去にニコニコ動画APIを使用して、ランダムにボカロ楽曲を表示するサイトを作りました。
https://vodd.site

よろしくお願いします。🙇‍♂️


この記事が気に入ったらサポートをしてみませんか?