S3バケット内の情報取得スクリプト

# 経緯
S3バケット内のオブジェクト（ファイル）について、名前・最終更新日・サイズを取得してCSVファイルに出力したい。
Pythonでスクリプトを書いていく。不慣れなため無駄が多いかと思うが、ご容赦を。
参考：[AWS Lambda Python S3でフォルダ以下のファイル一覧を取得する](https://qiita.com/koji4104/items/15ac578e561f53a0dadc)

# スクリプト作成
以下の構成において、xxx配下のファイル一覧（名前、最終更新日、サイズ）を取得する。
また、オブジェクトは名前（ooooo）で絞って出力する。
**s3://aaa.backup/xxx/ooooo**

aaa.backup：バケット
xxx：プリフィックス
ooooo**：オブジェクト

出力するCSVの中身は以下のようにしたい。
**見出し: Name,Data,Size**
**データ: oooooabcd,[JST]2022/01/10 12:05:10,20.5 KB**

# オブジェクトキーの出力
参考：[Boto 3 で Amazon S3 上の key を取得する方法、実装例、注意点](https://qiita.com/ikai/items/38c52e0c459792a4da46)

Boto3でS3 Buckets上の情報を取得するときは、list_objects() を使用する。
今回は対象が多いため、プリフィックスとオブジェクト名の一部を指定して条件を絞る。

# 最終更新日をJSTに変更
S3の最終更新日時（content['LastModified']）はUTCで保存されている。今回はJSTで出力したいため、変換を行う。
参考：[PythonでUTCからJSTへの時刻の変換](https://dev.classmethod.jp/articles/python-time-string-timezone/)

この方法で行うとS3で保持している最終更新日の最後の6字「+00:00」が邪魔になり、UTCのまま出力されてしまう。
そのため、文字列へ変換して該当文字を削除することでJSTで出力することができる。

* datetimeを使用してJSTへの変換を指定
* 文字列にし、「+00:00」を省く（後方から6文字削除）
* JSTへの時刻の変換

```
import datetime

def utc_to_jst(timestamp_utc):
    datetime_utc = datetime.datetime.strptime(timestamp_utc + "+0000", "%Y-%m-%d %H:%M:%S%z")
    datetime_jst = datetime_utc.astimezone(datetime.timezone(datetime.timedelta(hours=+9)))
    timestamp_jst = datetime.datetime.strftime(datetime_jst, '%Y-%m-%d %H:%M:%S')
    return timestamp_jst

for page in page_iterator:
    for content in page['Contents']:
        date = content['LastModified']
        Last = str(date)
        Last = Last[:-6]
        print(Last)
        print("[JST]" + utc_to_jst(Last))
```

（結果）
> 2022/01/10 12:05:10 +00:00
[JST]2022/01/10 12:05:10

# オブジェクト名からプリフィックスの表示を除く
そのままオブジェクトキー（content['Key']）を出力すると、プリフィックスを含んだものが出力される。
見にくいため、プリフィックス名を指定してオブジェクト名のみを出力する。
参考：[完全一致する文字列を削除: replace()](https://note.nkmk.me/python-str-remove-strip/)

```
        name = content['Key']
        print(name)
        print(name.replace('xxx/',''))
```

（結果）
> xxx/oooooabcd
oooooabcd

# サイズをKB表示にする
サイズ（content['Size']）をそのまま出力すると、バイトのため大きなサイズの際は見にくい。
また、単位もつけたいため、以下のように記述。
1024で割ってKBへ変換＞小数点以下第2位を四捨五入＞データ型を文字列に変換＞単位をつける
 
```
        n = content['Size']/1024
        Size = round(n,1)
        Size = str(Size) + "KB"
        print(content['Size'])
        print(Size)
```

（結果）
> 22837
22.3KB

# 1000件以上のデータ出力に対応

[Python で Amazon S3 バケットの全オブジェクト名を取得するジェネレータ](https://qiita.com/hoto17296/items/d3f01162ef959a0d2f04)
今回はV2不使用のため不要だったが、使用する際は考慮が要るかも。

# CSV出力

[Pythonでcsvファイルにデータを書き込みをする基本中の基本](https://tonari-it.com/python-csv-writer-writerow/)

* Excelでも使用したいので文字コードを shift-jis で保存
* ヘッダ行をつける（Name,Date,Size）　※実際のスクリプトでは1度開いてヘッダをつけ、再度開き直してオブジェクトキーなどの入力を行う
* ファイル名がオブジェクト名になるよう変数を設定

```
import csv

wwith open(Object + '_JST.csv','a',newline='',encoding = "shift-jis") as f:
    writer = csv.writer(f)
    writer.writerow(["Name","Date","Size"])
        with open(Object + '_JST.csv','a',newline='',encoding = "shift-jis") as f:
            writer = csv.writer(f)
writer.writerow([content['Key'].replace('xxx/',''),Last,Size])
```

## スクリプト
以下、完成したスクリプト



```
import boto3
import datetime
import csv

MY_REGION = 'MY_REGION';
MY_BUCKET = 'MY_BUCKET';
TARGET_PATH = 'TARGET_PATH/';
Object = 'Object';

client = boto3.client('s3', region_name=MY_REGION)
paginator = client.get_paginator('list_objects')

# フィルタリング設定
operation_parameters = {
    'Bucket': MY_BUCKET,
    'Prefix': TARGET_PATH + Object
}

page_iterator = paginator.paginate(**operation_parameters)

# UTCからJSTへの時刻の変換
def utc_to_jst(timestamp_utc):
    datetime_utc = datetime.datetime.strptime(timestamp_utc + "+0000", "%Y-%m-%d %H:%M:%S%z")
    datetime_jst = datetime_utc.astimezone(datetime.timezone(datetime.timedelta(hours=+9)))
    timestamp_jst = datetime.datetime.strftime(datetime_jst, '%Y-%m-%d %H:%M:%S')
    return timestamp_jst

# 出力CSVを作成し、ヘッダをつける
with open(Object + '_JST.csv','a',newline='',encoding = "shift-jis") as f:
    writer = csv.writer(f)
    writer.writerow(["Name","Date","Size"])

for page in page_iterator:
    for content in page['Contents']:

# 最終更新日をUTCからJSTへ変更
        Last = content['LastModified']
        Last = str(Last)
        Last = Last[:-6]
        Last = utc_to_jst(Last)

# サイズをキロバイトへ変更
        n = content['Size']/1024
        Size = round(n,1)
        Size = str(Size) + "KB"

        with open(Object + '_JST.csv','a',newline='',encoding = "shift-jis") as f:
            writer = csv.writer(f)   
            
# CSVへ情報出力
writer.writerow([content['Key'].replace('xxx/',''),Last,Size])

```

（出力結果）
> Name,Data,Size
oooooabcd,[JST]2022/01/10 12:05:10,20.5KB
oooooefgh,[JST]2022/01/11 10:03:18,13.2KB
…