PythonとGoogleSpreadSheetを連携してWebサイトから欲しいデータをスクレイピング（ExcelからGoogleSpreadSheetへの移行）

この記事は以前書いた[PythonとExcelを連携してWebサイトから欲しいデータをスクレイピング](https://qiita.com/kingdog/items/a12001e54d757c8af430)の続きとなります。
というか、ExcelでやっていたことをGoogleSpreadSheetに移行しただけのお話です。

# PythonをGoogleSpreadSheetで使えるようにする

まずは[Google Cloud Platform](https://console.cloud.google.com/apis/dashboard)からいろいろ認証設定を行う必要があります。
主に参考にしたのはこのサイト。
https://fresopiya.com/2019/04/18/googlespread/

他のサイトを見てもやることは変わらない。

1.　プロジェクトを作成する
2.　Google Drive とGoogle Sheets のAPI有効化
3.　認証情報の作成
　　役割の数が多く、もっと適切な権限もありそうな気がしますが、素直に[Project] > [編集者] で作成しました。
　　また上のリンクではUIが古く、認証情報のJSONファイルは同時に作成されません。下記リンクの手順でファイルを発行します。
　　https://support.google.com/workspacemigrate/answer/9222993?hl=ja
4.  対象のスプレッドシートに権限を設定する
　　リンク記事で作成したExcelファイルは事前にGoogleSpreadSheetにインポートしておきます。
    （ファイル > インポート > アップロード でローカルにあるExcelファイルをインポートできる）
　　使用するのは作成したJSONファイルの **client_email** の値を使用します。


ここまでやればGoogleSpreadSheet側の準備はOK。

# PythonからGoogleSpreadSheetを使用する

GoogleSpreadSheetを操作する用のファイルを作成します。
PythonからGoogleSpreadSheetを使用するためのimportなどはお決まりのようなのでさくっとコピペ。

```
$ pip install gspread
$ pip install oauth2client
```
gspreadとoauth2clientのインストールは忘れずに。


```python:googlespreadoperator.py
# Googleスプレッドシート操作
import gspread
import json
from oauth2client.service_account import ServiceAccountCredentials

scope = ['https://spreadsheets.google.com/feeds','https://www.googleapis.com/auth/drive']
 
#認証情報の設定
credentials = ServiceAccountCredentials.from_json_keyfile_name('JSONファイルのパス', scope)
 
#Googleスプレッドシートの取得
gClient = gspread.authorize(credentials)
SPREADSHEET_KEY = 'xxxxxxxxxx' #https://docs.google.com/spreadsheets/d/xxxxxxxxxx/edit#gid=0
worksheet = gClient.open_by_key(SPREADSHEET_KEY)
```

後は適当にセルの値を取得するメソッドとセルに値を書き込む処理を記述して疎通を確認します。
ファイルパスが通ってなかったり、共有設定をしたはずが共有されてなかったりということがあるので。（あった）


# ロジックの実装

以前Excelを操作するクラスとして分離して作成していたので、今回のようにGoogleSpreadSheetを操作するクラスを新たに作成して呼び出すメソッドを変えるだけという方法がとれた。ロジックも変わらない。さすが俺。


```python:exceloperator.py
# openpyxlを使用したExcel操作
import openpyxl

# 列位置
NAME = 1
COMPANY = 2
CATEGORY = 3
BASE_PRICE = 4
ASEETS = 5
BEFORE_ASEETS = 6
ALLOTMENT = 8
COMMISION = 9
COST = 10

def WriteExcel(rate, fund_info_list):
    # rはエスケープシーケンスを無視
    wb = openpyxl.load_workbook('Excelファイルのパス')
    ws = wb['総資産']
    ws['B14'] = rate

    ws = wb['ファンド']
    
    row = 2
    for fund in fund_info_list:
        # 6列目、7列目は更新対象外
        # ファンド名(A列)
        ws.cell(column=NAME, row=row, value=fund.name)
        # 取扱證券会社名(B列)
        ws.cell(column=COMPANY, row=row, value=fund.company)
        # 分類(C列)
        ws.cell(column=CATEGORY, row=row, value=fund.category)
        # 基準価額(D列)
        ws.cell(column=BASE_PRICE, row=row, value=fund.baseprice)    
        # 純資産額(E列)
        before_assets = ws.cell(row, ASEETS).value
        ws.cell(column=ASEETS, row=row, value=float(fund.assets.replace(',', '')))
        # 前回純資産額(F列)純資産額の差分(G列)は関数で計算するため対象外
        ws.cell(column=BEFORE_ASEETS, row=row, value=float(before_assets))
        # 直近分配金(H列)
        ws.cell(column=ALLOTMENT, row=row, value=int(fund.allotment))
        # 買付手数料(I列)
        if fund.commision == 'なし':
            ws.cell(column=COMMISION, row=row, value=0)
        else:
            ws.cell(column=COMMISION, row=row, value=fund.commision)
        # 信託報酬費用(J列)
        ws.cell(column=COST, row=row, value=fund.cost)
        row += 1

    wb.save('Excelファイルのパス')
```

```python:googlespreadoperator.py
(省略)
# 列位置
NAME = 1
COMPANY = 2
CATEGORY = 3
BASE_PRICE = 4
ASEETS = 5
BEFORE_ASEETS = 6
ALLOTMENT = 8
COMMISION = 9
COST = 10

def WriteGoogleSpread(rate, fund_info_list):
    # 為替レートを書き込む
    allAssetSheet = worksheet.get_worksheet(0)
    allAssetSheet.update_acell('B14', rate)

    # 各商品の情報を書き込む
    fundSheet = worksheet.get_worksheet(1)
    row = 2
    for fund in fund_info_list:
        # 6列目、7列目は更新対象外
        # ファンド名(A列)
        fundSheet.update_cell(row, NAME, fund.name)
        # 取扱證券会社名(B列)
        fundSheet.update_cell(row, COMPANY, fund.company)
        # 分類(C列)
        fundSheet.update_cell(row, CATEGORY, fund.category)
        # 基準価額(D列)
        fundSheet.update_cell(row, BASE_PRICE, fund.baseprice) 
        # 純資産額(E列)
        before_assets = fundSheet.cell(row, ASEETS).value
        fundSheet.update_cell(row, ASEETS, float(fund.assets.replace(',', '')))
        # 前回純資産額(F列)純資産額の差分(G列)は関数で計算するため対象外
        fundSheet.update_cell(row, BEFORE_ASEETS, float(before_assets))
        # 直近分配金(H列)
        fundSheet.update_cell(row, ALLOTMENT, int(fund.allotment))
        # 買付手数料(I列)
        if fund.commision == 'なし':
            fundSheet.update_cell(row, COMMISION, 0)
        else:
            fundSheet.update_cell(row, COMMISION, fund.commision)
        # 信託報酬費用(J列)
        fundSheet.update_cell(row, COST, fund.cost)
        row += 1
```
　　
変わったのはシートの取得方法がシート名からシートのインデックスになったことと、セルの値取得・更新方法をライブラリに合わせて変えただけです。脳死移行ここに極まれり。

呼び出し元としているmain.pyもgooglespreadoperatorをimportしてメソッドを呼び出すだけです。脳死移（略）

```python:main.py
import fund, googlespreadoperator
(省略)
# Googleスプレッドへ書き込み
googlespreadoperator.WriteGoogleSpread(rate, fund_info_list)
# EXCELへ書き込み
#exceloperator.WriteExcel(rate, fund_info_list)
```


# 雑感
実は前々からやろうと思っていたのだけど、「Googleの認証回りの設定めんどくさくね？」「ExcelファイルGoogleに移すのめんどくさくね？」と思っていたのでずっと放置していた。実際やってみると何も難しいことはなく、設定とExcelのインポート、実装と動作確認含めても **1時間ほど** ですべて終わってしまった。もっと早く取り掛かればよかった……

これでExcelを捨てて心置きなくPCの買い替えができる！
いや、今回初めてまともにGoogleSpreadSheet触れてみたけど、個人レベルなら高い金出してまでExcelつける理由ないわ。