Archiviazione, analisi e generazione di report delle immagini in Google Workspace e Google Cloud

1. Panoramica

Questo codelab immagina un possibile flusso di lavoro aziendale: archiviazione delle immagini, analisi e generazione di report. Immagina che la tua organizzazione disponga di una serie di immagini che occupano spazio su una risorsa vincolata. Vuoi archiviare i dati, analizzare le immagini e, soprattutto, generare un report che riassuma le località archiviate e i risultati dell'analisi, riuniti e pronti per essere utilizzati dalla gestione. Google Cloud fornisce gli strumenti per farlo utilizzando le API di due delle sue linee di prodotti, Google Workspace (in precedenza, G Suite o Google Apps) e Google Cloud (in precedenza Google Cloud).

In questo scenario, l'utente aziendale avrà delle immagini su Google Drive. Ha senso eseguire il back up di questi elementi "con una temperatura più bassa", ad esempio le classi di archiviazione disponibili su Google Cloud Storage. Google Cloud Vision consente agli sviluppatori di integrare facilmente le funzionalità di rilevamento visivo nelle applicazioni, tra cui il rilevamento di oggetti e punti di riferimento, il riconoscimento ottico dei caratteri (OCR) e così via. Infine, un foglio di lavoro in Fogli Google è uno strumento di visualizzazione utile per riassumere tutto questo per il tuo capo.

Dopo aver completato questo codelab per creare una soluzione che sfrutta tutto Google Cloud, ci auguriamo che troverai l'ispirazione per creare qualcosa di ancora più incisivo per la tua organizzazione o per i tuoi clienti.

Obiettivi didattici

  • Come utilizzare Cloud Shell
  • Come autenticare le richieste API
  • Come installare la libreria client delle API di Google per Python
  • Come abilitare le API di Google
  • Come scaricare file da Google Drive
  • Come caricare oggetti/blob in Cloud Storage
  • Come analizzare i dati con Cloud Vision
  • Come scrivere righe in Fogli Google

Che cosa ti serve

  • Un Account Google (gli account Google Workspace possono richiedere l'approvazione di un amministratore)
  • Un progetto Google Cloud con un account di fatturazione Google Cloud attivo
  • Dimestichezza con i comandi del terminale/della shell del sistema operativo
  • Competenze di base in Python (2 o 3), ma puoi utilizzare qualsiasi linguaggio supportato

Avere esperienza con i quattro prodotti Google Cloud elencati sopra sarebbe utile, ma non necessaria. Se hai il tempo di familiarizzare con loro separatamente, ti invitiamo a eseguire dei codelab per ciascuno prima di affrontare l'esercizio qui:

Sondaggio

Come utilizzerai questo tutorial?

Solo lettura Leggilo e completa gli esercizi

Come valuteresti la tua esperienza con Python?

Principiante Livello intermedio Eccellente

Come giudichi la tua esperienza di utilizzo dei servizi Google Cloud?

Principiante Livello intermedio Eccellente

Come giudichi la tua esperienza di utilizzo dei servizi per sviluppatori di Google Workspace?

Principiante Livello intermedio Eccellente

Vorresti vedere contenuti più "orientati al business" rispetto a quelli che sono introduzioni delle funzionalità dei prodotti?

No Più di entrambi

2. Configurazione e requisiti

Configurazione dell'ambiente autogestito

  1. Accedi alla console Google Cloud e crea un nuovo progetto o riutilizzane uno esistente. Se non hai ancora un account Gmail o Google Workspace, devi crearne uno.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Il Nome progetto è il nome visualizzato dei partecipanti del progetto. Si tratta di una stringa di caratteri non utilizzata dalle API di Google. Puoi aggiornarla in qualsiasi momento.
  • L'ID progetto deve essere univoco in tutti i progetti Google Cloud ed è immutabile (non può essere modificato dopo essere stato impostato). La console Cloud genera automaticamente una stringa univoca. di solito non ti importa cosa sia. Nella maggior parte dei codelab, dovrai fare riferimento all'ID progetto (in genere è identificato come PROJECT_ID). Se l'ID generato non ti soddisfa, puoi generarne un altro casuale. In alternativa, puoi provarne una personalizzata per verificare se è disponibile. Non può essere modificato dopo questo passaggio e rimarrà per tutta la durata del progetto.
  • Per informazione, c'è un terzo valore, un numero di progetto, utilizzato da alcune API. Scopri di più su tutti e tre questi valori nella documentazione.
  1. Successivamente, dovrai abilitare la fatturazione nella console Cloud per utilizzare risorse/API Cloud. Eseguire questo codelab non dovrebbe costare molto. Per arrestare le risorse in modo da non incorrere in fatturazione oltre questo tutorial, puoi eliminare le risorse che hai creato o eliminare l'intero progetto. I nuovi utenti di Google Cloud sono idonei al programma prova senza costi di 300$.

Avvia Cloud Shell

Riepilogo

Sebbene sia possibile sviluppare il codice localmente sul laptop, un obiettivo secondario di questo codelab è insegnarti a utilizzare Google Cloud Shell, un ambiente a riga di comando in esecuzione nel cloud tramite il browser web moderno.

Attiva Cloud Shell

  1. Dalla console Cloud, fai clic su Attiva Cloud Shell 853e55310c205094.png.

55efc1aaa7a4d3ad.png

Se non hai mai avviato Cloud Shell, ti viene mostrata una schermata intermedia (below the fold) che descrive di cosa si tratta. In tal caso, fai clic su Continua (e non la vedrai più). Ecco come appare quella singola schermata:

9c92662c6a846a5c.png

Il provisioning e la connessione a Cloud Shell dovrebbero richiedere solo qualche istante.

9f0e51b578fecce5.png

Questa macchina virtuale viene caricata con tutti gli strumenti di sviluppo di cui hai bisogno. Offre una home directory permanente da 5 GB e viene eseguita in Google Cloud, migliorando notevolmente le prestazioni di rete e l'autenticazione. Gran parte, se non tutto, del lavoro in questo codelab può essere svolto semplicemente con un browser o Chromebook.

Una volta eseguita la connessione a Cloud Shell, dovresti vedere che il tuo account è già autenticato e il progetto è già impostato sul tuo ID progetto.

  1. Esegui questo comando in Cloud Shell per verificare che l'account sia autenticato:
gcloud auth list

Output comando

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Esegui questo comando in Cloud Shell per confermare che il comando gcloud è a conoscenza del tuo progetto:
gcloud config list project

Output comando

[core]
project = <PROJECT_ID>

In caso contrario, puoi impostarlo con questo comando:

gcloud config set project <PROJECT_ID>

Output comando

Updated property [core/project].

3. Conferma l'ambiente Python

Questo codelab richiede l'uso del linguaggio Python (sebbene molti linguaggi siano supportati dalle librerie client delle API di Google, quindi non esitare a creare qualcosa di equivalente nel tuo strumento di sviluppo preferito e usa semplicemente il Python come pseudocodice). In particolare, questo codelab supporta Python 2 e 3, ma consigliamo di passare alla versione 3.x il prima possibile.

Cloud Shell è un pratico strumento disponibile per gli utenti direttamente dalla console Cloud e non richiede un ambiente di sviluppo locale, quindi questo tutorial può essere svolto completamente nel cloud con un browser web. In particolare per questo codelab, Cloud Shell ha già preinstallato entrambe le versioni di Python.

Su Cloud Shell è anche installato IPython: si tratta di un interprete Python interattivo di livello superiore che consigliamo, soprattutto se fai parte della community di data science o machine learning. In caso affermativo, IPython è l'interprete predefinito per i blocchi note Jupyter e per Colab, i blocchi note Jupyter ospitati da Google Research.

IPython favorisce prima un interprete Python 3, ma utilizza Python 2 se 3.x non è disponibile. È possibile accedere a Python da Cloud Shell, ma anche in un ambiente di sviluppo locale. Esci con ^D (Ctrl-d) e accetta l'offerta di uscire. L'output di esempio della fase ipython iniziale sarà il seguente:

$ ipython
Python 3.7.3 (default, Mar  4 2020, 23:11:43)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.13.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]:

Se IPython non è la tua preferenza, l'uso di un interprete interattivo Python standard (Cloud Shell o il tuo ambiente di sviluppo locale) è perfettamente accettabile (anche con ^D):

$ python
Python 2.7.13 (default, Sep 26 2018, 18:42:22)
[GCC 6.3.0 20170516] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 
$ python3
Python 3.7.3 (default, Mar 10 2020, 02:33:39)
[GCC 6.3.0 20170516] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

Il codelab presuppone anche che tu abbia lo strumento di installazione pip (gestore di pacchetti Python e resolver di dipendenze). Viene fornito in bundle con le versioni 2.7.9+ o 3.4+. Se hai una versione precedente di Python, consulta questa guida per le istruzioni di installazione. In base alle tue autorizzazioni, potrebbe essere necessario disporre dell'accesso sudo o come super user, ma in genere non è così. Puoi anche utilizzare esplicitamente pip2 o pip3 per eseguire pip per versioni Python specifiche.

La parte restante del codelab presuppone che tu stia utilizzando Python 3: verranno fornite istruzioni specifiche per Python 2 se differiscono in modo significativo da 3.x.

[Facoltativo] Crea e utilizza ambienti virtuali

Questa sezione è facoltativa ed è obbligatoria solo per chi deve utilizzare un ambiente virtuale per questo codelab (come indicato nella barra laterale di avviso in alto). Se sul computer è installato solo Python 3, puoi inviare questo comando per creare un virtualenv denominato my_env (puoi scegliere un altro nome, se necessario):

virtualenv my_env

Tuttavia, se utilizzi sia Python 2 sia 3 sul tuo computer, ti consigliamo di installare un virtualenv Python 3, che puoi fare con -p flag in questo modo:

virtualenv -p python3 my_env

Inserisci il virtualenv appena creato "attivando" nel seguente modo:

source my_env/bin/activate

Conferma di trovarti nell'ambiente osservando che il prompt della shell è ora preceduto dal nome dell'ambiente, ad esempio

(my_env) $ 

Ora dovresti essere in grado di pip install tutti i pacchetti richiesti, eseguire il codice all'interno di questo eivonment e così via. Un altro vantaggio è che se lo scomponi completamente, entri in una situazione in cui la tua installazione Python è danneggiata e così via, puoi soffiare via questo intero ambiente senza influire sul resto del sistema.

4. Installa la libreria client delle API di Google per Python

Questo codelab richiede l'utilizzo della libreria client delle API di Google per Python, quindi è un semplice processo di installazione oppure potresti non dover fare nulla.

In precedenza ti abbiamo consigliato di utilizzare Cloud Shell per praticità. Puoi completare l'intero tutorial da un browser web nel cloud. Un altro motivo per utilizzare Cloud Shell è che molti degli strumenti di sviluppo più diffusi e delle librerie necessarie sono già preinstallati.

*Installare le librerie client

(Facoltativo) Puoi saltare questa operazione se utilizzi Cloud Shell o un ambiente locale in cui hai già installato le librerie client. Devi eseguire questa operazione solo se stai sviluppando in locale e non hai (o non sei sicuro di averla) installata. Il modo più semplice è utilizzare pip (o pip3) per eseguire l'installazione (incluso l'aggiornamento di pip, se necessario):

pip install -U pip google-api-python-client oauth2client

Conferma installazione

Questo comando installa la libreria client e gli eventuali pacchetti da cui dipende. Che tu stia utilizzando Cloud Shell o il tuo ambiente, verifica che la libreria client sia installata importando i pacchetti necessari e conferma che non siano presenti errori di importazione (né output):

python3 -c "import googleapiclient, httplib2, oauth2client"

Se invece utilizzi Python 2 (da Cloud Shell), riceverai un avviso che ti informa che il relativo supporto è stato deprecato:

*******************************************************************************
Python 2 is deprecated. Upgrade to Python 3 as soon as possible.
See https://cloud.google.com/python/docs/python2-sunset

To suppress this warning, create an empty ~/.cloudshell/no-python-warning file.
The command will automatically proceed in  seconds or on any key.
*******************************************************************************

Ora che puoi eseguire il "test" di importazione (nessun errore/output), puoi iniziare a parlare con le API di Google.

Riepilogo

Poiché questo è un codelab intermedio, il presupposto è che tu abbia già esperienza con la creazione e utilizzando i progetti nella console. Se non hai mai utilizzato le API di Google e, nello specifico, le API di Google Workspace, prova prima il codelab introduttivo alle API di Google Workspace. Inoltre, se sai come creare (o riutilizzare) le credenziali dell'account utente (non dell'account di servizio), trascina il file client_secret.json nella directory di lavoro, salta il modulo successivo e vai ad "Abilita API di Google".

5. *Autorizzare le richieste API (autorizzazione dell'utente)

Puoi saltare questa sezione se hai già creato le credenziali di autorizzazione dell'account utente e hai familiarità con la procedura. È diversa dall'autorizzazione dell'account di servizio, la cui tecnica è diversa, quindi continua di seguito.

Introduzione all'autorizzazione (oltre ad alcune autenticazione)

Per effettuare richieste alle API, la tua applicazione deve disporre dell'autorizzazione adeguata. Autenticazione, una parola simile, descrive le credenziali di accesso: quando accedi al tuo Account Google con credenziali di accesso e password. Una volta eseguita l'autenticazione, il passaggio successivo consiste nel capire se sei, o meglio il tuo codice, autorizzato ad accedere a dati, ad esempio i file BLOB su Cloud Storage o i file personali di un utente su Google Drive.

Le API di Google supportano diversi tipi di autorizzazione, ma quello più comune per gli utenti dell'API G Suite è l'autorizzazione utente, poiché l'applicazione di esempio in questo codelab accede ai dati appartenenti agli utenti finali. Questi utenti finali devono concedere alla tua app l'autorizzazione ad accedere ai proprietari. Questo significa che il codice deve ottenere le credenziali OAuth2 dell'account utente.

Per ottenere le credenziali OAuth2 per l'autorizzazione utente, torna al gestore API e seleziona "Credenziali" scheda nel menu di navigazione sinistro:

635af008256d323.png

Una volta lì, vedrai tutte le tue credenziali in tre sezioni separate:

fd2f4133b406d572.png

Il primo riguarda le chiavi API, il secondo ID client OAuth 2.0 e gli ultimi account di servizio OAuth2. Utilizziamo quello centrale.

Creazione delle credenziali

Nella pagina Credenziali, fai clic sul pulsante + Crea credenziali in alto. Viene visualizzata una finestra di dialogo in cui puoi scegliere "ID client OAuth":

b17b663668e38787.png

Nella schermata successiva sono presenti due azioni: la configurazione della "schermata di consenso" per l'autorizzazione dell'app e scegli il tipo di applicazione:

4e0b967c9d70d262.png

Se non hai impostato una schermata per il consenso, vedrai l'avviso nella console e dovrai farlo ora. Salta questi passaggi successivi se la schermata per il consenso è già stata configurata.

Fai clic su "Configura schermata per il consenso" e seleziona "Esterno" (o "Interno" se sei un cliente G Suite):

f17e97b30d994b0c.png

Tieni presente che ai fini di questo esercizio, la scelta non è importante perché non stai pubblicando l'esempio del codelab. La maggior parte degli utenti seleziona "Esterni" a una schermata più complessa, ma devi compilare solo il campo "Nome applicazione" campo in alto:

b107ab81349bdad2.png

Al momento ti serve solo il nome di un'applicazione, quindi scegli qualcuno che rispecchi il codelab che stai facendo e fai clic su Salva.

Creazione dell'ID client OAuth (autenticazione account utente)

Ora torna alla scheda Credenziali per creare un ID client OAuth2. Qui vedrai una serie di ID client OAuth che puoi creare:

5ddd365ac0af1e34.png

Stiamo sviluppando uno strumento a riga di comando, Altro, quindi sceglilo e fai clic sul pulsante Crea. Scegli un nome ID client che rifletta l'app che stai creando o scegli semplicemente il nome predefinito, che in genere è "Altro client N".

Salvataggio delle credenziali in corso...

  1. Viene visualizzata una finestra di dialogo con le nuove credenziali. fai clic su OK per chiudere

8bec84d82cb104d7.png

  1. Torna alla pagina Credenziali, scorri verso il basso fino a "ID client OAuth2" individua e fai clic sull'icona di download f54b28417901b3aa.png all'estrema destra dell'ID client appena creato. 1b4e8d248274a338.png
  2. Si apre una finestra di dialogo per salvare un file denominato client_secret-LONG-HASH-STRING.apps.googleusercontent.com.json, probabilmente nella tua cartella Download. Ti consigliamo di accorciarlo con un nome più semplice come client_secret.json (che è quello utilizzato dall'app di esempio), quindi salvarla nella directory/cartella in cui creerai l'app di esempio in questo codelab.

Riepilogo

Ora è tutto pronto per abilitare le API di Google utilizzate in questo codelab. Inoltre, per il nome dell'applicazione nella schermata per il consenso OAuth abbiamo scelto "Demo dell'API Vision", quindi aspettati di vederla in alcuni dei prossimi screenshot.

6. Abilita le API di Google

Questo codelab utilizza quattro (4) API Google Cloud, una coppia di Google Cloud (Cloud Storage e Cloud Vision) e un'altra di Google Workspace (Google Drive e Fogli Google). Di seguito sono riportate le istruzioni generali per l'abilitazione delle API di Google. Quando sai come abilitare un'API, le altre sono simili.

Indipendentemente dall'API di Google che vuoi utilizzare nell'applicazione, queste devono essere abilitate. Le API possono essere abilitate dalla riga di comando o dalla console Cloud. Il processo di abilitazione delle API è identico, quindi una volta abilitata un'API, puoi abilitarne altre in modo simile.

Opzione 1: interfaccia a riga di comando gcloud (Cloud Shell o ambiente locale)

Sebbene l'abilitazione delle API dalla console Cloud sia più comune, alcuni sviluppatori preferiscono eseguire tutte le operazioni dalla riga di comando. Per farlo, devi cercare il "nome del servizio" di un'API. Sembra un URL: SERVICE_NAME.googleapis.com. Puoi trovarli nel grafico dei prodotti supportati oppure puoi eseguire query in modo programmatico con l'API Google Discovery.

Grazie a queste informazioni, utilizzando Cloud Shell (o il tuo ambiente di sviluppo locale in cui è installato lo strumento a riga di comando gcloud installato), puoi abilitare un'API o un servizio nel seguente modo:

gcloud services enable SERVICE_NAME.googleapis.com

Esempio 1: abilita l'API Cloud Vision

gcloud services enable vision.googleapis.com

Esempio 2: abilita la piattaforma di serverless computing Google App Engine

gcloud services enable appengine.googleapis.com

Esempio 3: abilita più API con una singola richiesta. Ad esempio, se questo codelab prevede visualizzatori che eseguono il deployment di un'app in App Engine, Cloud Functions e Cloud Run utilizzando l'API Cloud Translation, la riga di comando sarà:

gcloud services enable appengine.googleapis.com cloudfunctions.googleapis.com artifactregistry.googleapis.com run.googleapis.com translate.googleapis.com

Questo comando abilita App Engine, Cloud Functions, Cloud Run e l'API Cloud Translation. Inoltre, abilita Cloud Artifact Registry perché è qui che le immagini container devono essere registrate dal sistema Cloud Build per poter eseguire il deployment in Cloud Run.

Sono inoltre disponibili alcuni comandi per eseguire query sulle API da abilitare o su quali API sono già abilitate per il tuo progetto.

Esempio 4: query sulle API di Google disponibili per essere abilitate per il tuo progetto

gcloud services list --available --filter="name:googleapis.com"

Esempio 5: query per le API di Google abilitate per il tuo progetto

gcloud services list

Per ulteriori informazioni sui comandi riportati sopra, consulta la documentazione relativa all'attivazione e alla disattivazione dei servizi e all'elenco dei servizi.

Opzione 2: console Cloud

Puoi anche abilitare le API di Google nel gestore API. Dalla console Cloud, vai a Gestore API. In questa pagina della dashboard troverai alcune informazioni sul traffico relative alla tua app, grafici che mostrano le richieste dell'applicazione, gli errori generati dall'app e i tempi di risposta dell'app:

df4a0a5e00d29ffc.png

Sotto questi grafici, trovi un elenco delle API di Google abilitate per il tuo progetto:

5fcf10e5a05cfb97.png

Per abilitare (o disabilitare) le API, fai clic su Abilita API e servizi in alto:

eef4e5e863f4db66.png

In alternativa, vai alla barra di navigazione a sinistra e seleziona API e ServiziRaccolta:

6eda5ba145b30b97.png

In ogni caso, verrà visualizzata la pagina Libreria API:

5d4f1c8e7cf8df28.png

Inserisci il nome di un'API da cercare e visualizzare i risultati corrispondenti:

35bc4b9cf72ce9a4.png

Seleziona l'API che vuoi abilitare e fai clic sul pulsante Abilita:

9574a69ef8d9e8d2.png

Il processo di abilitazione di tutte le API è simile, indipendentemente dall'API di Google che intendi utilizzare.

Costo

Molte API di Google possono essere utilizzate senza costi; tuttavia, l'utilizzo della maggior parte dei prodotti e delle API Google Cloud comporta dei costi. Quando abiliti le API Cloud, ti potrebbe essere richiesto di creare un account di fatturazione attivo. Tuttavia, alcuni prodotti Google Cloud dispongono di un'opzione " Always Free" , che dovrai superare per sostenere i costi di fatturazione.

I nuovi utenti di Google Cloud sono idonei alla prova senza costi, che al momento costa 300 $per i primi 90 giorni. In genere, i codelab non prevedono una gran o nessuna fatturazione, quindi ti consigliamo di aspettare il momento della prova senza costi, specialmente se si tratta di un'offerta una tantum. Le quote del Livello senza costi non scadono e si applicano indipendentemente dal fatto che utilizzi o meno la prova senza costi.

Gli utenti devono fare riferimento alle informazioni sui prezzi di qualsiasi API prima di abilitarla (ad esempio, la pagina Prezzi dell'API Cloud Vision ), soprattutto indicando se è disponibile un livello senza costi e, in tal caso, di cosa si tratta. Se rimani entro i limiti giornalieri o mensili specificati in forma aggregata, non ti verrà addebitato alcun costo. I prezzi e i livelli senza costi variano a seconda delle API dei gruppi di prodotti Google. Esempi:

I vari prodotti Google vengono fatturati in modo diverso, quindi assicurati di consultare la documentazione appropriata per queste informazioni.

Riepilogo

Ora che Cloud Vision è stato abilitato, attiva le altre tre API (Google Drive, Cloud Storage, Fogli Google) nello stesso modo. Da Cloud Shell, usa gcloud services enable oppure dalla console Cloud:

  1. Torna alla libreria API
  2. Inizia una ricerca digitando alcune lettere del suo nome
  3. Selezionare l'API desiderata
  4. Attiva

Insapona, risciacqua e ripeti. Per Cloud Storage hai a disposizione diverse opzioni: scegli l'"API JSON di Google Cloud Storage". Anche l'API Cloud Storage è in attesa di un account di fatturazione attivo.

7. Passaggio 0: configura importazioni e codice di autorizzazione

Questo è l'inizio di una porzione di codice di medie dimensioni, quindi un po' di seguire pratiche agili aiuta a garantire un'infrastruttura comune, stabile e funzionante prima di affrontare l'applicazione principale. Verifica che client_secret.json sia disponibile nella directory corrente e avvia ipython e inserisci il seguente snippet di codice oppure salvalo in analyze_gsimg.py ed eseguilo dalla shell (quest'ultimo è preferibile perché continueremo ad aggiungerlo all'esempio di codice):

from __future__ import print_function

from googleapiclient import discovery, http
from httplib2 import Http
from oauth2client import file, client, tools

# process credentials for OAuth2 tokens
SCOPES = 'https://www.googleapis.com/auth/drive.readonly'
store = file.Storage('storage.json')
creds = store.get()
if not creds or creds.invalid:
    flow = client.flow_from_clientsecrets('client_secret.json', SCOPES)
    creds = tools.run_flow(flow, store)

# create API service endpoints
HTTP = creds.authorize(Http())
DRIVE  = discovery.build('drive',   'v3', http=HTTP)

Questo componente principale include blocchi di codice per le importazioni di moduli e pacchetti, l'elaborazione delle credenziali di autenticazione utente e la creazione di endpoint di servizio API. Le parti principali del codice da esaminare:

  • L'importazione della funzione print() rende questo esempio compatibile con Python 2-3 e le importazioni della libreria di Google includono tutti gli strumenti necessari per comunicare con le API di Google.
  • La variabile SCOPES rappresenta le autorizzazioni da richiedere all'utente. Per il momento ce n'è solo una: l'autorizzazione a leggere i dati dal suo Google Drive
  • Il resto del codice di elaborazione delle credenziali si legge nei token OAuth2 memorizzati nella cache, probabilmente aggiornandolo a un nuovo token di accesso con il token di aggiornamento se quello originale è scaduto.
  • Se non sono stati creati token o se il recupero di un token di accesso valido non è riuscito per un altro motivo, l'utente deve seguire il flusso OAuth2 a tre vie (3LO): creare la finestra di dialogo con le autorizzazioni richieste e chiedere all'utente di accettare. Al termine dell'operazione, l'app continua, altrimenti tools.run_flow() genera un'eccezione e l'esecuzione si interrompe.
  • Una volta che l'utente concede l'autorizzazione, viene creato un client HTTP per comunicare con il server e tutte le richieste vengono firmate con le credenziali dell'utente per motivi di sicurezza. Quindi viene creato un endpoint di servizio per l'API Google Drive (versione 3) con quel client HTTP e quindi assegnato a DRIVE.

Esecuzione dell'applicazione

La prima volta che esegui lo script, questo non avrà l'autorizzazione ad accedere ai file dell'utente sul Drive (tuo). Con l'esecuzione in pausa, l'output è simile al seguente:

$ python3 ./analyze_gsimg.py
/usr/local/lib/python3.6/site-packages/oauth2client/_helpers.py:255: UserWarning: Cannot access storage.json: No such file or directory
  warnings.warn(_MISSING_FILE_MESSAGE.format(filename))

Your browser has been opened to visit:
    https://accounts.google.com/o/oauth2/auth?client_id=LONG-STRING.apps.googleusercontent.com&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2F&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive.readonly&access_type=offline&response_type=code

If your browser is on a different machine then exit and re-run this
application with the command-line parameter

  --noauth_local_webserver

Se stai eseguendo da Cloud Shell, passa direttamente alla sezione quindi scorri indietro per esaminare le schermate pertinenti in "Dall'ambiente di sviluppo locale" quando opportuno.

Dall'ambiente di sviluppo locale

Lo script della riga di comando viene messo in pausa all'apertura di una finestra del browser. Potresti visualizzare una pagina di avviso simile alla seguente:

149241d33871a141.png

Si tratta di un problema legittimo, in quanto stai tentando di eseguire un'app che accede ai dati utente. Poiché questa è solo un'app demo e sei lo sviluppatore, spero che tu ti fidi abbastanza di te per procedere. Per capirlo meglio, mettiti nei panni dei tuoi utenti: ti viene chiesto di consentire al codice di qualcun altro di accedere ai tuoi dati. Se intendi pubblicare un'app come questa, dovrai seguire la procedura di verifica in modo che gli utenti non vedano questa schermata.

Dopo aver fatto clic sul pulsante app" Verrà visualizzata una finestra di dialogo delle autorizzazioni OAuth2 simile a quella riportata di seguito. Lavoriamo costantemente per migliorare la nostra interfaccia utente, quindi non preoccuparti se non si tratta di una corrispondenza esatta:

a122eb7468d0d34e.png

La finestra di dialogo del flusso OAuth2 riflette le autorizzazioni richieste dallo sviluppatore (tramite la variabile SCOPES). In questo caso, si tratta della possibilità di visualizzare e scaricare dal Google Drive dell'utente. Nel codice dell'applicazione, questi ambiti di autorizzazione vengono visualizzati come URI, ma sono tradotti nella lingua specificata dalle impostazioni internazionali dell'utente. In questo caso l'utente deve fornire un'autorizzazione esplicita per le autorizzazioni richieste, altrimenti viene generata un'eccezione, in modo che lo script non prosegua ulteriormente.

Potresti persino visualizzare un'altra finestra di dialogo in cui ti viene chiesto di conferma:

bf171080dcd6ec5.png

NOTA: alcuni utilizzano più browser web connessi ad account diversi, quindi la richiesta di autorizzazione potrebbe andare alla scheda/finestra del browser sbagliata e potresti dover tagliare e incollare il link relativo a questa richiesta in un browser su cui hai eseguito l'accesso con l'account corretto.

Da Cloud Shell

Da Cloud Shell, non viene visualizzata alcuna finestra del browser, lasciandoti bloccato. Crea il messaggio di diagnostica in basso rivolto a te:

If your browser is on a different machine then exit and re-run this
application with the command-line parameter

  --noauth_local_webserver

Devi premere ^C (Ctrl-C o altri tasti per interrompere l'esecuzione dello script) ed eseguirlo dalla shell con il flag aggiuntivo. Se lo esegui in questo modo, verrà visualizzato invece il seguente output:

$ python3 analyze_gsimg.py --noauth_local_webserver
/usr/local/lib/python3.7/site-packages/oauth2client/_helpers.py:255: UserWarning: Cannot access storage.json: No such file or directory
  warnings.warn(_MISSING_FILE_MESSAGE.format(filename))

Go to the following link in your browser:

    https://accounts.google.com/o/oauth2/auth?client_id=LONG-STRING.apps.googleusercontent.com&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive.readonly&access_type=offline&response_type=code

Enter verification code:

(L'avviso verrà ignorato perché sappiamo che storage.json non è stato ancora creato e) Seguendo le istruzioni in un'altra scheda del browser con quell'URL, avrai un'esperienza quasi identica a quella descritta sopra per gli ambienti di sviluppo locali (vedi gli screenshot qui sopra). Alla fine c'è un'ultima schermata con il codice di verifica da inserire in Cloud Shell:

40a567cda0f31cc9.png

Copia e incolla questo codice nella finestra del terminale.

Riepilogo

A parte "Authentication successful", non prevedi alcun output aggiuntivo. Ricorda che questa è solo la configurazione... non hai ancora fatto nulla. Ciò che hai fatto è iniziare con successo il tuo percorso verso qualcosa che ha maggiori probabilità di essere eseguito correttamente la prima volta. La parte migliore è che ti è stata richiesta l'autorizzazione una sola volta; tutte le esecuzioni successive la ignorano perché le tue autorizzazioni sono state memorizzate nella cache. Ora facciamo in modo che il codice esegua un lavoro reale generando un output effettivo.

Risoluzione dei problemi

Se visualizzi un errore anziché nessun output, la causa potrebbe essere una o più cause, ad esempio questa:

8. Passaggio 1: scarica l'immagine da Google Drive

Nel passaggio precedente, ti abbiamo consigliato di creare il codice come analyze_gsimg.py e modificarlo da lì. È anche possibile semplicemente tagliare e incollare tutto direttamente nella shell di iPython o Python standard, tuttavia è più complicato perché continueremo a creare l'app pezzo per pezzo.

Supponiamo che la tua app sia stata autorizzata e che l'endpoint di servizio API sia stato creato. Nel codice è rappresentato dalla variabile DRIVE. Ora troviamo un file immagine su Google Drive e

impostalo su una variabile denominata NAME. Inserisci questo più la seguente funzione drive_get_img() appena sotto il codice del Passaggio 0:

FILE = 'YOUR_IMG_ON_DRIVE'  # fill-in with name of your Drive file

def drive_get_img(fname):
    'download file from Drive and return file info & binary if found'

    # search for file on Google Drive
    rsp = DRIVE.files().list(q="name='%s'" % fname,
            fields='files(id,name,mimeType,modifiedTime)'
    ).execute().get('files', [])

    # download binary & return file info if found, else return None
    if rsp:
        target = rsp[0]  # use first matching file
        fileId = target['id']
        fname = target['name']
        mtype = target['mimeType']
        binary = DRIVE.files().get_media(fileId=fileId).execute()
        return fname, mtype, target['modifiedTime'], binary

La raccolta files() di Drive ha un metodo list() che esegue una query (il parametro q) per il file specificato. Il parametro fields viene utilizzato per specificare i valori restituiti che ti interessano: perché dovresti preoccuparsi di riavere tutto e rallentare le cose se non ti interessano gli altri valori? Se non hai mai utilizzato le maschere di campo per filtrare i valori restituiti dall'API, consulta questo post del blog e video. Altrimenti, esegui la query e recupera l'attributo files restituito, per impostazione predefinita un array di elenchi vuoto se non ci sono corrispondenze.

Se non ci sono risultati, il resto della funzione viene ignorato e viene restituito None (implicitamente). Altrimenti, recupera la prima risposta corrispondente (rsp[0]), restituisce il nome file, il tipo MIME, il timestamp dell'ultima modifica e, infine, il relativo payload binario, recuperato dalla funzione get_media() (tramite l'ID file), sempre nella raccolta files(). I nomi dei metodi potrebbero differire leggermente con le librerie client di altri linguaggi.

La parte finale è la parte "principale" che gestisce l'intera applicazione:

if __name__ == '__main__':
    # download img file & info from Drive
    rsp = drive_get_img(FILE)
    if rsp:
        fname, mtype, ftime, data = rsp
        print('Downloaded %r (%s, %s, size: %d)' % (fname, mtype, ftime, len(data)))
    else:
        print('ERROR: Cannot download %r from Drive' % fname)

Se supponiamo un'immagine denominata section-work-card-img_2x.jpg su Drive e impostata su FILE, dopo l'esecuzione dello script dovresti vedere un output che conferma che è stato possibile leggere il file da Drive (ma non essere salvato sul computer):

$ python3 analyze_gsimg.py
Downloaded 'section-work-card-img_2x.jpg' (image/jpeg, 2020-02-27T09:27:22.095Z, size: 27781)

Risoluzione dei problemi

Se non ottieni l'output corretto come in precedenza, la causa potrebbe essere una o più cause, forse questa:

Riepilogo

In questa sezione hai appreso come (in 2 chiamate API separate) connettersi all'API Drive eseguendo query su un file specifico e scaricandolo. Caso d'uso aziendale: archiviare i dati di Drive e magari analizzarli, ad esempio con gli strumenti Google Cloud. Il codice dell'app in questa fase deve corrispondere a quello presente nel repository all'indirizzo step1-drive/analyze_gsimg.py.

Leggi ulteriori informazioni sul download di file su Google Drive qui o consulta questo post del blog e video. Questa parte del codelab è quasi identica all'intera introduzione al codelab delle API Google Workspace: anziché scaricare un file, mostra i primi 100 file/cartelle sul Google Drive di un utente e utilizza un ambito più restrittivo.

9. Passaggio 2: archivia il file in Cloud Storage

Il passaggio successivo consiste nell'aggiungere il supporto per Google Cloud Storage. Per farlo dobbiamo importare un altro pacchetto Python, io. Assicurati che la sezione superiore delle importazioni ora abbia il seguente aspetto:

from __future__ import print_function                   
import io

Oltre al nome file di Drive, abbiamo bisogno di alcune informazioni sul luogo in cui archiviare il file in Cloud Storage, in particolare il nome del "bucket" lo inserirai in qualsiasi "cartella principale" prefissi. Altre informazioni a riguardo a breve:

FILE = 'YOUR_IMG_ON_DRIVE'
BUCKET = 'YOUR_BUCKET_NAME'
PARENT = ''     # YOUR IMG FILE PREFIX                  

Una parola sui bucket: Cloud Storage offre archiviazione BLOB amorfo. Quando carica i file lì, non comprende il concetto di tipo di file, estensioni e così via, come fa Google Drive. Sono solo "blob" in Cloud Storage. Inoltre, in Cloud Storage non esiste il concetto di cartelle o sottodirectory.

Sì, i nomi file possono contenere barre (/) per rappresentare l'astrazione di più sottocartelle, ma in fin dei conti tutti i BLOB vengono inseriti in un bucket e i "/" sono solo caratteri nei nomi file. Per saperne di più, consulta la pagina delle convenzioni di denominazione di bucket e oggetti.

Il passaggio 1 riportato sopra richiedeva l'ambito di sola lettura di Drive. Per il momento era tutto quello di cui avevi bisogno. Ora è richiesta l'autorizzazione di caricamento (lettura/scrittura) su Cloud Storage. Cambia SCOPES da una singola variabile di stringa a un array (tupla Python [o elenco]) di ambiti di autorizzazione in modo che abbia il seguente aspetto:

SCOPES = (
    'https://www.googleapis.com/auth/drive.readonly',
    'https://www.googleapis.com/auth/devstorage.full_control',
)                  

Ora crea un endpoint di servizio per Cloud Storage proprio sotto quello di Drive. Tieni presente che abbiamo leggermente modificato la chiamata in modo da riutilizzare lo stesso oggetto client HTTP, in quanto non è necessario crearne uno nuovo quando può essere una risorsa condivisa.

# create API service endpoints
HTTP = creds.authorize(Http())
DRIVE  = discovery.build('drive',   'v3', http=HTTP)
GCS    = discovery.build('storage', 'v1', http=HTTP)                  

Ora aggiungi questa funzione (dopo il giorno drive_get_img()) che viene caricata in Cloud Storage:

def gcs_blob_upload(fname, bucket, media, mimetype):
    'upload an object to a Google Cloud Storage bucket'

    # build blob metadata and upload via GCS API
    body = {'name': fname, 'uploadType': 'multipart', 'contentType': mimetype}
    return GCS.objects().insert(bucket=bucket, body=body,
            media_body=http.MediaIoBaseUpload(io.BytesIO(media), mimetype),
            fields='bucket,name').execute()

La chiamata objects.().insert() richiede il nome del bucket, i metadati del file e il blob binario stesso. Per filtrare i valori restituiti, la variabile fields richiede solo i nomi del bucket e degli oggetti restituiti dall'API. Per saperne di più su queste maschere di campo nelle richieste di lettura delle API, consulta questo post e video.

Ora integra l'utilizzo di gcs_blob_upload() nell'applicazione principale:

        # upload file to GCS
        gcsname = '%s/%s'% (PARENT, fname)
        rsp = gcs_blob_upload(gcsname, BUCKET, data, mtype)
        if rsp:
            print('Uploaded %r to GCS bucket %r' % (rsp['name'], rsp['bucket']))
        else:
            print('ERROR: Cannot upload %r to Cloud Storage' % gcsname)

La variabile gcsname unisce qualsiasi "sottodirectory principale" nome/i aggiunto con il nome file stesso e, quando è preceduto dal nome del bucket, dà l'impressione che stai archiviando il file in "/bucket/parent.../filename". Inserisci questo blocco subito dopo la prima funzione print() appena sopra la clausola else in modo che l'intero elemento "main" ha il seguente aspetto:

if __name__ == '__main__':
    # download img file & info from Drive
    rsp = drive_get_img(FILE)
    if rsp:
        fname, mtype, ftime, data = rsp
        print('Downloaded %r (%s, %s, size: %d)' % (fname, mtype, ftime, len(data)))

        # upload file to GCS
        gcsname = '%s/%s'% (PARENT, fname)
        rsp = gcs_blob_upload(gcsname, BUCKET, data, mtype)
        if rsp:
            print('Uploaded %r to GCS bucket %r' % (rsp['name'], rsp['bucket']))
        else:
            print('ERROR: Cannot upload %r to Cloud Storage' % gcsname)
    else:
        print('ERROR: Cannot download %r from Drive' % fname)

Supponiamo di specificare un bucket denominato "vision-demo" con "analyzed_imgs" come "sottodirectory principale". Dopo aver impostato le variabili ed eseguito nuovamente lo script, section-work-card-img_2x.jpg verrà scaricato da Drive e poi caricato in Cloud Storage, giusto? NO!

$ python3 analyze_gsimg.py 
Downloaded 'section-work-card-img_2x.jpg' (image/jpeg, 2020-02-27T09:27:22.095Z, size: 27781)
Traceback (most recent call last):
  File "analyze_gsimg.py", line 85, in <module>
    io.BytesIO(data), mimetype=mtype), mtype)
  File "analyze_gsimg.py", line 72, in gcs_blob_upload
    media_body=media, fields='bucket,name').execute()
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/googleapiclient/_helpers.py", line 134, in positional_wrapper
    return wrapped(*args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/googleapiclient/http.py", line 898, in execute
    raise HttpError(resp, content, uri=self.uri)
googleapiclient.errors.HttpError: <HttpError 403 when requesting https://storage.googleapis.com/upload/storage/v1/b/PROJECT_ID/o?fields=bucket%2Cname&alt=json&uploadType=multipart returned "Insufficient Permission">

Guarda attentamente, mentre il download di Drive è riuscito, il caricamento su Cloud Storage non è riuscito. Perché?

Il motivo è che quando abbiamo autorizzato questa applicazione inizialmente per il Passaggio 1, abbiamo autorizzato solo l'accesso di sola lettura a Google Drive. Anche se abbiamo aggiunto l'ambito di lettura/scrittura per Cloud Storage, non abbiamo mai chiesto all'utente di autorizzare questo accesso. Affinché funzioni, dobbiamo eliminare il file storage.json, in cui manca questo ambito, ed eseguirlo di nuovo.

Dopo la nuova autorizzazione (conferma l'operazione cercando all'interno di storage.json e visualizzando entrambi gli ambiti), l'output sarà quello previsto:

$ python3 analyze_gsimg.py

    . . .

Authentication successful.
Downloaded 'section-work-card-img_2x.jpg' (image/jpeg, 2020-02-27T09:27:22.095Z, size: 27781)
Uploaded 'analyzed_imgs/section-work-card-img_2x.jpg' to GCS bucket 'vision-demo'

Riepilogo

Si tratta di un aspetto importante, che mostra, con relativamente poche righe di codice, come trasferire file tra entrambi i sistemi di archiviazione basati su cloud. Il caso d'uso aziendale in questo caso è eseguire il backup di una risorsa potenzialmente vincolata a un ambiente più freddo, più economico, come abbiamo detto prima. Cloud Storage offre classi di archiviazione diverse a seconda che l'accesso ai dati sia regolare, mensile, trimestrale o annuale.

Naturalmente, gli sviluppatori di tanto in tanto ci chiedono perché esistono sia Google Drive che Cloud Storage. Dopo tutto, non sono entrambi i file di archiviazione sul cloud? È per questo che abbiamo realizzato questo video. Il codice in questa fase deve corrispondere a quello presente nel repository all'indirizzo step2-gcs/analyze_gsimg.py.

10. Passaggio 3: analizza con Cloud Vision

Anche se ora sappiamo che è possibile spostare dati tra Google Cloud e Google Workspace, non abbiamo ancora fatto alcuna analisi, quindi è il momento di inviare l'immagine a Cloud Vision per l'annotazione delle etichette, ovvero il rilevamento di oggetti. Per farlo, dobbiamo codificare i dati in Base64, il che significa un altro modulo Python, base64. Assicurati che la sezione di importazione principale ora abbia il seguente aspetto:

from __future__ import print_function
import base64
import io

Per impostazione predefinita, l'API Vision restituisce tutte le etichette trovate. Per garantire la coerenza, richiediamo solo i primi 5 (che ovviamente possono essere modificati dall'utente). Per farlo, utilizzeremo una variabile costante TOP: lo aggiungiamo sotto tutte le altre costanti:

FILE = 'YOUR_IMG_ON_DRIVE'
BUCKET = 'YOUR_BUCKET_NAME'
PARENT = ''   # YOUR IMG FILE PREFIX 
TOP = 5       # TOP # of VISION LABELS TO SAVE                 

Come per i passaggi precedenti, abbiamo bisogno di un altro ambito delle autorizzazioni, questa volta per l'API Vision. Aggiorna SCOPES con la sua stringa:

SCOPES = (
    'https://www.googleapis.com/auth/drive.readonly',
    'https://www.googleapis.com/auth/devstorage.full_control',
    'https://www.googleapis.com/auth/cloud-vision',
)                  

Ora crea un endpoint di servizio per Cloud Vision in modo che sia allineato agli altri in questo modo:

# create API service endpoints
HTTP = creds.authorize(Http())
DRIVE  = discovery.build('drive',   'v3', http=HTTP)
GCS    = discovery.build('storage', 'v1', http=HTTP)
VISION = discovery.build('vision',  'v1', http=HTTP)

Ora aggiungi questa funzione che invia il payload dell'immagine a Cloud Vision:

def vision_label_img(img, top):
    'send image to Vision API for label annotation'

    # build image metadata and call Vision API to process
    body = {'requests': [{
                'image':     {'content': img},
                'features': [{'type': 'LABEL_DETECTION', 'maxResults': top}],
    }]}
    rsp = VISION.images().annotate(body=body).execute().get('responses', [{}])[0]

    # return top labels for image as CSV for Sheet (row)
    if 'labelAnnotations' in rsp:
        return ', '.join('(%.2f%%) %s' % (
                label['score']*100., label['description']) \
                for label in rsp['labelAnnotations'])

La chiamata images().annotate() richiede i dati e le funzionalità API desiderate. Anche il limite delle prime 5 etichette fa parte del payload (ma è completamente facoltativo). Se la chiamata ha esito positivo, il payload restituisce le prime 5 etichette degli oggetti più un punteggio di confidenza che un oggetto è presente nell'immagine. Se non ricevi alcuna risposta, assegna un dizionario Python vuoto in modo che la seguente istruzione if non presenti errori. Questa funzione semplicemente raccoglie i dati in una stringa CSV per l'utilizzo finale nel nostro report.

Queste 5 righe che chiamano vision_label_img() devono essere inserite subito dopo il corretto caricamento in Cloud Storage:

            # process w/Vision
            rsp = vision_label_img(base64.b64encode(data).decode('utf-8'), TOP)
            if rsp:
                print('Top %d labels from Vision API: %s' % (TOP, rsp))
            else:
                print('ERROR: Vision API cannot analyze %r' % fname)

Con questa aggiunta, l'intero elemento trainante principale dovrebbe avere il seguente aspetto:

if __name__ == '__main__':
    # download img file & info from Drive
    rsp = drive_get_img(FILE)
    if rsp:
        fname, mtype, ftime, data = rsp
        print('Downloaded %r (%s, %s, size: %d)' % (fname, mtype, ftime, len(data)))

        # upload file to GCS
        gcsname = '%s/%s'% (PARENT, fname)
        rsp = gcs_blob_upload(gcsname, BUCKET, data, mtype)
        if rsp:
            print('Uploaded %r to GCS bucket %r' % (rsp['name'], rsp['bucket']))

            # process w/Vision
            rsp = vision_label_img(base64.b64encode(data).decode('utf-8'), TOP)
            if rsp:
                print('Top %d labels from Vision API: %s' % (TOP, rsp))
            else:
                print('ERROR: Vision API cannot analyze %r' % fname)
        else:
            print('ERROR: Cannot upload %r to Cloud Storage' % gcsname)
    else:
        print('ERROR: Cannot download %r from Drive' % fname)

L'eliminazione di storage.json per aggiornare gli ambiti e la nuova esecuzione dell'applicazione aggiornata dovrebbe generare un output simile al seguente, con un'indicazione dell'aggiunta dell'analisi di Cloud Vision:

$ python3 analyze_gsimg.py

    . . .

Authentication successful.
Downloaded 'section-work-card-img_2x.jpg' (image/jpeg, 2020-02-27T09:27:22.095Z, size: 27781)
Uploaded 'analyzed_imgs/section-work-card-img_2x.jpg' to GCS bucket 'vision-demo'
Top 5 labels from Vision API: (89.94%) Sitting, (86.09%) Interior design, (82.08%) Furniture, (81.52%) Table, (80.85%) Room

Riepilogo

Non tutti dispongono delle competenze di machine learning per creare e addestrare i propri modelli di ML per l'analisi dei dati. Il team di Google Cloud ha reso disponibili alcuni dei modelli preaddestrati di Google per l'uso generale e li ha inseriti dietro le API, contribuendo a democratizzare l'IA e ML per tutti.

Se sei uno sviluppatore e puoi chiamare un'API, puoi utilizzare il machine learning. Cloud Vision è solo uno dei servizi API con cui puoi analizzare i dati. Scopri di più sugli altri qui. Il codice ora dovrebbe corrispondere a quello presente nel repository all'indirizzo step3-vision/analyze_gsimg.py.

11. Passaggio 4: genera un report con Fogli Google

A questo punto, sei stato in grado di archiviare i dati aziendali e analizzarli, ma ciò che manca è un riassunto di questo lavoro. Organizziamo tutti i risultati in un unico report che puoi consegnare al tuo capo. Che cos'è più presentabile di un foglio di lavoro per la gestione?

Non sono necessarie importazioni aggiuntive per l'API Fogli Google e l'unica nuova informazione necessaria è l'ID file di un foglio di lavoro esistente già formattato e in attesa di una nuova riga di dati, quindi la costante SHEET. Ti consigliamo di creare un nuovo foglio di lavoro simile al seguente:

4def78583d05300.png

L'URL del foglio di lavoro sarà il seguente: https://docs.google.com/spreadsheets/d/FILE_ID/edit. Afferra questo FILE_ID e assegnalo come stringa a SHEET.

Abbiamo anche inserito una piccola funzione denominata k_ize() che converte i byte in kilobyte, definendola come lambda in Python, dato che è una semplice riga di una riga. Entrambe queste, integrate con le altre costanti, hanno il seguente aspetto:

k_ize =  lambda b: '%6.2fK' % (b/1000.)  # bytes to kBs
FILE = 'YOUR_IMG_ON_DRIVE'
BUCKET = 'YOUR_BUCKET_NAME'
PARENT = ''     # YOUR IMG FILE PREFIX
SHEET = 'YOUR_SHEET_ID'
TOP = 5       # TOP # of VISION LABELS TO SAVE                 

Come nei passaggi precedenti, abbiamo bisogno di un altro ambito delle autorizzazioni, questa volta lettura e scrittura per l'API Fogli. Ora SCOPES ha tutte e quattro le funzionalità necessarie:

SCOPES = (
    'https://www.googleapis.com/auth/drive.readonly',
    'https://www.googleapis.com/auth/devstorage.full_control',
    'https://www.googleapis.com/auth/cloud-vision',
    'https://www.googleapis.com/auth/spreadsheets',
)                  

Ora crea un endpoint di servizio per Fogli Google accanto agli altri, in modo che abbia questo aspetto:

# create API service endpoints
HTTP = creds.authorize(Http())
DRIVE  = discovery.build('drive',   'v3', http=HTTP)
GCS    = discovery.build('storage', 'v1', http=HTTP)
VISION = discovery.build('vision',  'v1', http=HTTP)
SHEETS = discovery.build('sheets',  'v4', http=HTTP)

La funzionalità di sheet_append_row() è semplice: prendi una riga di dati e l'ID di un foglio e aggiungi la riga al foglio in questione:

def sheet_append_row(sheet, row):
    'append row to a Google Sheet, return #cells added'

    # call Sheets API to write row to Sheet (via its ID)
    rsp = SHEETS.spreadsheets().values().append(
            spreadsheetId=sheet, range='Sheet1',
            valueInputOption='USER_ENTERED', body={'values': [row]}
    ).execute()
    if rsp:
        return rsp.get('updates').get('updatedCells')

La chiamata spreadsheets().values().append() richiede l'ID file del foglio, un intervallo di celle, la modalità di inserimento dei dati e i dati stessi. L'ID file è semplice, l'intervallo di celle è fornito in notazione A1. Un intervallo di "Sheet1" indica l'intero foglio, che indica all'API di aggiungere la riga dopo tutti i dati nel foglio. Sono disponibili due opzioni per come aggiungere i dati al foglio: "RAW" (inserisci i dati della stringa testualmente) o "USER_ENTERED" (scrivi i dati come se li avessi inseriti sulla tastiera con l'applicazione Fogli Google, mantenendo eventuali funzionalità di formattazione delle celle).

Se la chiamata ha esito positivo, il valore restituito non ha nulla di super utile, quindi abbiamo optato per ottenere l'aggiornamento del numero di celle dalla richiesta API. Di seguito è riportato il codice che chiama questa funzione:

                # push results to Sheet, get cells-saved count
                fsize = k_ize(len(data))
                row = [PARENT,
                        '=HYPERLINK("storage.cloud.google.com/%s/%s", "%s")' % (
                        BUCKET, gcsname, fname), mtype, ftime, fsize, rsp
                ]
                rsp = sheet_append_row(SHEET, row)
                if rsp:
                    print('Updated %d cells in Google Sheet' % rsp)
                else:
                    print('ERROR: Cannot write row to Google Sheets')

Il foglio Google contiene colonne che rappresentano dati, ad esempio una "sottodirectory" principale la posizione del file archiviato in Cloud Storage (bucket + nome file), il tipo MIME del file, le dimensioni del file (originariamente in byte, ma convertiti in kilobyte con k_ize()) e la stringa delle etichette di Cloud Vision. Tieni inoltre presente che la posizione archiviata è un link ipertestuale su cui il tuo manager può fare clic per confermare che il backup è stato eseguito in sicurezza.

Aggiungendo il blocco di codice riportato sopra, subito dopo aver visualizzato i risultati di Cloud Vision, la parte principale che guida l'app è ora completa, anche se strutturalmente un po' complessa:

if __name__ == '__main__':
    # download img file & info from Drive
    rsp = drive_get_img(FILE)
    if rsp:
        fname, mtype, ftime, data = rsp
        print('Downloaded %r (%s, %s, size: %d)' % (fname, mtype, ftime, len(data)))

        # upload file to GCS
        gcsname = '%s/%s'% (PARENT, fname)
        rsp = gcs_blob_upload(gcsname, BUCKET, data, mtype)
        if rsp:
            print('Uploaded %r to GCS bucket %r' % (rsp['name'], rsp['bucket']))

            # process w/Vision
            rsp = vision_label_img(base64.b64encode(data).decode('utf-8'))
            if rsp:
                print('Top %d labels from Vision API: %s' % (TOP, rsp))

                # push results to Sheet, get cells-saved count
                fsize = k_ize(len(data))
                row = [PARENT,
                        '=HYPERLINK("storage.cloud.google.com/%s/%s", "%s")' % (
                        BUCKET, gcsname, fname), mtype, ftime, fsize, rsp
                ]
                rsp = sheet_append_row(SHEET, row)
                if rsp:
                    print('Updated %d cells in Google Sheet' % rsp)
                else:
                    print('ERROR: Cannot write row to Google Sheets')
            else:
                print('ERROR: Vision API cannot analyze %r' % fname)
        else:
            print('ERROR: Cannot upload %r to Cloud Storage' % gcsname)
    else:
        print('ERROR: Cannot download %r from Drive' % fname)

L'eliminazione di storage.json un'ultima volta e la nuova esecuzione dell'applicazione aggiornata dovrebbe generare un output simile al seguente, con un'indicazione dell'aggiunta dell'analisi di Cloud Vision:

$ python3 analyze_gsimg.py

    . . .

Authentication successful.
Downloaded 'section-work-card-img_2x.jpg' (image/jpeg, 2020-02-27T09:27:22.095Z, size: 27781)
Uploaded 'analyzed_imgs/section-work-card-img_2x.jpg' to GCS bucket 'vision-demo'
Top 5 labels from Vision API: (89.94%) Sitting, (86.09%) Interior design, (82.08%) Furniture, (81.52%) Table, (80.85%) Room
Updated 6 cells in Google Sheet

La riga di output aggiuntiva, sebbene utile, viene visualizzata meglio dando un'occhiata al foglio Google aggiornato, con l'ultima riga (riga 7 dell'esempio sotto) aggiunta al set di dati esistente prima dell'ultima riga:

b53a5bc944734652.png

Riepilogo

Nei primi 3 passaggi di questo tutorial, hai effettuato la connessione alle API Google Workspace e Google Cloud per spostare i dati e analizzarli, il che rappresenta l'80% di tutto il lavoro. In fin dei conti, però, nulla di tutto ciò se non puoi presentare alla gestione tutto ciò che hai fatto. Per visualizzare meglio i risultati, riassumere tutti i risultati in un report generato parla molto.

Per migliorare ulteriormente l'utilità dell'analisi, oltre a scrivere i risultati in un foglio di lavoro, un possibile miglioramento potrebbe essere l'indicizzazione di queste 5 etichette principali per ogni immagine in modo da poter creare un database interno che consenta ai dipendenti autorizzati di eseguire query sulle immagini da parte del team di ricerca, ma lasciamo tutto questo come un esercizio per i lettori.

Per ora, i risultati sono in un foglio e sono accessibili alla gestione. Il codice dell'app in questa fase deve corrispondere a quello presente nel repository all'indirizzo step4-sheets/analyze_gsimg.py. Il passaggio finale consiste nel ripulire il codice e convertirlo in uno script utilizzabile.

12. *Ultimo passaggio: refactoring

(Facoltativo) È bello avere un'app funzionante, ma possiamo migliorarla? Sì, soprattutto l'applicazione principale, che sembra essere un disastro. Inseriamo questa funzione nella sua funzione e la mettiamo in pratica consentendo l'input dell'utente piuttosto che una costante fissa. Lo faremo nel modulo argparse. Inoltre, apriamo una scheda del browser web per visualizzare il foglio una volta che abbiamo scritto la nostra riga di dati. Questo è possibile con il modulo webbrowser. Intreccia queste importazioni con le altre in modo che le importazioni principali abbiano il seguente aspetto:

from __future__ import print_function
import argparse
import base64
import io
import webbrowser

Per poter utilizzare questo codice in altre applicazioni, è necessario poter eliminare l'output, quindi aggiungiamo un flag DEBUG a questo scopo, aggiungendo questa riga alla fine della sezione delle costanti in alto:

DEBUG = False

Ora parliamo del corpo principale. Durante la creazione dell'anteprima, dovresti aver iniziato a sentirti "a disagio" man mano che il nostro codice aggiunge un ulteriore livello di nidificazione a ogni servizio aggiunto. Se ti sei sentito così, ci sei anche tu, perché ciò aumenta la complessità del codice, come descritto in questo post del blog di Google Testing.

Seguendo questa best practice, riorganizzamo la parte principale dell'app in una funzione e return in ogni "punto di interruzione" invece della nidificazione (restituisce None se un passaggio non riesce e True se tutti i passaggi hanno esito positivo):

def main(fname, bucket, sheet_id, folder, top, debug):
    '"main()" drives process from image download through report generation'

    # download img file & info from Drive
    rsp = drive_get_img(fname)
    if not rsp:
        return
    fname, mtype, ftime, data = rsp
    if debug:
        print('Downloaded %r (%s, %s, size: %d)' % (fname, mtype, ftime, len(data)))

    # upload file to GCS
    gcsname = '%s/%s'% (folder, fname)
    rsp = gcs_blob_upload(gcsname, bucket, data, mtype)
    if not rsp:
        return
    if debug:
        print('Uploaded %r to GCS bucket %r' % (rsp['name'], rsp['bucket']))

    # process w/Vision
    rsp = vision_label_img(base64.b64encode(data).decode('utf-8'))
    if not rsp:
        return
    if debug:
        print('Top %d labels from Vision API: %s' % (top, rsp))

    # push results to Sheet, get cells-saved count
    fsize = k_ize(len(data))
    row = [folder,
            '=HYPERLINK("storage.cloud.google.com/%s/%s", "%s")' % (
            bucket, gcsname, fname), mtype, ftime, fsize, rsp
    ]
    rsp = sheet_append_row(sheet_id, row)
    if not rsp:
        return
    if debug:
        print('Added %d cells to Google Sheet' % rsp)
    return True

È più ordinato e lineare, lasciando così la sensazione della catena if-else ricorsiva e riducendo la complessità del codice come descritto sopra. L'ultimo pezzo del puzzle è creare un'immagine "reale" driver principale, consentendo la personalizzazione da parte dell'utente e riducendo al minimo l'output (se non lo desideri):

if __name__ == '__main__':
    # args: [-hv] [-i imgfile] [-b bucket] [-f folder] [-s Sheet ID] [-t top labels]
    parser = argparse.ArgumentParser()
    parser.add_argument("-i", "--imgfile", action="store_true",
            default=FILE, help="image file filename")
    parser.add_argument("-b", "--bucket_id", action="store_true",
            default=BUCKET, help="Google Cloud Storage bucket name")
    parser.add_argument("-f", "--folder", action="store_true",
            default=PARENT, help="Google Cloud Storage image folder")
    parser.add_argument("-s", "--sheet_id", action="store_true",
            default=SHEET, help="Google Sheet Drive file ID (44-char str)")
    parser.add_argument("-t", "--viz_top", action="store_true",
            default=TOP, help="return top N (default %d) Vision API labels" % TOP)
    parser.add_argument("-v", "--verbose", action="store_true",
            default=DEBUG, help="verbose display output")
    args = parser.parse_args()

    print('Processing file %r... please wait' % args.imgfile)
    rsp = main(args.imgfile, args.bucket_id,
            args.sheet_id, args.folder, args.viz_top, args.verbose)
    if rsp:
        sheet_url = 'https://docs.google.com/spreadsheets/d/%s/edit' % args.sheet_id
        print('DONE: opening web browser to it, or see %s' % sheet_url)
        webbrowser.open(sheet_url, new=1, autoraise=True)
    else:
        print('ERROR: could not process %r' % args.imgfile)

Se tutti i passaggi hanno esito positivo, lo script avvia un browser web sul foglio di lavoro specificato in cui è stata aggiunta la nuova riga di dati.

Riepilogo

Non è necessario eliminare storage.json perché non sono state apportate modifiche all'ambito. Se esegui nuovamente l'applicazione aggiornata, vedrai una nuova finestra del browser aperta nel foglio modificato, meno righe di output e l'emissione dell'opzione -h mostra agli utenti le opzioni a loro disposizione, tra cui -v per ripristinare le righe di output ora soppresse viste in precedenza:

$ python3 analyze_gsimg.py
Processing file 'section-work-card-img_2x.jpg'... please wait
DONE: opening web browser to it, or see https://docs.google.com/spreadsheets/d/SHEET_ID/edit

$ python3 analyze_gsimg.py -h
usage: analyze_gsimg.py [-h] [-i] [-t] [-f] [-b] [-s] [-v]

optional arguments:
  -h, --help       show this help message and exit
  -i, --imgfile    image file filename
  -t, --viz_top    return top N (default 5) Vision API labels
  -f, --folder     Google Cloud Storage image folder
  -b, --bucket_id  Google Cloud Storage bucket name
  -s, --sheet_id   Google Sheet Drive file ID (44-char str)
  -v, --verbose    verbose display output

Le altre opzioni consentono agli utenti di scegliere nomi di file di Drive diversi, "Sottodirectory" di Cloud Storage e nomi dei bucket, top "N" da Cloud Vision e ID file dei fogli di lavoro (Fogli). Con questi ultimi aggiornamenti, la versione finale del codice dovrebbe ora corrispondere a ciò che si trova nel repository all'indirizzo final/analyze_gsimg.py e qui nella sua interezza:

'''
analyze_gsimg.py - analyze Google Workspace image processing workflow

Download image from Google Drive, archive to Google Cloud Storage, send
to Google Cloud Vision for processing, add results row to Google Sheet.
'''

from __future__ import print_function
import argparse
import base64
import io
import webbrowser

from googleapiclient import discovery, http
from httplib2 import Http
from oauth2client import file, client, tools

k_ize = lambda b: '%6.2fK' % (b/1000.) # bytes to kBs
FILE = 'YOUR_IMG_ON_DRIVE'
BUCKET = 'YOUR_BUCKET_NAME'
PARENT = ''     # YOUR IMG FILE PREFIX
SHEET = 'YOUR_SHEET_ID'
TOP = 5       # TOP # of VISION LABELS TO SAVE
DEBUG = False

# process credentials for OAuth2 tokens
SCOPES = (
    'https://www.googleapis.com/auth/drive.readonly',
    'https://www.googleapis.com/auth/devstorage.full_control',
    'https://www.googleapis.com/auth/cloud-vision',
    'https://www.googleapis.com/auth/spreadsheets',
)
store = file.Storage('storage.json')
creds = store.get()
if not creds or creds.invalid:
    flow = client.flow_from_clientsecrets('client_secret.json', SCOPES)
    creds = tools.run_flow(flow, store)

# create API service endpoints
HTTP = creds.authorize(Http())
DRIVE  = discovery.build('drive',   'v3', http=HTTP)
GCS    = discovery.build('storage', 'v1', http=HTTP)
VISION = discovery.build('vision',  'v1', http=HTTP)
SHEETS = discovery.build('sheets',  'v4', http=HTTP)


def drive_get_img(fname):
    'download file from Drive and return file info & binary if found'

    # search for file on Google Drive
    rsp = DRIVE.files().list(q="name='%s'" % fname,
            fields='files(id,name,mimeType,modifiedTime)'
    ).execute().get('files', [])

    # download binary & return file info if found, else return None
    if rsp:
        target = rsp[0]  # use first matching file
        fileId = target['id']
        fname = target['name']
        mtype = target['mimeType']
        binary = DRIVE.files().get_media(fileId=fileId).execute()
        return fname, mtype, target['modifiedTime'], binary


def gcs_blob_upload(fname, bucket, media, mimetype):
    'upload an object to a Google Cloud Storage bucket'

    # build blob metadata and upload via GCS API
    body = {'name': fname, 'uploadType': 'multipart', 'contentType': mimetype}
    return GCS.objects().insert(bucket=bucket, body=body,
            media_body=http.MediaIoBaseUpload(io.BytesIO(media), mimetype),
            fields='bucket,name').execute()


def vision_label_img(img, top):
    'send image to Vision API for label annotation'

    # build image metadata and call Vision API to process
    body = {'requests': [{
                'image':     {'content': img},
                'features': [{'type': 'LABEL_DETECTION', 'maxResults': top}],
    }]}
    rsp = VISION.images().annotate(body=body).execute().get('responses', [{}])[0]

    # return top labels for image as CSV for Sheet (row)
    if 'labelAnnotations' in rsp:
        return ', '.join('(%.2f%%) %s' % (
                label['score']*100., label['description']) \
                for label in rsp['labelAnnotations'])


def sheet_append_row(sheet, row):
    'append row to a Google Sheet, return #cells added'

    # call Sheets API to write row to Sheet (via its ID)
    rsp = SHEETS.spreadsheets().values().append(
            spreadsheetId=sheet, range='Sheet1',
            valueInputOption='USER_ENTERED', body={'values': [row]}
    ).execute()
    if rsp:
        return rsp.get('updates').get('updatedCells')


def main(fname, bucket, sheet_id, folder, top, debug):
    '"main()" drives process from image download through report generation'

    # download img file & info from Drive
    rsp = drive_get_img(fname)
    if not rsp:
        return
    fname, mtype, ftime, data = rsp
    if debug:
        print('Downloaded %r (%s, %s, size: %d)' % (fname, mtype, ftime, len(data)))

    # upload file to GCS
    gcsname = '%s/%s'% (folder, fname)
    rsp = gcs_blob_upload(gcsname, bucket, data, mtype)
    if not rsp:
        return
    if debug:
        print('Uploaded %r to GCS bucket %r' % (rsp['name'], rsp['bucket']))

    # process w/Vision
    rsp = vision_label_img(base64.b64encode(data).decode('utf-8'), top)
    if not rsp:
        return
    if debug:
        print('Top %d labels from Vision API: %s' % (top, rsp))

    # push results to Sheet, get cells-saved count
    fsize = k_ize(len(data))
    row = [folder,
            '=HYPERLINK("storage.cloud.google.com/%s/%s", "%s")' % (
            bucket, gcsname, fname), mtype, ftime, fsize, rsp
    ]
    rsp = sheet_append_row(sheet_id, row)
    if not rsp:
        return
    if debug:
        print('Added %d cells to Google Sheet' % rsp)
    return True


if __name__ == '__main__':
    # args: [-hv] [-i imgfile] [-b bucket] [-f folder] [-s Sheet ID] [-t top labels]
    parser = argparse.ArgumentParser()
    parser.add_argument("-i", "--imgfile", action="store_true",
            default=FILE, help="image file filename")
    parser.add_argument("-b", "--bucket_id", action="store_true",
            default=BUCKET, help="Google Cloud Storage bucket name")
    parser.add_argument("-f", "--folder", action="store_true",
            default=PARENT, help="Google Cloud Storage image folder")
    parser.add_argument("-s", "--sheet_id", action="store_true",
            default=SHEET, help="Google Sheet Drive file ID (44-char str)")
    parser.add_argument("-t", "--viz_top", action="store_true",
            default=TOP, help="return top N (default %d) Vision API labels" % TOP)
    parser.add_argument("-v", "--verbose", action="store_true",
            default=DEBUG, help="verbose display output")
    args = parser.parse_args()

    print('Processing file %r... please wait' % args.imgfile)
    rsp = main(args.imgfile, args.bucket_id,
            args.sheet_id, args.folder, args.viz_top, args.verbose)
    if rsp:
        sheet_url = 'https://docs.google.com/spreadsheets/d/%s/edit' % args.sheet_id
        print('DONE: opening web browser to it, or see %s' % sheet_url)
        webbrowser.open(sheet_url, new=1, autoraise=True)
    else:
        print('ERROR: could not process %r' % args.imgfile)

Faremo il possibile per mantenere aggiornati i contenuti di questo tutorial, ma in alcuni casi il repository avrà la versione più recente del codice.

13. Complimenti!

Hai sicuramente imparato molto in questo codelab e l'hai ottenuto, sopravvivendo a uno dei codelab più lunghi. Di conseguenza, hai affrontato un possibile scenario aziendale con circa 130 righe di Python, sfruttando tutti i servizi Google Cloud e Google Workspace e spostando i dati da una all'altra per creare una soluzione funzionante. Esplora il repository open source per tutte le versioni di questa app (maggiori informazioni di seguito).

Esegui la pulizia

  1. L'utilizzo delle API Google Cloud non è senza costi, mentre le API Google Workspace sono coperte dalla quota di abbonamento mensile a Google Workspace (gli utenti Gmail consumer hanno una tariffa mensile pari a zero), quindi non è richiesta la pulizia/il ritiro delle API per gli utenti di Google Workspace. Per Google Cloud, puoi andare alla dashboard della console Cloud e controllare la "scheda" Fatturazione per gli addebiti stimati.
  2. Per Cloud Vision, è consentito un numero fisso di chiamate API al mese senza costi. Quindi, finché rimani entro questi limiti, non dovrai spegnere nulla né disattivare/eliminare il progetto. Ulteriori informazioni sulla fatturazione e sulla quota senza costi dell'API Vision sono disponibili nella pagina dei prezzi dell'API Vision.
  3. Alcuni utenti di Cloud Storage ricevono una quantità senza costi di spazio di archiviazione al mese. Se le immagini archiviate utilizzando questo codelab non ti fanno superare questa quota, non ti verrà addebitato alcun costo. Ulteriori informazioni sulla fatturazione GCS e sulla quota senza costi sono disponibili nella relativa pagina dei prezzi. Puoi visualizzare ed eliminare facilmente i BLOB dal browser Cloud Storage.
  4. Anche il tuo utilizzo di Google Drive potrebbe prevedere una quota di spazio di archiviazione e, se la superi (o ti avvicini al limite), prendi in considerazione l'utilizzo dello strumento che hai creato in questo codelab per archiviare le immagini in Cloud Storage e ottenere più spazio su Drive. Ulteriori informazioni sullo spazio di archiviazione di Google Drive sono disponibili nella pagina dei prezzi appropriata per gli utenti di Google Workspace Basic o per gli utenti Gmail/consumer.

Anche se la maggior parte dei piani Google Workspace Business ed Enterprise dispone di spazio di archiviazione illimitato, le cartelle di Drive potrebbero essere sovraccaricate e/o sovraccaricate. Inoltre, l'app che hai creato in questo tutorial è un ottimo modo per archiviare file superflui e ripulire Google Drive.

Versioni alternative

Mentre final/analyze_gsimg.py è l'"ultimo" versione ufficiale a cui stai lavorando in questo tutorial, non è la fine della storia. Un problema con la versione finale dell'app è che utilizza le librerie di autenticazione precedenti che sono state ritirate. Abbiamo scelto questo percorso perché, al momento della stesura del presente documento, le librerie di autenticazione più recenti non supportavano diversi elementi chiave: gestione dell'archiviazione dei token OAuth e sicurezza dei thread.

Librerie di autenticazione attuali (più recenti)

Tuttavia, prima o poi le librerie di autenticazione precedenti non saranno più supportate, quindi ti invitiamo a esaminare le versioni che utilizzano le librerie di autenticazione più recenti (attuali) presenti nella cartella alt del repository, anche se non sono sicure per i thread (ma puoi creare la tua soluzione). Cerca i file il cui nome contiene *newauth*.

Librerie client dei prodotti Google Cloud

Google Cloud consiglia a tutti gli sviluppatori di utilizzare le librerie client del prodotto quando utilizzano le API Google Cloud. Purtroppo, al momento le API non Google Cloud non dispongono di librerie di questo tipo. L'uso delle librerie di livello inferiore consente un utilizzo coerente dell'API e una migliore leggibilità delle funzionalità. Analogamente al suggerimento precedente, versioni alternative che utilizzano le librerie client dei prodotti Google Cloud sono disponibili nella cartella alt del repository per consentirti di esaminarla. Cerca i file il cui nome contiene *-gcp*.

Autorizzazione account di servizio

Quando si lavora puramente nel cloud, in genere non sono presenti dati di proprietà di persone o esseri umani, quindi è per questo che gli account di servizio e le autorizzazioni degli account di servizio vengono utilizzati principalmente con Google Cloud. Tuttavia, i documenti di Google Workspace sono generalmente di proprietà di utenti umani, quindi è per questo che questo tutorial utilizza l'autorizzazione dell'account utente. Ciò non significa che non è possibile utilizzare le API Google Workspace con gli account di servizio. Se tali account dispongono del livello di accesso appropriato, possono sicuramente essere utilizzati nelle applicazioni. Analogamente a quanto sopra, versioni alternative che utilizzano l'autorizzazione dell'account di servizio sono disponibili nella cartella alt del repository per consentirti di esaminarla. Cerca i file il cui nome contiene *-svc*.

Catalogo versioni alternative

Di seguito sono riportate tutte le versioni alternative di final/analyze_gsimg.py, ciascuna delle quali include una o più proprietà tra quelle citate sopra. Nel nome file di ogni versione, cerca:

  • "oldauth" per le versioni che utilizzano le librerie di autenticazione precedenti (oltre a final/analyze_gsimg.py)
  • "newauth" per chi usa le librerie di autenticazione attuali/più recenti
  • "gcp" per chi usa le librerie client dei prodotti Google Cloud, ad esempio google-cloud-storage e così via.
  • "svc" per chi utilizza un'autenticazione con account di servizio ("svc acct") anziché un account utente.

Ecco tutte le versioni:

Nome file

Descrizione

final/analyze_gsimg.py

Il campione principale; usa le librerie di autenticazione precedenti

alt/analyze_gsimg-newauth.py

Come final/analyze_gsimg.py, ma utilizza le librerie di autenticazione più recenti

alt/analyze_gsimg-oldauth-gcp.py

Come final/analyze_gsimg.py, ma utilizza le librerie client del prodotto Google Cloud

alt/analyze_gsimg-newauth-gcp.py

Come alt/analyze_gsimg-newauth.py, ma utilizza le librerie client del prodotto Google Cloud

alt/analyze_gsimg-oldauth-svc.py

Uguale a final/analyze_gsimg.py, ma utilizza l'account svc al posto dell'account utente

alt/analyze_gsimg-newauth-svc.py

Uguale a alt/analyze_gsimg-newauth.py, ma utilizza l'autenticazione dell'account svc al posto dell'account utente

alt/analyze_gsimg-oldauth-svc-gcp.py

Come alt/analyze_gsimg-oldauth-svc.py, ma utilizza le librerie client del prodotto Google Cloud e alt/analyze_gsimg-oldauth-gcp.py, ma utilizza l'autenticazione account svc anziché l'account utente

alt/analyze_gsimg-newauth-svc-gcp.py

Come alt/analyze_gsimg-oldauth-svc-gcp.py, ma utilizza le librerie di autenticazione più recenti

Insieme alla final/analyze_gsimg.py originale , hai tutte le possibili combinazioni della soluzione finale, indipendentemente dall'ambiente di sviluppo delle API di Google, e puoi scegliere quella che meglio si adatta alle tue esigenze. Per una spiegazione simile, consulta anche alt/README.md.

Studio aggiuntivo

Di seguito sono riportate alcune idee su come eseguire questo esercizio di uno o due passi. Il set di problemi che la soluzione corrente può gestire può essere espanso per apportare questi miglioramenti:

  1. (Più immagini nelle cartelle) Invece di elaborare una sola immagine, supponiamo che tu abbia immagini nelle cartelle di Google Drive.
  2. (più immagini nei file ZIP) Invece di una cartella di immagini, che ne dici degli archivi ZIP contenenti file immagine? Se utilizzi Python, prendi in considerazione il modulo zipfile.
  3. (analizza le etichette di Vision) Raggruppa le immagini simili, magari iniziando cercando le etichette più comuni, poi la seconda più comune e così via.
  4. (Crea grafici) Follow-up 3: genera grafici con l'API Fogli in base all'analisi e alla categorizzazione dell'API Vision
  5. (categorizza i documenti) Invece di analizzare le immagini con l'API Cloud Vision, supponiamo che tu abbia file PDF da classificare con l'API Cloud Natural Language. Se utilizzi le soluzioni illustrate sopra, i PDF possono trovarsi in cartelle di Drive o archivi ZIP su Drive.
  6. (Creare presentazioni) Utilizza l'API Presentazioni per generare una presentazione dai contenuti del report di Fogli Google. Per trovare l'ispirazione, leggi questo post del blog e video sulla generazione di slide dai dati di un foglio di lavoro.
  7. (Esporta come PDF) Esporta il foglio di lavoro e/o la presentazione come PDF, ma non è una funzionalità delle API Fogli o Presentazioni. Suggerimento: API Google Drive. Merito aggiuntivo: unisci i PDF di Fogli e Presentazioni in un unico PDF master con strumenti come Ghostscript (Linux, Windows) o Combine PDF Pages.action (Mac OS X).

Scopri di più

Codelab

Generale

Google Workspace

Google Cloud

Licenza

Questo lavoro è concesso in licenza ai sensi di una licenza Creative Commons Attribution 2.0 Generic.