20
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

株式会社Works Human IntelligenceAdvent Calendar 2021

Day 22

Google Spread SheetのデータをMySQLにインポートしてみる

Last updated at Posted at 2021-12-21

#はじめに
みなさん、はじめまして
人生で始めてQiita書きます、お手柔らかにお願いします

私は現在テクニカルサービス部門の開発グループにいます
とは言っても、最近なかなかコーディングをする機会が減っており、そんな折アドベントカレンダーを書いてはいかが?というお話をいただいたので、チャレンジしてみようかなと思いました

弊社では業務の中で Google Spread Sheet を利用しており、実際 Google Spread Sheet や Google Apps Script 関連記事が投稿されていたりします

今回は、そんなみんな大好きGoogle Spread Sheetのデータを、DBに格納してみようと思います

#主な流れ

  1. Google APIの有効化
  • サンプルデータ、シートの準備
  • PythonからSpread Sheetの情報を取得
  • 取得してきた情報をMySQLに格納

#前提条件

  • Googleアカウントを保有している
  • Python3系の開発環境がある
  • MySQLのデータベースがある

Google APIの有効化

まずは、お手持ちのGoogleアカウントでログインした状態で Google Developer Console にアクセスします

##プロジェクトを作成する

「プロジェクトの選択」をクリック
001.png

「新しいプロジェクト」から新しいプロジェクトを作ります
002.png

「プロジェクト名」を入力して作成します
 今回は、「tanaka-gss-test」という名前で作ってみます
003.png

無事にプロジェクトが作成されました
004.png

##Google Spread SheetのAPI(Google Sheets API)を有効化する

APIライブラリで、Google Spread Sheet用のAPIを探します
005.png

「Google Sheets API」が見つかるので、選択します
006.png

APIを有効にします
007.png

すると、Google Sheets APIが有効になります
008.png

##OAuth同意

外部からアクセスを許可するためにOAuth同意をします
Google Sheets APIから、「同意画面を設定」を選択します
009.png

User Typeを「内部」か「外部」かどちらか選択して、作成します
010.png

注意
個人アカウントのため「外部」を選択していますが、Google Workspaceユーザの場合は「内部」を選択した方が安全かと思います。

次に、アプリ情報を入力します
今回は、必須項目である下記の情報だけ入力します

必須項目 入力内容
アプリ名 任意のアプリケーション名(変更不可)
ユーザーサポートメール Googleアカウント
メールアドレス 自分のメールアドレス
011-01.png

次に、スコープを設定します
「スコープを追加または削除」を選択します
012.png

認証のスコープに入れるAPIを選択します
今回はGoogle Spread Sheetのデータを参照しかしないので
Google Sheets API の範囲 .../auth/spreadsheets.readonly を選択します
必要に応じて、他のAPIも追加します
013.png

「機密性の高いスコープ」の部分に
先ほど選択したAPIが表示されるようになります
014.png

次にテストユーザを決めます
このアプリの公開ステータスが「テスト中」に設定されている間も、アクセスできるユーザを設定します
今回は自分のアカウントだけを設定します

「+ADD USER」を選択します
015.png

サンプルなので dummy@gmail.com と入力していますが
実際は存在するGoogleアカウントを入力してください
015-01.png

先ほど入力したGoogleアカウントが表示されました
015-02.png

OAuth同意ができました
016.png

##認証情報の設定
いよいよ、この章最後の部分になります
あともう少しです、頑張ってください!

認証情報から、「+認証情報を作成」を選択します
017.png

「OAuthクライアントID」を選択します
018.png

アプリケーションの種類に
このアプリを実行するプラットフォームを選択します

  • ウェブ アプリケーション
  • Android
  • Chromeアプリ
  • iOS
  • テレビと入力が限られたデバイス
  • デスクトップアプリ
  • ユニバーサルWindows プラットフォーム

が選択でき、自分に該当するするものを選択します
今回は「デスクトップアプリ」を選択します

「名前」は、コンソール画面上で識別するためだけのもののため
適当に識別できる名前をつけてやります
019.png

OAuthクライアントが作成されました
ここで クライアントIDクライアント シークレットキー が表示されます
また「JSONをダウンロード」を選択すると、これらの情報が記載されているclient_secret_1234567890-xyzxyzxyzxyzxyz.apps.googleusercontent.com.json みたいなJSONファイルがダウンロードされます
あとで利用するので、大切に保管してください
020.png

#サンプルデータ、シートの準備

さて、Google API側の設定はようやく終わりました
ここから実際に読み込むためのデータの準備をしていきたいと思います

##サンプルデータの作成
個人情報テストデータジェネレーター という個人情報サンプルデータをランダムで生成してくれるサービスを利用します

このサービスが結構便利で、氏名、年齢、生年月日などの個人情報を10000レコードまで作成してくれます
今回はここから、

  • 氏名(漢字、ひらがな)
  • 年齢
  • 生年月日
  • 性別
  • 血液型
  • 郵便番号
  • 住所

を選択して、1000件のサンプルデータを作成します
generator.png

##Google Spread Sheetにインポート

次に、今回利用するGoogle Spread Sheetを新規作成します
そして、「ファイル」>「インポート」を選択します
import.png

「アップロード」を選択し、先ほど作成した個人情報サンプルデータをCSV取込します
import2.png

こんな感じで、CSVの内容がSpread Sheetに反映されます
今回はシート名を questionnaire にしました、のちほど使います
spreadsheet.png

#PythonからSpread Sheetの情報を取得
今回はPythonを使って、さきほど作成した Spread Sheetにアクセスします

まず必要なライブラリをインストールします

pip install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib

次に、ソースコードを用意します

GssDataImporter.py
import os

from google.auth.transport.requests import Request
from google_auth_oauthlib.flow import InstalledAppFlow
from google.oauth2.credentials import Credentials
from googleapiclient.discovery import build

SCOPES = 'https://www.googleapis.com/auth/spreadsheets.readonly'
TOKEN_JSON_FILE = 'token.json'

CLIENT_SECRET_FILE = 'D:\\workspace\\python\\GssImportTest\\credentials\\client_secret.json'
SPREADSHEET_ID = '1234567890ABCDEFGHIJKLMN'
RANGE_NAME = 'questionnaire!A2:H1001'


def get_questionnaire():
    credentials = None
    if os.path.exists(TOKEN_JSON_FILE):
        credentials = Credentials.from_authorized_user_file(TOKEN_JSON_FILE, SCOPES)

    if not credentials or not credentials.valid:
        if credentials and credentials.expired and credentials.refresh_token:
            credentials.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(CLIENT_SECRET_FILE, SCOPES)
            credentials = flow.run_local_server(port=0)
        with open(TOKEN_JSON_FILE, 'w') as token:
            token.write(credentials.to_json())

    service = build('sheets', 'v4', credentials=credentials)
    result = service.spreadsheets().values().get(spreadsheetId=SPREADSHEET_ID, range=RANGE_NAME).execute()

    return result.get('values', [])


def main():
    res = get_questionnaire()
    for row in res:
        print(row[0], row[1], row[2], row[3], row[4], row[5], row[6])


if __name__ == "__main__":
    main()

CLIENT_SECRET_FILE
さきほど「OAuthクライアント」作成時にダウンロードしたJSONファイルの場所を指定します

SPREADSHEET_ID
取込対象のGoogle Spread SheetのURLに書いてあるIDを指定します
https://docs.google.com/spreadsheets/d/1234567890ABCDEFGHIJKLMN/ というURLであれば、この 1234567890ABCDEFGHIJKLMN 部分になります

RANGE_NAME
シートの名称と範囲を [シート名]![範囲] という形で指定します
範囲は指定したい領域の左上のセルから右下のセルになります

- A B C D E F G H
1
2
3
4
5
6

例えば、test シートの B2セルからG5セルまでを対象にしたい場合は test!B2:G5 と指定します

今回用意しているのは

questionnaire というシート
カラムAの「氏名」から、カラムH「住所」まで
1行目はタイトル行なので、2行目から1000行後の1001行目

を利用したいので、questionnaire!A2:H1001 を指定しました

今回用意しているSpread Sheetをもう一度
data.png


さて、実際に実行してみましょう
アクセストークンがなく、初めてのアプリからのアクセスの場合は、Google Chromeが勝手に起動してログイン認証が求められます

ここで、自分のログイン中のアカウントを選択します
021.png

公開ステータスが「テスト」のものですよ、の警告がでます
Continueを選択します

022.png

注意
今回は自分が開発者のもののためContinueを選択しますが、そうではない場合は信頼できるデベロッパーか確認しましょう

アプリがあなたのアカウントにアクセスしますの確認が来ます
Continueを選択します
023.png

すると、Python側で処理が続行されます

Please visit this URL to authorize this application: https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=************************
松岡 大輔 まつおか だいすけ 20 2001/03/18 男 B 839-3912
宮城 康彦 みやぎ やすひこ 31 1990/08/12 男 A 584-9795
宮里 康文 みやざと やすふみ 51 1969/12/20 男 B 666-2986
坂本 弥生 さかもと やよい 68 1953/07/28 女 A 182-5377
中村 竜介 なかむら りゅうすけ 40 1981/01/07 男 A 121-0792
・・・
・・・
・・・
平賀 直樹 ひらが なおき 66 1955/05/23 男 A 336-3182
斉藤 明子 さいとう あきこ 42 1978/12/23 女 O 191-1756

プロセスは終了コード 0 で完了しました

Spread Sheetの内容がコンソールに出力されました!

#取得してきた情報をMySQLに格納

さきほどSpread Sheetから取得してきたデータはリスト型で返ってきています
これをそのままMySQL向けにexecutemanyで突っ込んでやります

まずは、取り込む先のDBにテーブルを作りましょう
下記のSQLをすでに用意しているDBで実行します

create_questionnaire_table.sql
CREATE TABLE `test`.`questionnaire` (
  `name` VARCHAR(128) NULL,
  `furigana` VARCHAR(128) NULL,
  `age` INT NULL,
  `birthday` DATE NULL,
  `gender` VARCHAR(16) NULL,
  `blood_type` VARCHAR(8) NULL,
  `postal_code` VARCHAR(16) NULL,
  `address` VARCHAR(256) NULL);

次にPython側で、MySQLに接続する準備をします
まずは必要なライブラリのインストールを行います

pip install --upgrade mysql-connector-python

さらに、さきほどSpread SheetにアクセスしたPythonコードに下記のコードを追加します
DBのuser、password、host、databaseは、適宜自分の環境に置き換えてください

def insert_data(questionnaire_data):
    conn = None
    try:
        conn = mysql.connector.connect(
            user='root',
            password='root',
            host='localhost',
            database='test')

        c = conn.cursor()

        sql = 'insert into test.questionnaire values (%s, %s, %s, %s, %s, %s, %s, %s)'
        c.executemany(sql, questionnaire_data)
        conn.commit()

        c.close()

    except Exception as e:
        print(e)

    finally:
        if conn is not None and conn.is_connected():
            conn.close()

メインメソッドも書き換えます

def main():
    res = get_questionnaire()
    insert_data(res)

全体的に見ると、こんな感じになるかと思われます

GssDataImporter.py
import os

import mysql.connector
from google.auth.transport.requests import Request
from google_auth_oauthlib.flow import InstalledAppFlow
from google.oauth2.credentials import Credentials
from googleapiclient.discovery import build

SCOPES = 'https://www.googleapis.com/auth/spreadsheets.readonly'
TOKEN_JSON_FILE = 'token.json'

CLIENT_SECRET_FILE = 'D:\\workspace\\python\\GssImportTest\\credentials\\client_secret.json'
SPREADSHEET_ID = '1234567890ABCDEFGHIJKLMN'
RANGE_NAME = 'questionnaire!A2:H1001'


def get_questionnaire():
    credentials = None
    if os.path.exists(TOKEN_JSON_FILE):
        credentials = Credentials.from_authorized_user_file(TOKEN_JSON_FILE, SCOPES)

    if not credentials or not credentials.valid:
        if credentials and credentials.expired and credentials.refresh_token:
            credentials.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(CLIENT_SECRET_FILE, SCOPES)
            credentials = flow.run_local_server(port=0)
        with open(TOKEN_JSON_FILE, 'w') as token:
            token.write(credentials.to_json())

    service = build('sheets', 'v4', credentials=credentials)
    result = service.spreadsheets().values().get(spreadsheetId=SPREADSHEET_ID, range=RANGE_NAME).execute()
    return result.get('values', [])


def insert_data(questionnaire_data):
    conn = None
    try:
        conn = mysql.connector.connect(
            user='root',
            password='rootroot',
            host='localhost',
            database='test')

        c = conn.cursor()

        sql = 'insert into test.questionnaire values (%s, %s, %s, %s, %s, %s, %s, %s)'
        c.executemany(sql, questionnaire_data)
        conn.commit()

        c.close()

    except Exception as e:
        print(e)

    finally:
        if conn is not None and conn.is_connected():
            conn.close()


def main():
    res = get_questionnaire()
    insert_data(res)


if __name__ == "__main__":
    main()

さて、Pythonコードを実行して、テーブルの方を見てみましょう
mysql.png

テーブルの中にコードが無事に入ってきました


いかがだったでしょうか

Spread Sheetに溜めている情報と社内にあるデータを組み合わせて、データ加工したり分析、BIツールで可視化したり、いろんな用途で使えそうですね

今回はただデータを引っ張ってくるだけでしたが、もちろんSpread SheetをAPIから変更することも可能です
詳しくは Google Sheets for Developers を参考にしてみてください

20
12
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
20
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?