YouTubeAPIを叩く（51件以降のデータを取得する）

# 0.今回の依頼内容
前回の続きです！ [YouTubeAPIを叩く](https://qiita.com/DoNotPrayDebug/items/733164c3498654c79066)

**【今回の仕様】
キーワード検索で、数か月で登録者1000人突破したチャンネルを抽出**

実際に動かしたのものが、こちら。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr"><a href="https://twitter.com/hashtag/YouTube?src=hash&amp;ref_src=twsrc%5Etfw">#YouTube</a> で1000人登録って大変<br><br>サンプルは<br>・検索ワード「<a href="https://twitter.com/hashtag/%E3%83%81%E3%82%A7%E3%83%B3%E3%82%BD%E3%83%BC%E3%83%9E%E3%83%B3?src=hash&amp;ref_src=twsrc%5Etfw">#チェンソーマン</a>」<br>・チャンネル開設から6か月以内で1000人突破<br>・昨日までに何らかの投稿をした<br>・日本のチャンネル<br><br>75チャンネルあって9チャンネルが条件に合う…と<br>こう見ると、やっぱ狭き門なのね<br><br>API使ったんで、また解説記事かきます <a href="https://t.co/rZDsiEneO3">pic.twitter.com/rZDsiEneO3</a></p>&mdash; 【現役PG】Don&#39;t Pray Debug（プレイさん） (@DebugDon) <a href="https://twitter.com/DebugDon/status/1596644972123537408?ref_src=twsrc%5Etfw">November 26, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

この依頼内容からAPIの仕様も加味して以下の処理内容で実装しました。
1. Searchを使ってチャンネル検索
    * 期限（指定しないと、チャンネルの詳細検索ができないため）
    * チャンネル開設日の抽出（プログラミングで対応）
   
1. Channelsを使ってチャンネルの詳細を調べる（チャンネルIDで検索）
    * 登録者数が1000突破してる（プログラミングで対応）
    * チャンネル開設場所が日本（プログラミングで対応）
    
では、順番に解説していきます！

# 1.日付作成
YouTubeAPIの日付はフォーマットが決まっているので
フォーマットに合わせた日付を作ります。
```.js
//※GASのコードです
const day = new Date();
//今日の日付
TODAY = Utilities.formatDate(day,"JST","yyyy-MM-dd'T'HH:mm:ss'Z'");

let setChannelDay = day;
//MONTHか月前
setChannelDay.setMonth(setChannelDay.getMonth() - MONTH);
CHANNELDAY = Utilities.formatDate(setChannelDay,"JST","yyyy-MM-dd'T'HH:mm:ss'Z'");

let setBeforeDay = day;
//DAY日前
setBeforeDay.setDate(setBeforeDay.getDay() - DAY); 
BEFOREDAY = Utilities.formatDate(setBeforeDay,"JST","yyyy-MM-dd'T'HH:mm:ss'Z'");
```

# 2.Searchを叩く（51件以上 検索したい）
今回のメイン解説
YouTubeAPIの仕様では1リクエスト50件がMAXです。
なので51件以降のデータをゲットするのは、ちょっとコツがいります。

```.js
function APISearch(){
    //API側の仕様
    let URL = "https://www.googleapis.com/youtube/v3/search";
    URL += "?part=snippet";
    //50件（MAX値）
    URL += "&maxResults=" + LIMIT;
    URL += "&order=date";
    //対象期間
    URL += "&publishedBefor=" + BEFOREDAY;
    URL += "&publishedAfter=" + TODAY;
    //キーワード指定
    URL += "&q=" + WORD;
    
    /*
    //両方のワードを含む
    const WORD = "犬 ネコ";
    
    //どちらかのワードを含む
    const WORD = "魔王 OR 天使";
    */
    
    //チャンネルを対象
    URL += "&type=channel";
    
    //2回目以降の処理(51以降を検索する)
    if(pageToken != ""){
        URL += "&pageToken=" + pageToken;
    }
    
    URL += "&key=" + APIKEY;
    
    const response = UrlFetchApp.fetch(URL);
    const json = JSON.parse(response);

    /*抽出の判定式*/
    
    //51件以上ある場合
    if(json.nextPageToken){
        //次のトークン入れ込み
        pageToken = json.nextPageToken;
        //もう一回Searchを叩く
        APISearch();
    }
}
```
これで51件以上あっても条件に合うすべてのデータを取得することができます。
# 3.抽出条件とChannels前処理
Channelsも同様に1リクエスト50件がマックスなので
そちらの対応をしたコードが、こちらです
```.js
function APISearch(){
    /*API叩くとこまで*/
  
    //該当データがない
    if(!json.items || json.items.length == 0){
        //APIChannels呼び出し処理
        CallChannels();
        return;
    }
  
    for(let i=0; i<json.items.length; i++){
        //フォーマットを指定して日付を作成
        const At = Utilities.formatDate(new Date(json.items[i].snippet.publishedAt),"JST","yyyy-MM-dd'T'HH:mm:ss'Z'");
  
        if(At > CHANNELDAY){
            //データ入れ込み
            idList.push(json.items[i].snippet.channelId);
        }
    }
  
    if(json.nextPageToken){
        /*もう一回Searchを叩く*/
    }else{
        //APIChannels呼び出し処理
        CallChannels();
        return;
    }
}
```

```.js
//APIChannels呼び出し処理
function CallChannels(){
    if(idList.length == 0){
      console.log("処理終了");
      return;
    }else{
      if(idList.length <= 50){
        //そのままjoinしてAPIを叩く
        APIChannels(idList.join(","));
      }else{
        //配列から50件を抜き出す
        let setIdList = idList.splice(0,50);
        //MAX50件でチャンネル検索
        APIChannels(setIdList.join(","));
  
        //もう一回呼び出す
        CallChannels();
      }
    }
}
```

# 4.条件に合うチャンネルデータの取得
ココは前回、やったとこなのでサラッといきます
```.js
function APIChannels(id){
    let URL = "https://www.googleapis.com/youtube/v3/channels";
    URL += "?part=snippet,statistics";
    URL += "&maxResults=" + LIMIT;
    URL += "&id="+id;
    URL += "&key="+ APIKEY;
    
    const response = UrlFetchApp.fetch(URL);
    const json = JSON.parse(response);
  
    //書き出し対象データ
    let writeData = [];
    let channelIdList = id.split(",");
  
    for(let i=0; i<json.items.length; i++){
      if(json.items[i].statistics.subscriberCount >= SUBSCRIVER && json.items[i].snippet.country == "JP"){
        
        //必要なデータ類(チャンネル名チャンネル作製日,登録者数)
        let channelData = [];
        channelData.push(json.items[i].snippet.title);
        channelData.push(channelIdList[i]);
        let at = json.items[i].snippet.publishedAt;
        at = at.substring(0,at.indexOf("T"));
        channelData.push(at);
  
        channelData.push(json.items[i].statistics.subscriberCount);
  
        //書き出し用配列に叩き込む
        writeData.push(channelData);
      }
    }
  
    if(writeData.length > 0){
      console.log("シートに書き込みます");
      /*スプレッドシートに書き出し*/
    }
  }
```
以上！
質問、依頼等がありましたらTwitterにてお話、聞きます。
[Twitter: Don't Pray Debug](https://twitter.com/DebugDon)