Télécharger des fichiers sur Google Drive avec Lambda (Python)

Télécharger des fichiers sur Google Drive avec Lambda (Python)

Cet article est un article pratique pour passer en revue et corriger les connaissances acquises en développant Serverless Web App Mosaic. C'est l'un des w2or3w / items / 87b57dfdbcf218de91e2).

Ce serait bien de lire cet article après avoir regardé ce qui suit.

introduction

S3 est bon si vous enregistrez simplement le fichier, mais il ne convient pas que les gens se réfèrent à ce fichier. Même s'il s'agit d'une image, elle ne peut pas être visualisée telle quelle sur un navigateur Web, et il est nécessaire de la télécharger une fois, puis de la visualiser. C'est un peu compliqué. À cet égard, Google Drive est agréable car vous pouvez parcourir les images bien avec un navigateur ou une application, que ce soit un PC ou un smartphone.

contenu

Créer un projet Google Developers Console

Accédez à la Developers Console de Google. https://console.developers.google.com

Si vous n'avez pas de projet, créez-en un. Screenshot 2020-01-06 at 22.43.06.png

Activer l'API Google Drive

Cliquez sur "+ Activer les API et les services" en haut de l'écran "API et services" de la console pour activer Google Drive. Screenshot 2020-01-06 at 22.45.12.png Screenshot 2020-01-06 at 22.47.53.png Screenshot 2020-01-06 at 22.48.10.png

Créer des identifiants

Après avoir activé l'API Google Drive, créez les informations d'identification à partir de "Informations d'identification" dans le volet gauche de l'écran "API et services" de la console. Sélectionnez «Compte de service» dans le menu déroulant qui apparaît lorsque vous appuyez sur «+ Créer des informations d'identification» en haut de la page Informations d'identification. Screenshot 2020-01-06 at 22.56.00.png

Veuillez saisir le nom du compte de service pour le créer. L'identifiant du compte de service sous le nom du compte de service est une information importante, veuillez donc le gérer afin qu'il ne soit pas divulgué. ink (1).png

Confirmation du compte de service

Après avoir créé le compte de service, parcourez les détails du compte de service créé à partir de «Compte de service» dans le volet gauche de l'écran «IAM et administration» de la console. ink (2).png

Création d'une clé privée de compte de service

Dans les détails du compte de service, cliquez sur les boutons "Modifier" et "Créer + Clé" pour créer la clé privée au format JSON et télécharger le fichier JSON. ink (4).png

Créez un dossier sur Google Drive et partagez-le avec votre compte de service

Créez un dossier pour télécharger des fichiers sur Google Drive. Ici, le nom du dossier est «sample-drive». Partagez ensuite ce dossier avec le compte de service (adresse e-mail) que vous avez créé précédemment. Screenshot 2020-01-06 at 23.11.04.png ink (3).png

La chaîne après l'URL de ce dossier sera utilisée plus tard dans le programme. (Partie cachée de la capture ci-dessous) ink (5).png

Eh bien, cela complète les paramètres du côté Google. Ensuite, importons le fichier par programmation avec l'API Google.

Demander l'API Google à Lambda (Python) avec un compte de service

Tout d'abord, renommez le fichier JSON de clé privée du compte de service que vous avez téléchargé précédemment sous un nom approprié et placez-le au même emplacement que lambda_function.py. Je l'ai nommé "service-account-key.json" ici.

Ensuite, installez les bibliothèques requises.

$ pip install google-api-python-client -t .
$ pip install oauth2client -t .

Importez ensuite ce dont vous avez besoin.

lambda_function.py


  :
from googleapiclient.discovery import build 
from googleapiclient.http import MediaFileUpload 
from oauth2client.service_account import ServiceAccountCredentials 
  :

Ensuite, téléchargez le fichier avec l'implémentation suivante.

lambda_function.py


  :
def uploadFileToGoogleDrive(fileName, localFilePath):
    try:
        ext = os.path.splitext(localFilePath.lower())[1][1:]
        if ext == "jpg":
            ext = "jpeg"
        mimeType = "image/" + ext

        service = getGoogleService()
        file_metadata = {"name": fileName, "mimeType": mimeType, "parents": ["*********************************"] } 
        media = MediaFileUpload(localFilePath, mimetype=mimeType, resumable=True) 
        file = service.files().create(body=file_metadata, media_body=media, fields='id').execute()

    except Exception as e:
        logger.exception(e)

def getGoogleService():
    scope = ['https://www.googleapis.com/auth/drive.file'] 
    keyFile = 'service-account-key.json'
    credentials = ServiceAccountCredentials.from_json_keyfile_name(keyFile, scopes=scope)
    
    return build("drive", "v3", credentials=credentials, cache_discovery=False) 

"parents": ["*********************************"] Cette partie est un dossier créé dans Google Drive Remplacez-le par la chaîne après l'URL dans.

Enfin, juste au cas où, je posterai l'intégralité du programme.

lambda_function.py


# coding: UTF-8
import boto3
import os
import json
from urllib.parse import unquote_plus
import numpy as np
import cv2
import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)
s3 = boto3.client("s3")
rekognition = boto3.client('rekognition')

from gql import gql, Client
from gql.transport.requests import RequestsHTTPTransport
ENDPOINT = "https://**************************.appsync-api.ap-northeast-1.amazonaws.com/graphql"
API_KEY = "da2-**************************"
_headers = {
    "Content-Type": "application/graphql",
    "x-api-key": API_KEY,
}
_transport = RequestsHTTPTransport(
    headers = _headers,
    url = ENDPOINT,
    use_json = True,
)
_client = Client(
    transport = _transport,
    fetch_schema_from_transport = True,
)

from googleapiclient.discovery import build 
from googleapiclient.http import MediaFileUpload 
from oauth2client.service_account import ServiceAccountCredentials 

def lambda_handler(event, context):
    bucket = event["Records"][0]["s3"]["bucket"]["name"]
    key = unquote_plus(event["Records"][0]["s3"]["object"]["key"], encoding="utf-8")
    logger.info("Function Start (deploy from S3) : Bucket={0}, Key={1}" .format(bucket, key))

    fileName = os.path.basename(key)
    dirPath = os.path.dirname(key)
    dirName = os.path.basename(dirPath)
    
    orgFilePath = "/tmp/" + fileName
    
    if (not key.startswith("public") or key.startswith("public/processed/")):
        logger.info("don't process.")
        return
    
    apiCreateTable(dirName, key)

    keyOut = key.replace("public", "public/processed", 1)
    dirPathOut = os.path.dirname(keyOut)

    try:
        s3.download_file(Bucket=bucket, Key=key, Filename=orgFilePath)

        orgImage = cv2.imread(orgFilePath)
        grayImage = cv2.cvtColor(orgImage, cv2.COLOR_RGB2GRAY)
        processedFileName = "gray-" + fileName
        processedFilePath = "/tmp/" + processedFileName
        uploadImage(grayImage, processedFilePath, bucket, os.path.join(dirPathOut, processedFileName), dirName, False)

        uploadFileToGoogleDrive(key, orgFilePath)
        detectFaces(bucket, key, fileName, orgImage, dirName, dirPathOut)

    except Exception as e:
        logger.exception(e)
        raise e
        
    finally:
        if os.path.exists(orgFilePath):
            os.remove(orgFilePath)

def uploadImage(image, localFilePath, bucket, s3Key, group, isUploadGoogleDrive):
    logger.info("start uploadImage({0}, {1}, {2}, {3})".format(localFilePath, bucket, s3Key, group))
    try:
        cv2.imwrite(localFilePath, image)
        s3.upload_file(Filename=localFilePath, Bucket=bucket, Key=s3Key)
        apiCreateTable(group, s3Key)
        if isUploadGoogleDrive:
            uploadFileToGoogleDrive(s3Key, localFilePath)
    except Exception as e:
        logger.exception(e)
        raise e
    finally:
        if os.path.exists(localFilePath):
            os.remove(localFilePath)

def apiCreateTable(group, path):
    logger.info("start apiCreateTable({0}, {1})".format(group, path))
    try:
        query = gql("""
            mutation create {{
                createSampleAppsyncTable(input:{{
                group: \"{0}\"
                path: \"{1}\"
              }}){{
                group path
              }}
            }}
            """.format(group, path))
        _client.execute(query)
    except Exception as e:
        logger.exception(e)
        raise e

def detectFaces(bucket, key, fileName, image, group, dirPathOut):
    logger.info("start detectFaces ({0}, {1}, {2}, {3}, {4})".format(bucket, key, fileName, group, dirPathOut))
    try:
        response = rekognition.detect_faces(
            Image={
                "S3Object": {
                    "Bucket": bucket,
                    "Name": key,
                }
            },
            Attributes=[
                "ALL",
            ]
        )

        name, ext = os.path.splitext(fileName)
        
        jsonFileName = name + ".json"
        localPathJSON = "/tmp/" + jsonFileName
        with open(localPathJSON, 'w') as f:
            json.dump(response, f, ensure_ascii=False)
        s3.upload_file(Filename=localPathJSON, Bucket=bucket, Key=os.path.join(dirPathOut, jsonFileName))
        if os.path.exists(localPathJSON):
            os.remove(localPathJSON)
        
        imgHeight = image.shape[0]
        imgWidth = image.shape[1]
        index = 0
        for faceDetail in response["FaceDetails"]:
            index += 1
            faceFileName = "face_{0:03d}".format(index) + ext
            box = faceDetail["BoundingBox"]
            x = max(int(imgWidth * box["Left"]), 0)
            y = max(int(imgHeight * box["Top"]), 0)
            w = int(imgWidth * box["Width"])
            h = int(imgHeight * box["Height"])
            logger.info("BoundingBox({0},{1},{2},{3})".format(x, y, w, h))
            
            faceImage = image[y:min(y+h, imgHeight-1), x:min(x+w, imgWidth)]
            
            localFaceFilePath = os.path.join("/tmp/", faceFileName)
            uploadImage(faceImage, localFaceFilePath, bucket, os.path.join(dirPathOut, faceFileName), group, False)
            cv2.rectangle(image, (x, y), (x+w, y+h), (0, 0, 255), 3)

        processedFileName = "faces-" + fileName
        processedFilePath = "/tmp/" + processedFileName
        uploadImage(image, processedFilePath, bucket, os.path.join(dirPathOut, processedFileName), group, True)
    except Exception as e:
        logger.exception(e)
        raise e


def uploadFileToGoogleDrive(fileName, localFilePath):
    try:
        ext = os.path.splitext(localFilePath.lower())[1][1:]
        if ext == "jpg":
            ext = "jpeg"
        mimeType = "image/" + ext

        service = getGoogleService()
        file_metadata = {"name": fileName, "mimeType": mimeType, "parents": ["*********************************"] } 
        media = MediaFileUpload(localFilePath, mimetype=mimeType, resumable=True) 
        file = service.files().create(body=file_metadata, media_body=media, fields='id').execute()

    except Exception as e:
        logger.exception(e)

def getGoogleService():
    scope = ['https://www.googleapis.com/auth/drive.file'] 
    keyFile = 'service-account-key.json'
    credentials = ServiceAccountCredentials.from_json_keyfile_name(keyFile, scopes=scope)
    
    return build("drive", "v3", credentials=credentials, cache_discovery=False) 

Contrôle de fonctionnement

Lorsque vous téléchargez une image à partir d'une application Web, Python de Lambda s'exécute pour traiter l'image, puis vous téléchargez également l'image d'origine et l'image avec le retour sur investissement marqué sur le visage vers Google Drive. Contrairement à S3, je suis heureux de le voir comme une image. Screenshot 2020-01-08 at 22.51.30.png

Épilogue

Je voudrais également parler du service cloud de Google. J'aime Google. C'est l'un des objectifs pour 2020.

En passant, il y a de nombreux produits Google autour de moi, tels que le Pixel 3a, le Chromebook, le Google Home Mini, le Chromecast et le Google Wifi. En ce qui concerne le service, j'utilise quotidiennement Google Fit avec Mi Band ainsi que Gmail, Agenda, Drive, Photo, etc., et j'aime publier Google Map dans un style de guide local. Google One a également été mis à niveau à 2 To (13 000 ¥ par an).

OK Google, je t'aime!

Recommended Posts

Télécharger des fichiers sur Google Drive avec Lambda (Python)
Télécharger des images sur Google Drive avec Python
Accédez à Google Drive avec Python
Comment charger des fichiers dans Google Drive avec Google Colaboratory
Transférer vers un Drive partagé avec l'API Google Drive V3
Téléchargez des fichiers Google Drive en Python
Comment télécharger des fichiers sur Cloud Storage avec le SDK Python de Firebase
Importez et supprimez des fichiers dans Google Cloud Storages avec django-storage
Comment rechercher Google Drive dans Google Colaboratory
Connectez-vous à s3 avec AWS Lambda Python
Comment télécharger avec Heroku, Flask, Python, Git (4)
Télécharger des fichiers avec Django
Conduisez WebDriver avec python
Exemple de notification Slack avec python lambda
Télécharger des fichiers directement sur Google Drive (à l'aide de Google Colaboratory)
Exporter un instantané RDS vers S3 avec Lambda (Python)
Téléchargez ce que vous avez dans la demande vers S3 avec AWS Lambda Python
Comment télécharger avec Heroku, Flask, Python, Git (Partie 3)
Un moyen facile de gratter avec Python en utilisant Google Colab
Écrire plusieurs enregistrements dans DynamoDB avec Lambda (Python, JavaScript)
Comment télécharger avec Heroku, Flask, Python, Git (Partie 1)
Comment télécharger avec Heroku, Flask, Python, Git (Partie 2)
Connectez-vous à BigQuery avec Python
Exploitez TwitterBot avec Lambda, Python
Connectez-vous à Wikipedia avec Python
Publiez sur Slack avec Python 3
Étudiez Python avec Google Colaboratory
Tri des fichiers image avec Python (2)
Trier de gros fichiers avec python
Tri des fichiers image avec Python (3)
Tri des fichiers image avec Python
Intégrez des fichiers PDF avec Python
Lire des fichiers .txt avec Python
Basculer python vers 2.7 avec des alternatives
Écrire en csv avec Python
Montez Google Drive avec google-drive-ocamlfuse
Conseils relatifs aux API Google Drive (Python)
Comment utiliser Python lambda
Comment extraire n'importe quel rendez-vous dans Google Agenda avec Python
[AWS] Essayez d'ajouter la bibliothèque Python à la couche avec SAM + Lambda (Python)
Défi problème 5 avec Python: lambda ... j'ai décidé de copier sans
Publier un message sur Google Hangouts Chat avec un fil de discussion (Python)
Enregistrer des images sur le Web sur un lecteur avec Python (Colab)
[Python] Exportez régulièrement de CloudWatch Logs vers S3 avec Lambda
Utilisez Google Agenda à partage limité avec Lambda (Python) [cloudpack Osaka]
Jusqu'à ce que nous ayons créé un mécanisme pour télécharger des fichiers partagés vers Slack vers Google Drive sans serveur
[Présentation de l'application Udemy Python3 +] 58. Lambda
Téléchargeons des fichiers S3 avec CLI
Python: comment utiliser async avec
Lien pour commencer avec python
[Python] Ecrire dans un fichier csv avec Python
Manipulation des fichiers EAGLE .brd avec Python
Ravi de vous rencontrer avec python
Essayez d'exploiter Facebook avec Python
Détection de visage avec Lambda (Python) + Rekognition
Sortie vers un fichier csv avec Python
[Lambda] [Python] Publier sur Twitter depuis Lambda!