【FANZA】スプレッドシート+GASでデータベースを構築する

# はじめに
初めまして、東雲愛(@ai_shinonome)でございます。
普段はTokyoでビジネスパーソンをしております。

私はスキルがないのですが、スキルアップの近道はアウトプットだろうと。
とにかく出してみますか。
せっかくならFANZAと掛け合わせた個人学習がしたいなと思い、サンプル画像を一斉取得して愉しむことにしました。
サンプル画像っていいよね。

# サンプルジャーニー(準備編)
というわけで早速取得したいのですが、せっかくならシステム化してやろうとも思ったので、検証環境で取得しながらナレッジを身に着けていこうと思います。
おっと。ちょうど手元にGoogle Cloudがあるじゃないか。
サンプルジャーニーと準備を始めよう。
ちなみに、この記事では**サンプル画像を取得しません**ので、次回以降の記事にまとめたいと思います。
ということで、本日はただデータベースを作成するだけになりました。笑
まあね、初心者だからね。しょうがないね。


# まずはDMM様よりお赦しを得る
さて、旅には必ず準備がいる。
サンプル画像を愉しむにはDMM Webサービスを利用するのが至高。
こちらの「商品検索API」を利用してサンプル画像を軒並み刈り取る。

https://affiliate.dmm.com/api/v3/itemlist.html

ちなみにDMM Webサービスは事前に登録をして、自身の[api_id]と[affiliate_id]を利用する必要がある。
登録の流れやお作法は、以前noteに書いた記事を見てもらうとわかりやすい。

https://note.com/kanikama27/n/n48a7ae0d0ed5

そして忘れちゃいけない儀式がある。
DMM Webサービスを利用する場合は、必ずクレジットを記載する必要がある。

https://affiliate.dmm.com/api/credit.html

今宵もお世話になります。
<a href="https://affiliate.dmm.com/api/"><img src="https://p.dmm.co.jp/p/affiliate/web_service/r18_88_35.gif" width="88" height="35" alt="WEB SERVICE BY FANZA" /></a>
というわけで、DMM様よりお赦しを頂けたらはじめましょう。


# スプレッドシートに好きな女優をまとめる
まずはサンプル画像が欲しい女優をリストアップしましょう。
ToDoリストは楽しくないけど、女優さんのリストアップはとても楽しい。
せっかくなのでGoogleスプレッドシートにまとめます。まとめ方としてはこんな感じ。
| 女優ID | 女優名 | 作成日 | リクエストURL | 最後の取得日 |
|:-:|:-:|:-:|:-:|:-:|
| FANZA参照 | FANZA参照 | レコード追加日 | APIのお作法参照 | 後述 |

こんな感じでまとめます。まとめると、こんな感じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4071974/387d23f8-9d99-4bba-8edc-d556ab7c3dc1.png)
うーん、圧巻。

このリクエストURLですが、リファレンスの記載通りに構成すれば問題ないです。

https://affiliate.dmm.com/api/v3/itemlist.html

ここでは女優IDが必要になるのですが、それは本家のサイトで検索すれば出てきます。
アドレスバーに出ている女優IDをスプレッドシートに埋めていく感じですね。
女優IDを一括取得できる仕組みを作るのも面白いのだろうけど、それはまた今度にする。
なぜなら、サンプル画像を愉しむという目的が遠くなるから。

ちなみに、私が今回用意したURLはこんな感じ。
https://api.dmm.com/affiliate/v3/ItemList?api_id=XXXXXXXXXXXXXXXXXXXXXXX&affiliate_id=AAAAAAAAAAAAAAAAAAAAA&site=FANZA&service=digital&floor=videoa&hits=100&offset=1&sort=date&article[0]=genre&article[1]=actress&article_id[0]=4025&article_id[1]=女優ID&output=json
総集編は動画で愉しむ派なので、対象の女優さんが出演された単体作品のみで絞りました。

# Cloud SQLをデプロイ
ここでやっとGoogle CLoudが出てきます。
せっかくなので、Google Cloudが誇る「Cloud SQL」をデータベースとして利用します。
直感的でわかりやすいので、ささっとデプロイしていきましょう。

まずは「インスタンスの作成」で[MySQL]を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4071974/cd790108-e105-4efa-9edb-59b7fc56540b.png)

お財布と相談しながらインスタンスのスペックとリージョンを選定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4071974/2c93923e-2960-4d9f-aed0-f01e0f7eac2b.png)

はい、できた
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4071974/eac6858a-3153-4b64-bd61-cb8d71ebf9de.png)
キュ〇ピーのお料理教室みたいに事前に作成していたのでね。こんな感じでね。

あと、ユーザーとテーブルだけ作成しておいてください。
どちらもGoogle CLoudの管理コンソールからGUIで作成できます。
個人開発なのでGUI使えるものは使います。

# GASで流し込む
いよいよGoogleスプレッドシートに書き溜めた女優情報を、欲望を可視化したデータベースへの変化させます。
これだから、テクノロジーはやめられねぇ。

今回GASで用意したスクリプトは2つ。
1. 女優IDから女優ごとのリクエストURLを生成する
1. スプレッドシート更新後、作成したテーブルにレコードを追加する

つまりスプレッドシートはUIでありフロントエンドの役割を果たすわけです。
合理的でしょ。

## 女優IDから女優ごとのリクエストURLを生成する
じゃあまずはリクエストURLの生成から。
構文がきまっており、女優IDが変数となるだけなのでかなりシンプルです。

```baseurl.gs
function updateUrls() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("シート名"); // シート名を変更してください
  var range = sheet.getRange("A2:A" + sheet.getLastRow()); // A列のデータ範囲を指定

  var baseUrl = "https://api.dmm.com/affiliate/v3/ItemList?api_id=XXXXXXXXXXXXXXXXXXXXXXX&affiliate_id=AAAAAAAAAAAAAAAAAAAAA&site=FANZA&service=digital&floor=videoa&hits=100&offset=1&sort=date&article[0]=genre&article[1]=actress&article_id[0]=4025&article_id[1]=";

  range.getValues().forEach((row, index) => {
    var actressId = row[0]; // A列の値を取得
    var rowIndex = index + 2; // データ行に対応（ヘッダーを除外するため+2）

    if (actressId) { // A列に値が存在する場合
      var fullUrl = baseUrl + actressId + "&output=json";
      sheet.getRange(rowIndex, 4).setValue(fullUrl); // D列にURLを記載
    } else { // A列の値が空の場合
      sheet.getRange(rowIndex, 4).setValue(""); // D列のURLを削除
    }
  });
}

```
これにより、我々は女優IDのみ埋めれば勝手にスプレッドシートが更新されるようになりました。
これだけでもだいぶラクになったよね。
まぁまだ取得していないんですけども。

## スプレッドシート更新後、作成したテーブルにレコードを追加する
続いて、作成したデータベースへ自動的に反映させましょう。
スクリプトはこちら。

```syncdb.gs
function Gattai() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("にゃん♡");
  if (!sheet) {
    Logger.log("エラー:シート名を確認して♡");
    return;
  }

  var data = sheet.getDataRange().getValues(); // スプレッドシートの全データ取得

  // Cloud SQL接続情報
  var instanceConnectionName = "いーんーす♡"; // インスタンス接続名
  var dbUrl = "jdbc:google:mysql://" + instanceConnectionName + "/なーにー♡"; // Cloud SQL用の接続URL
  var username = "東雲♡愛";
  var password = "らぶちうにう♡";

  var conn;
  try {
    conn = Jdbc.getCloudSqlConnection(dbUrl, username, password);
    Logger.log("Cloud SQL接続成功♡");
  } catch (e) {
    Logger.log("うーん: " + e.message);
    return;
  }

  var stmt = conn.prepareStatement("INSERT INTO actresses (actress_id, actress_name, created_at, base_url, latest_release_date) VALUES (?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE actress_name=?, base_url=?, latest_release_date=?");

  for (var i = 1; i < data.length; i++) { // 1行目（ヘッダー）は無視
    try {
      stmt.setString(1, data[i][0]); // actress_id
      stmt.setString(2, data[i][1]); // actress_name
      
      // 修正: TIMESTAMP → 文字列フォーマットで管理
      var formattedTimestamp = Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "yyyy-MM-dd HH:mm:ss");
      stmt.setString(3, formattedTimestamp); // created_at をセット

      stmt.setString(4, data[i][3]); // base_url
      stmt.setString(5, Utilities.formatDate(new Date(data[i][4]), Session.getScriptTimeZone(), "yyyy-MM-dd")); // latest_release_date をセット

      stmt.setString(6, data[i][1]); // 更新時のactress_name
      stmt.setString(7, data[i][3]); // 更新時のbase_url
      stmt.setString(8, Utilities.formatDate(new Date(data[i][4]), Session.getScriptTimeZone(), "yyyy-MM-dd")); // 更新時のlatest_release_date

      stmt.execute();
    } catch (e) {
      Logger.log("うーん: " + e.message);
    }
  }

  stmt.close();
  conn.close();
  Logger.log("できた♡！");
}

```

といった形でスクリプトを作成します。
あとはスプレッドシート編集時に2つのスクリプトが実行できるよう、トリガーを準備すれば大丈夫です。

# いざ鎌倉
では実践。
まず、A列に乙アリスさんの女優IDを入れます。音速でリクエストURLが作成されました。
すかさず作成日も入力しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4071974/2cc6deec-94ec-40d5-b1e4-d21c011b2603.png)

そして、目にも留まらぬ速さでデータベースにも乙アリスがリストアップされました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4071974/5308c699-47e7-405d-a0f6-ece39a3ea3e1.png)

素晴らしい！これがプログラミングの力だ！

とはいえ、検証してみて改善の余地ありだな。
特にスプレッドシートは他のカラムも自動で入力された方がいい。
結果的に女優IDだけ入れればすべてが解決するってのが至高なのかもしれない。
まぁ、これはサンプル画像を愉しんでからでもいい気がする。
サンプルジャーニーってのは長いんだ。

# 本日の総括
というわけで、本日はGoogleスプレッドシートとGAS(Google Apps Script)を利用してデータベースを構築してみた。自分好みの、いいデータベースができたと思う。
ちなみにGASで紹介したスクリプトは生成AIに書いてもらった。
経験がなくてもスクリプトが書けるとは、いい世の中になったもんだ。
今後もいろいろと試していきたいと思う。

では、このへんで。ごきげんよう。