PythonのプログラムとGoogle Photos APIを使って、Googleフォトに画像を1枚アップロードする方法をまとめます。
プログラムを使って、画像ファイルをGoogleフォトへアップロードできるようになります。
前提として、Googleアカウントを持っている必要があります。
概要
大きく4つのステップとなります。
STEP1,2,3が準備編で、STEP4で実際に画像をアップロードします。
- STEP1テストユーザを追加
- STEP2Google Photos APIを有効化
- STEP3必要なファイルを準備
- STEP4画像ファイルのアップロード
手順
STEP1. テストユーザを追加
まず、Googleフォトへのログイン権限を許可するため、テストユーザを追加します。
①Google Cloud Platformにログインします。
②APIとサービスから、Oauth同意画面を選択します。
③テストユーザのところにある+ADD USERSを選択します。
④アクセスしたいGoogleフォトアカウントのgmailアドレスを入力し、保存します。
STEP2. Google Photos APIを有効化
次に、Google Photos APIを有効化します。
①Google Cloud Platformにログインします。
②APIとサービスを選択します。
③ライブラリを選択します。
④検索バーに”photos”と入力し、Photos Library APIを選択します。
⑤有効化を選択します。
STEP3. 必要なファイルを準備
Google Photos APIを使って画像をアルバムにアップロードするために必要な物は、3つです。
アップロードしたい画像ファイル
アップロードしたい画像ファイルを用意し、任意のフォルダに入れておきます。
ここでは、ファイル名をtest.jpgとして用意することにします。
認証ファイル
APIをつかってGoogleフォトにアクセスするために必要となる、認証ファイルを用意します。
①Google Cloud Platformにログインします。
②APIとサービスから、OAuth同意画面を選択します。
③外部を選択し、次へを選択します。
④アプリケーション名を”Google Photos with Python”にして次へを選択します。
⑤APIとサービスから、認証情報を選択します。
⑥上部にある+認証情報を作成を選択し、OAuthクライアント IDを選択します。
⑦アプリケーションの種類からデスクトップアプリを選択し、名前を”Google Photos with Python”にします。
⑧JSONをダウンロードからclient_secret_xxxxxxxxx.jsonというファイルをダウンロードします。
⑨ダウンロードした.jsonファイルを”credentials.json”にリネームします。
⑩credentials.jsonファイルをtest.jpgファイルと同じフォルダに入れておきます。
APIを使ったアップロードプログラム
APIを使って、Googleフォトにtest.jpgファイルをアップロードするプログラムコードを作成します。ここでは、Pythonで作成したサンプルコード(upload.py)を載せておきます。
このファイルも、test.jpgファイルと同じフォルダに入れておきます。
upload.pyは、以下3つのステップでtest.jpgをアップロードします。
- Googleフォトにログイン;login関数
- testという名前でアルバムを作成;create_albums関数
- test.jpgをtestアルバムにアップロード;upload関数
コードの冒頭でimportしているライブラリは、事前にインストールしておきましょう。
from pathlib import Path
from requests_oauthlib import OAuth2Session
import json
import os,sys
#各URLやスコープ
api_url = "https://photoslibrary.googleapis.com/v1/mediaItems"
scope = ["https://www.googleapis.com/auth/photoslibrary"]
albums_url = "https://photoslibrary.googleapis.com/v1/albums"
upload_url = "https://photoslibrary.googleapis.com/v1/uploads"
media_url = "https://photoslibrary.googleapis.com/v1/mediaItems:batchCreate"
def main():
#Googleフォトにログインする
google = login()
#testという名前の新しいアルバムを作成
album_id = create_albums(google, "test")
#写真のアップロード
upload(google, album_id)
# ログインしてセッションオブジェクトを返す
def login():
# 認証情報を読み込み
auth_info = json.loads(Path(resource_path("./credentials.json")).read_text()).get("installed", None)
assert auth_info is not None
# トークンがあったら読み込む
token = load_token()
# トークン更新用の認証情報
extras = {
"client_id": auth_info.get("client_id"),
"client_secret": auth_info.get("client_secret"),
}
# セッションオブジェクトを作成
google = OAuth2Session(
auth_info.get("client_id"),
scope=scope,
token=token,
auto_refresh_kwargs=extras,
token_updater=save_token,
auto_refresh_url=auth_info.get("token_uri"),
redirect_uri=auth_info.get("redirect_uris")[0]
)
# ログインしていない場合ログインを行う
if not google.authorized:
authorization_url, state = google.authorization_url(
auth_info.get("auth_uri"),
access_type="offline",
prompt="select_account"
)
# 認証URLにアクセスしてコードをペースト
print("Access {} and paste code.".format(authorization_url))
access_code = input(">>> ")
google.fetch_token(
auth_info.get("token_uri"),
client_secret=auth_info.get("client_secret"),
code=access_code
)
assert google.authorized
# トークンを保存
save_token(google.token)
return google
# token.jsonが存在したら読み込み
def load_token():
# 存在しない場合は期限切れのダミーを返す
token = {
"access_token": "",
"refresh_token": "",
"token_type": "",
"expires_in": "-30",
}
path = Path(resource_path("./token.json"))
if path.exists():
token = json.loads(path.read_text())
return token
# ログイン後に取得したトークンをtoken.jsonに保存
def save_token(token):
token = {
"access_token": token.get("access_token"),
"refresh_token": token.get("refresh_token"),
"token_type": token.get("token_type"),
"expires_in": token.get("expires_in")
}
Path("token.json").write_text(json.dumps(token))
def create_albums(google, name):
data = {
"album":{
"title": name
}
}
data = json.dumps(data)
r = google.post(albums_url, data=data)
print(r.content)
r = r.json()
albumid = r["id"]
print(albumid)
return albumid
def upload(google, album_id):
headers = {
'Authorization': "Bearer " + str(google.token),
'Content-Type': 'application/octet-stream',
'X-Goog-Upload-File-Name': "test.jpg",
'X-Goog-Upload-Protocol': "raw",
}
image_path = resource_path("./test.jpg")
with open(image_path, 'rb') as image_data:
# 写真のアップロード
response1 = google.post(upload_url, headers=headers, data=image_data)
print("\nresponse1=" + str(response1.content))
r = response1.content
data = {
'albumId': album_id,
"newMediaItems":[{
"simpleMediaItem":
{"uploadToken":r.decode("utf-8")}
}
]
}
data = json.dumps(data)
print("\ndata=" + data)
#写真の登録
response2 = google.post(media_url, data=data)
print("\nresponse2=" + str(response2.content))
def resource_path(relative_path):
try:
base_path = sys._MEIPASS
except Exception:
base_path = os.path.dirname(__file__)
return os.path.join(base_path, relative_path)
if __name__ == "__main__":
main()
STEP4. 画像ファイルのアップロード
ここまでで、以下3つのファイルを準備できました。
それでは早速、PythonプログラムからAPIを使って、Googleフォトにtest.jpgファイルをアップロードしてみます。
①pythonコード(test.py)を実行します。
②初回実行時はtokenファイルが無いため、標準出力画面にURLが表示され、一旦処理がストップします。
③標準出力に表示されたURLをCtrl + クリックし、ブラウザで表示します。
④ログインを促されるので、アクセスしたいGoogleアカウントでログインします。
⑤ログインすると、ランダムに生成されたコードが表示されますので、コピーして標準出力画面の”>>>”となっているところにペーストします。
⑥コードをペーストすると、あとはプログラムが自動でtestという名前でアルバム新規作成し、test.jpgファイルをそのアルバムにアップロードするところまでを行ってくれますので、動作が完了するのを待ちます。
⑦プログラムの動作がおわったら、Googleフォトにログインし、testという名前のアルバムにtest.jpgがアップロードされていることを確認し、終わりとなります。
参考サイト
upload.pyのコードは、以下2つの記事をまるっと参考にさせていただきました。
upload関数で使用しているupload_urlとmedia_urlの値については、かなり試行錯誤しましたので、本記事のupload.pyのコードではその点も明記しておきました。
また参考記事では、upload関数の第3引数と第4引数に、アップロードする画像ファイルの情報を辞書型で渡していますが、本記事のコードでは簡易化しています。
以上になります!