Bildarchivierung, -analyse und -erstellung für Google Workspace & Google Cloud

1. Übersicht

Dieses Codelab stellt einen möglichen Unternehmensworkflow vor: Bildarchivierung, Analyse und Berichterstellung. Stellen Sie sich vor, Ihre Organisation hat eine Reihe von Bildern, die Speicherplatz auf einer eingeschränkten Ressource belegen. Sie möchten diese Daten archivieren, die Bilder analysieren und vor allem einen Bericht erstellen, der die archivierten Standorte sowie die Ergebnisse der Analyse zusammenfasst und vom Management abrufbereit enthält. Google Cloud bietet die entsprechenden Tools und nutzt die APIs aus zwei seiner Produktlinien: Google Workspace (ehemals G Suite oder Google Apps) und Google Cloud (zuvor Google Cloud).

In unserem Szenario hat der geschäftliche Nutzer Bilder auf Google Drive. Es ist sinnvoll, sie als „kälter“, günstigerer Speicher wie die in Google Cloud Storage verfügbaren Speicherklassen. Mit Google Cloud Vision können Entwickler leicht Funktionen zur visuellen Erkennung in Anwendungen einbinden, z. B. die Erkennung von Objekten und Sehenswürdigkeiten oder der optischen Zeichenerkennung (Optical Character Recognition, OCR). Außerdem ist eine Tabelle in Google Tabellen ein nützliches Visualisierungstool, mit dem Sie all dies für Ihren Chef zusammenfassen können.

Nachdem Sie dieses Codelab abgeschlossen haben, um eine Lösung zu entwickeln, die Google Cloud vollständig nutzt, hoffen wir, dass Sie etwas Interessantes für Ihr Unternehmen oder Ihre Kunden entwickeln können.

Lerninhalte

  • Cloud Shell verwenden
  • API-Anfragen authentifizieren
  • Google APIs-Clientbibliothek für Python installieren
  • Google APIs aktivieren
  • Dateien aus Google Drive herunterladen
  • Objekte/Blobs in Cloud Storage hochladen
  • Daten mit Cloud Vision analysieren
  • Zeilen in Google Tabellen schreiben

Voraussetzungen

  • Ein Google-Konto (Google Workspace-Konten erfordern möglicherweise die Genehmigung eines Administrators)
  • Ein Google Cloud-Projekt mit einem aktiven Google Cloud-Rechnungskonto
  • Erfahrung mit Terminal-/Shell-Befehlen des Betriebssystems
  • Grundkenntnisse in Python (2 oder 3), Sie können aber jede unterstützte Sprache verwenden.

Erfahrung mit den vier oben aufgeführten Google Cloud-Produkten wäre hilfreich, aber nicht erforderlich. Wenn Sie genügend Zeit haben, um sich separat mit ihnen vertraut zu machen, können Sie gerne Codelabs für jedes dieser Labs durchführen, bevor Sie hier mit der Übung beginnen:

Umfrage

Wie möchten Sie diese Anleitung nutzen?

<ph type="x-smartling-placeholder"></ph> Nur bis zum Ende lesen Lies sie dir durch und absolviere die Übungen

Wie würden Sie Ihre Erfahrung mit Python bewerten?

<ph type="x-smartling-placeholder"></ph> Neuling Mittel Kompetent

Wie würden Sie Ihre Erfahrungen im Umgang mit Google Cloud-Diensten bewerten?

<ph type="x-smartling-placeholder"></ph> Neuling Mittel Kompetent

Wie würden Sie Ihre Erfahrungen mit den Google Workspace-Entwicklerdiensten bewerten?

<ph type="x-smartling-placeholder"></ph> Neuling Mittel Kompetent

Würden Sie gerne mehr „geschäftsorientierte“ sehen? Codelabs oder Codelabs, bei denen es sich um die Einführung von Produktfunktionen handelt?

<ph type="x-smartling-placeholder"></ph> Ja Nein Mehr von beidem

2. Einrichtung und Anforderungen

Umgebung zum selbstbestimmten Lernen einrichten

  1. Melden Sie sich in der Google Cloud Console an und erstellen Sie ein neues Projekt oder verwenden Sie ein vorhandenes Projekt. Wenn Sie noch kein Gmail- oder Google Workspace-Konto haben, müssen Sie eines erstellen.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Der Projektname ist der Anzeigename für die Projektteilnehmer. Es handelt sich um eine Zeichenfolge, die von Google APIs nicht verwendet wird. Sie können sie jederzeit aktualisieren.
  • Die Projekt-ID muss für alle Google Cloud-Projekte eindeutig sein und ist unveränderlich. Sie kann nach dem Festlegen nicht mehr geändert werden. Die Cloud Console generiert automatisch einen eindeutigen String. ist Ihnen meist egal, was es ist. In den meisten Codelabs musst du auf die Projekt-ID verweisen, die üblicherweise als PROJECT_ID gekennzeichnet ist. Wenn Ihnen die generierte ID nicht gefällt, können Sie eine weitere zufällige ID erstellen. Alternativ können Sie einen eigenen verwenden und nachsehen, ob er verfügbar ist. Sie kann nach diesem Schritt nicht mehr geändert werden und bleibt für die Dauer des Projekts bestehen.
  • Zur Information gibt es noch einen dritten Wert, die Projektnummer, die von manchen APIs verwendet wird. Weitere Informationen zu allen drei Werten finden Sie in der Dokumentation.
  1. Als Nächstes müssen Sie in der Cloud Console die Abrechnung aktivieren, um Cloud-Ressourcen/APIs verwenden zu können. Dieses Codelab sollte möglichst wenig kosten. Wenn Sie Ressourcen herunterfahren möchten, um über diese Anleitung hinaus keine Kosten zu verursachen, können Sie die von Ihnen erstellten Ressourcen oder das gesamte Projekt löschen. Neue Google Cloud-Nutzer haben Anspruch auf eine kostenlose Testversion mit 300$Guthaben.

Cloud Shell starten

Zusammenfassung

Sie können Code zwar lokal auf Ihrem Laptop entwickeln, aber in diesem Codelab lernen Sie nicht nur, wie Sie Google Cloud Shell verwenden, eine Befehlszeilenumgebung, die in der Cloud über Ihren modernen Webbrowser ausgeführt wird.

Cloud Shell aktivieren

  1. Klicken Sie in der Cloud Console auf Cloud Shell aktivieren 853e55310c205094.png.

55efc1aaa7a4d3ad.png

Wenn Sie Cloud Shell noch nie gestartet haben, wird ein Zwischenbildschirm (below the fold) angezeigt, in dem beschrieben wird, worum es sich dabei handelt. Klicken Sie in diesem Fall auf Weiter. Der Chat wird nie wieder angezeigt. So sieht dieser einmalige Bildschirm aus:

9c92662c6a846a5c.png

Die Bereitstellung und Verbindung mit Cloud Shell dauert nur einen Moment.

9f0e51b578fecce5.png

Diese virtuelle Maschine verfügt über alle Entwicklungstools, die Sie benötigen. Es bietet ein Basisverzeichnis mit 5 GB nichtflüchtigem Speicher und wird in Google Cloud ausgeführt. Dadurch werden die Netzwerkleistung und die Authentifizierung erheblich verbessert. Viele, wenn nicht sogar alle Arbeiten in diesem Codelab können Sie ganz einfach mit einem Browser oder Ihrem Chromebook erledigen.

Sobald Sie mit Cloud Shell verbunden sind, sollten Sie sehen, dass Sie bereits authentifiziert sind und dass das Projekt bereits auf Ihre Projekt-ID eingestellt ist.

  1. Führen Sie in Cloud Shell den folgenden Befehl aus, um zu prüfen, ob Sie authentifiziert sind:
gcloud auth list

Befehlsausgabe

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

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Führen Sie in Cloud Shell den folgenden Befehl aus, um zu prüfen, ob der gcloud-Befehl Ihr Projekt kennt:
gcloud config list project

Befehlsausgabe

[core]
project = <PROJECT_ID>

Ist dies nicht der Fall, können Sie die Einstellung mit diesem Befehl vornehmen:

gcloud config set project <PROJECT_ID>

Befehlsausgabe

Updated property [core/project].

3. Python-Umgebung bestätigen

Für dieses Codelab müssen Sie die Sprache Python verwenden (obwohl von den Google APIs-Clientbibliotheken viele Sprachen unterstützt werden). Sie können also in Ihrem bevorzugten Entwicklungstool etwas Äquivalentes erstellen und Python einfach als Pseudocode verwenden. Dieses Codelab unterstützt insbesondere Python 2 und 3. Wir empfehlen jedoch, so schnell wie möglich auf Version 3.x umzusteigen.

Cloud Shell ist ein praktisches Tool für Nutzer, das direkt in der Cloud Console verfügbar ist. Da keine lokale Entwicklungsumgebung erforderlich ist, kann dieses Tutorial vollständig in der Cloud über einen Webbrowser durchgeführt werden. Genauer gesagt sind für dieses Codelab bereits beide Versionen von Python in Cloud Shell vorinstalliert.

In Cloud Shell ist auch IPython installiert: ein interaktiver Python-Interpreter auf höherer Ebene, den wir empfehlen, insbesondere wenn Sie Teil der Data Science- oder Machine Learning-Community sind. Falls ja, ist IPython der Standard-Interpreter für Jupyter Notebooks sowie für Colab, Jupyter Notebooks, die von Google Research gehostet werden.

IPython bevorzugt zuerst einen Python 3-Interpreter, greift jedoch auf Python 2 zurück, wenn 3.x nicht verfügbar ist. IPython kann über Cloud Shell aufgerufen werden, kann aber auch in einer lokalen Entwicklungsumgebung installiert werden. Beenden Sie den Vorgang mit ^D (Strg-d) und akzeptieren Sie das Angebot. Die Beispielausgabe für den Start von ipython sieht so aus:

$ 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]:

Wenn Sie IPython nicht bevorzugen, können Sie einen standardmäßigen interaktiven Python-Interpreter (entweder Cloud Shell oder Ihre lokale Entwicklungsumgebung) verwenden. Sie können den Vorgang auch mit ^D beenden:

$ 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.
>>>

Im Codelab wird außerdem davon ausgegangen, dass Sie das pip-Installationstool (Python-Paketmanager und Abhängigkeits-Resolver) haben. Es ist in den Versionen 2.7.9 und höher bzw. 3.4 und höher enthalten. Wenn Sie eine ältere Python-Version verwenden, finden Sie die Installationsanweisungen in dieser Anleitung. Je nach Ihren Berechtigungen benötigen Sie möglicherweise sudo- oder Superuser-Zugriff. Das ist jedoch in der Regel nicht der Fall. Sie können auch explizit pip2 oder pip3 verwenden, um pip für bestimmte Python-Versionen auszuführen.

Im restlichen Codelab wird davon ausgegangen, dass Sie Python 3 verwenden. Für Python 2 werden spezifische Anweisungen bereitgestellt, wenn sie sich deutlich von 3.x unterscheiden.

[optional] Virtuelle Umgebungen erstellen und verwenden

Dieser Abschnitt ist optional und nur für Nutzer erforderlich, die für dieses Codelab eine virtuelle Umgebung verwenden müssen (siehe Seitenleiste oben). Wenn auf Ihrem Computer nur Python 3 installiert ist, können Sie einfach den folgenden Befehl ausführen, um eine virtuelle Umgebung namens my_env zu erstellen. Sie können bei Bedarf auch einen anderen Namen wählen:

virtualenv my_env

Wenn Sie jedoch sowohl Python 2 als auch 3 auf Ihrem Computer installieren, empfehlen wir Ihnen, eine Python 3-Umgebung zu installieren, die Sie mit dem -p flag so verwenden können:

virtualenv -p python3 my_env

Geben Sie die neu erstellte Virtualsuche ein, indem Sie „aktivieren“ so:

source my_env/bin/activate

Prüfen Sie, ob Sie sich in der Umgebung befinden. Sehen Sie dazu nach, ob Ihrer Shell-Eingabeaufforderung jetzt der Name Ihrer Umgebung vorangestellt ist, z. B.

(my_env) $ 

Jetzt sollten Sie in der Lage sein, alle erforderlichen Pakete mit pip install zu versehen, Code innerhalb dieser Datei auszuführen usw. Ein weiterer Vorteil ist, dass Sie die gesamte Umgebung sprengen können, ohne den Rest Ihres Systems zu beeinträchtigen.

4. Google APIs-Clientbibliothek für Python installieren

Für dieses Codelab ist die Google API-Clientbibliothek für Python erforderlich. Die Installation ist daher einfach oder du musst gar nichts tun.

Wir haben Ihnen bereits die Verwendung von Cloud Shell empfohlen. Sie können die gesamte Anleitung über einen Webbrowser in der Cloud durcharbeiten. Ein weiterer Grund für die Verwendung von Cloud Shell ist, dass viele gängige Entwicklertools und notwendige Bibliotheken bereits vorinstalliert sind.

*Clientbibliotheken installieren

(optional) Dieser Schritt kann übersprungen werden, wenn Sie Cloud Shell oder eine lokale Umgebung verwenden, in der Sie bereits die Clientbibliotheken installiert haben. Dies ist nur erforderlich, wenn Sie lokal entwickeln und diese noch nicht installiert haben oder nicht sicher sind. Am einfachsten ist es, die Installation mit pip (oder pip3) durchzuführen (einschließlich der Aktualisierung von pip selbst, falls erforderlich):

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

Installation bestätigen

Mit diesem Befehl werden die Clientbibliothek sowie alle davon abhängigen Pakete installiert. Unabhängig davon, ob Sie Cloud Shell oder Ihre eigene Umgebung verwenden, prüfen Sie, ob die Clientbibliothek installiert ist. Importieren Sie dazu die erforderlichen Pakete und achten Sie darauf, dass keine Importfehler (keine Ausgabe) vorliegen:

python3 -c "import googleapiclient, httplib2, oauth2client"

Wenn Sie stattdessen Python 2 (über Cloud Shell) verwenden, erhalten Sie eine Warnung, dass die Unterstützung dafür eingestellt wurde:

*******************************************************************************
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.
*******************************************************************************

Sobald Sie den Import „test“ ausführen können, erfolgreich ausgeführt (keine Fehler/Ausgabe) haben, können Sie mit Google APIs kommunizieren.

Zusammenfassung

Da es sich um ein Zwischen-Codelab handelt, gehen wir davon aus, dass Sie bereits Erfahrung mit dem Erstellen und mit Projekten in der Console. Wenn Sie mit Google APIs und Google Workspace APIs noch nicht vertraut sind, probieren Sie zuerst das Codelab zur Einführung in die Google Workspace APIs aus. Wenn Sie außerdem wissen, wie Sie Anmeldedaten für Nutzerkonten (nicht Dienstkonto) erstellen (oder wiederverwenden), legen Sie die Datei client_secret.json in Ihrem Arbeitsverzeichnis ab, überspringen Sie das nächste Modul und fahren Sie mit „Google APIs aktivieren“ fort.

5. *API-Anfragen autorisieren (Nutzerautorisierung)

Dieser Abschnitt kann übersprungen werden, wenn Sie bereits Anmeldedaten für die Nutzerkontoautorisierung erstellt haben und mit dem Vorgang vertraut sind. Sie unterscheidet sich von der Dienstkontoautorisierung, deren Verfahren unterschiedlich ist. Fahren Sie daher unten fort.

Einführung in die Autorisierung (sowie einige Authentifizierungsmethoden)

Damit Sie Anfragen an die APIs senden können, muss Ihre Anwendung über die entsprechende Autorisierung verfügen. Authentifizierung, ein ähnliches Wort, beschreibt Anmeldedaten. Dabei authentifizieren Sie sich, wenn Sie sich mit einem Log-in und einem Passwort in Ihrem Google-Konto anmelden. Passwort. Nach der Authentifizierung legen Sie im nächsten Schritt fest, ob Sie für den Zugriff auf Daten wie Blob-Dateien in Cloud Storage oder auf die privaten Dateien eines Nutzers in Google Drive berechtigt sind (bzw. Ihr Code).

Google APIs unterstützen mehrere Autorisierungstypen. Die am häufigsten verwendete Methode für G Suite API-Nutzer ist die Nutzerautorisierung, da die Beispielanwendung in diesem Codelab auf Daten von Endnutzern zugreift. Diese Endnutzer müssen Ihrer App Zugriff auf ihre Daten gewähren. Das bedeutet, dass mit Ihrem Code OAuth2-Anmeldedaten von Nutzerkonten abgerufen werden müssen.

Um OAuth2-Anmeldedaten für die Nutzerautorisierung abzurufen, gehen Sie zurück zum API-Manager und wählen Sie die Option im linken Navigationsbereich:

635af008256d323.png

Dort werden alle Ihre Anmeldedaten in drei separaten Abschnitten angezeigt:

fd2f4133b406d572.png

Das erste ist für API-Schlüssel, die zweiten OAuth 2.0-Client-IDs und die letzten OAuth2-Dienstkonten. Wir verwenden das in der Mitte.

Anmeldedaten erstellen

Klicken Sie oben auf der Seite „Anmeldedaten“ auf die Schaltfläche + Anmeldedaten erstellen. Daraufhin wird ein Dialogfeld angezeigt, in dem Sie „OAuth-Client-ID“ auswählen.

b17b663668e38787.png

Auf dem nächsten Bildschirm gibt es zwei Aktionen: Konfigurieren Sie den Zustimmungsbildschirm für die Autorisierung Ihrer App. und wählen Sie den Anwendungstyp aus:

4e0b967c9d70d262.png

Wenn Sie keinen Zustimmungsbildschirm eingerichtet haben, wird die Warnung in der Konsole angezeigt und Sie müssen dies jetzt tun. Wenn Ihr Zustimmungsbildschirm bereits eingerichtet wurde, können Sie diese nächsten Schritte überspringen.

Klicken Sie auf „Zustimmungsbildschirm konfigurieren“. in dem Sie ein "Extern"-Element App (oder „Intern“ für G Suite-Kunde):

f17e97b30d994b0c.png

Für die Zwecke dieser Übung spielt es keine Rolle, welche Sie auswählen, da Sie Ihr Codelab-Beispiel nicht veröffentlichen. Die meisten Nutzer werden „Extern“ auswählen um zu einem komplexeren Bildschirm weitergeleitet zu werden, aber Sie müssen nur den Namen ein:

b107ab81349bdad2.png

Im Moment benötigen Sie nur einen Anwendungsnamen. Wählen Sie also einen Namen aus, der zu Ihrem Codelab passt, und klicken Sie auf Speichern.

OAuth-Client-ID wird erstellt (Authentifizierung des Nutzerkontos)

Kehren Sie nun zum Tab „Anmeldedaten“ zurück, um eine OAuth2-Client-ID zu erstellen. Hier siehst du eine Vielzahl von OAuth-Client-IDs, die du erstellen kannst:

5ddd365ac0af1e34.png

Wir entwickeln das Befehlszeilentool Andere. Wählen Sie dieses aus und klicken Sie auf Erstellen. Wählen Sie einen Client-ID-Namen für die App aus, die Sie erstellen, oder verwenden Sie einfach den Standardnamen, der normalerweise "Anderer Client N" lautet.

Anmeldedaten werden gespeichert

  1. Ein Dialogfeld mit den neuen Anmeldedaten wird angezeigt. Klicken Sie zum Schließen auf OK.

8bec84d82cb104d7.png

  1. Scrollen Sie auf der Seite „Anmeldedaten“ nach unten zu „OAuth2-Client-IDs“. suchen und klicken Sie auf das Downloadsymbol f54b28417901b3aa.png ganz rechts unter Ihrer neu erstellten Client-ID. 1b4e8d248274a338.png
  2. Es wird ein Dialogfeld zum Speichern einer Datei mit dem Namen client_secret-LONG-HASH-STRING.apps.googleusercontent.com.json geöffnet, die wahrscheinlich im Ordner Downloads abgelegt wird. Wir empfehlen, ihn in einen einfacheren Namen wie client_secret.json zu kürzen, der in der Beispiel-App verwendet wird, und ihn dann in dem Verzeichnis/Ordner zu speichern, in dem du die Beispiel-App in diesem Codelab erstellst.

Zusammenfassung

Jetzt können Sie die in diesem Codelab verwendeten Google APIs aktivieren. Für den Anwendungsnamen im OAuth-Zustimmungsbildschirm haben wir "Vision API-Demo" gewählt. Er wird daher in einigen der nächsten Screenshots zu finden sein.

6. Google APIs aktivieren

In diesem Codelab werden vier (4) Google Cloud APIs verwendet, ein Paar aus Google Cloud (Cloud Storage und Cloud Vision) und ein weiteres Paar aus Google Workspace (Google Drive und Google Tabellen). Im Folgenden finden Sie eine allgemeine Anleitung zum Aktivieren von Google APIs. Sobald Sie wissen, wie Sie eine API aktivieren, sind die anderen ähnlich.

Unabhängig davon, welche Google API Sie in Ihrer Anwendung verwenden möchten, müssen sie aktiviert sein. APIs können über die Befehlszeile oder die Cloud Console aktiviert werden. Die Vorgehensweise zum Aktivieren von APIs ist identisch. Wenn Sie also eine API aktivieren, können Sie andere auf ähnliche Weise aktivieren.

Option 1: gcloud-Befehlszeile (Cloud Shell oder lokale Umgebung)

Das Aktivieren von APIs über die Cloud Console ist zwar üblicher, aber einige Entwickler bevorzugen es, alles über die Befehlszeile zu erledigen. Dazu müssen Sie den „Dienstnamen“ einer API suchen. Es sieht aus wie eine URL: SERVICE_NAME.googleapis.com. Sie finden diese Produkte im Diagramm der unterstützten Produkte. Alternativ können Sie sie mit der Google Discovery API programmatisch abfragen.

Auf Grundlage dieser Informationen können Sie mit Cloud Shell (oder Ihrer lokalen Entwicklungsumgebung, in der das gcloud-Befehlszeilentool installiert ist) eine API oder einen Dienst aktivieren. Gehen Sie dazu so vor:

gcloud services enable SERVICE_NAME.googleapis.com

Beispiel 1: Cloud Vision API aktivieren

gcloud services enable vision.googleapis.com

Beispiel 2: Serverlose Computing-Plattform Google App Engine aktivieren

gcloud services enable appengine.googleapis.com

Beispiel 3: Mehrere APIs mit einer Anfrage aktivieren Wenn in diesem Codelab beispielsweise Betrachter eine Anwendung bereitstellen, die die Cloud Translation API in App Engine, Cloud Functions und Cloud Run verwendet, sieht die Befehlszeile so aus:

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

Dieser Befehl aktiviert App Engine, Cloud Functions, Cloud Run und die Cloud Translation API. Außerdem wird Cloud Artifact Registry aktiviert, da dort Container-Images vom Cloud Build-System registriert werden müssen, um sie in Cloud Run bereitzustellen.

Außerdem können Sie über einige Befehle herausfinden, ob APIs aktiviert werden sollen oder welche APIs bereits für Ihr Projekt aktiviert sind.

Beispiel 4: Abfrage der Google APIs, die für Ihr Projekt aktiviert werden können

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

Beispiel 5: Abfrage für für Ihr Projekt aktivierte Google APIs

gcloud services list

Weitere Informationen zu den oben genannten Befehlen finden Sie in der Dokumentation zum Aktivieren und Deaktivieren von Diensten und zum Auflisten von Diensten.

Option 2: Cloud Console

Sie können die Google APIs auch im API Manager aktivieren. Rufen Sie in der Cloud Console den API Manager auf. Auf dieser Dashboard-Seite sehen Sie einige Traffic-Informationen für Ihre Anwendung, Grafiken zu Anwendungsanfragen, von Ihrer Anwendung generierte Fehler und die Antwortzeiten Ihrer Anwendung:

df4a0a5e00d29ffc.png

Im Folgenden finden Sie eine Liste der Google APIs, die für Ihr Projekt aktiviert sind:

5fcf10e5a05cfb97.png

Klicken Sie oben auf APIs und Dienste aktivieren, um APIs zu aktivieren oder zu deaktivieren:

eef4e5e863f4db66.png

Alternativ können Sie in der linken Navigationsleiste APIs und DiensteBibliothek:

6eda5ba145b30b97.png

In beiden Fällen gelangen Sie zur Seite API-Bibliothek:

5d4f1c8e7cf8df28.png

Geben Sie einen API-Namen ein, nach dem gesucht werden soll, um passende Ergebnisse zu erhalten:

35bc4b9cf72ce9a4.png

Wählen Sie die API aus, die Sie aktivieren möchten, und klicken Sie auf die Schaltfläche Aktivieren:

9574a69ef8d9e8d2.png

Das Aktivieren aller APIs ist ähnlich, unabhängig davon, welche Google API Sie verwenden möchten.

Kosten

Viele Google APIs können kostenlos genutzt werden. Bei den meisten Google Cloud-Produkten und -APIs fallen jedoch Kosten an. Beim Aktivieren von Cloud APIs werden Sie möglicherweise nach einem aktiven Rechnungskonto gefragt. Einige Google Cloud-Produkte bieten jedoch ein „Immer kostenlos“- , die Sie überschreiten müssen, damit Kosten anfallen.

Neue Google Cloud-Nutzer können eine kostenlose Testversion nutzen, die in den ersten 90 Tagen aktuell 300 $beträgt. Für Codelabs wird in der Regel nichts berechnet und es fallen keine Kosten an. Daher empfehlen wir Ihnen, die kostenlose Testversion erst zu nutzen, wenn Sie wirklich bereit sind, sie zu testen. Das gilt insbesondere, da es sich um ein einmaliges Angebot handelt. Die Kontingente der kostenlosen Stufe laufen nicht ab und gelten unabhängig davon, ob Sie den kostenlosen Testzeitraum verwenden oder nicht.

Nutzer sollten sich vor der Aktivierung einer API auf die Preisinformationen beziehen (Beispiel: Cloud Vision API – Preise ) und darauf achten, ob sie eine kostenlose Stufe hat und wenn ja, um welche es sich handelt. Solange Sie insgesamt innerhalb der festgelegten Tages- oder Monatslimits bleiben, fallen keine Kosten an. Preise und kostenlose Stufen unterscheiden sich je nach Google-Produktgruppen-APIs. Beispiele:

Verschiedene Google-Produkte werden unterschiedlich abgerechnet. Lesen Sie daher die entsprechende Dokumentation.

Zusammenfassung

Nachdem Cloud Vision aktiviert wurde, aktivieren Sie die anderen drei APIs (Google Drive, Cloud Storage, Google Tabellen) auf die gleiche Weise. Verwenden Sie in Cloud Shell gcloud services enable oder in der Cloud Console:

  1. Zurück zur API-Bibliothek
  2. Starten Sie eine Suche, indem Sie einige Buchstaben des Namens eingeben
  3. Wählen Sie die gewünschte API aus und
  4. Aktivieren

Einschäumen, ausspülen und wiederholen. Für Cloud Storage haben Sie mehrere Möglichkeiten: Wählen Sie die Google Cloud Storage JSON API aus. Die Cloud Storage API erwartet außerdem ein aktives Rechnungskonto.

7. Schritt 0: Importe und Autorisierungscode

Dies ist der Anfang eines mittelgroßen Code-Snippets. Daher trägt die Einhaltung agiler Praktiken dazu bei, eine gemeinsame, stabile und funktionierende Infrastruktur zu gewährleisten, bevor die Hauptanwendung in Angriff genommen wird. Überprüfen Sie, ob client_secret.json in Ihrem aktuellen Verzeichnis verfügbar ist, und starten Sie entweder ipython und geben Sie das folgende Code-Snippet ein oder speichern Sie es unter analyze_gsimg.py und führen Sie es über die Shell aus. Letzteres wird bevorzugt, da wir das Codebeispiel weiter ergänzen:

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)

Diese Kernkomponente umfasst Codeblöcke für Modul-/Paketimporte, die Verarbeitung von Anmeldedaten für die Nutzerauthentifizierung und das Erstellen von API-Dienstendpunkten. Die wichtigsten Elemente des Codes, die Sie überprüfen sollten:

  • Durch den Import der Funktion print() ist dieses Beispiel mit Python 2-3 kompatibel. Die Google-Bibliotheksimporte beinhalten alle für die Kommunikation mit Google APIs erforderlichen Tools.
  • Die Variable SCOPES steht für die Berechtigungen, die vom Nutzer angefordert werden sollen. Derzeit gibt es nur eine: die Berechtigung zum Lesen von Daten aus Google Drive.
  • Der Rest des Anmeldedaten-Verarbeitungscodes liest im Cache gespeicherte OAuth2-Tokens und wird möglicherweise auf ein neues Zugriffstoken mit dem Aktualisierungstoken aktualisiert, wenn das ursprüngliche Zugriffstoken abgelaufen ist.
  • Wenn keine Tokens erstellt wurden oder das Abrufen eines gültigen Zugriffstokens aus einem anderen Grund fehlgeschlagen ist, muss der Nutzer den dreibeinigen OAuth2-Vorgang (3LO) durchlaufen: Erstellen Sie das Dialogfeld mit den angeforderten Berechtigungen und fordern Sie den Nutzer zur Annahme auf. Danach wird die App fortgesetzt. Andernfalls löst tools.run_flow() eine Ausnahme aus und die Ausführung wird angehalten.
  • Nachdem der Nutzer die Berechtigung erteilt hat, wird ein HTTP-Client für die Kommunikation mit dem Server erstellt. Außerdem werden alle Anfragen aus Sicherheitsgründen mit den Anmeldedaten des Nutzers signiert. Anschließend wird ein Dienstendpunkt für die Google Drive API (Version 3) mit diesem HTTP-Client erstellt und dann DRIVE zugewiesen.

Anwendung ausführen

Wenn Sie das Skript zum ersten Mal ausführen, erhält es nicht die Berechtigung, auf die Dateien des Nutzers in Google Drive (Ihre eigenen) zuzugreifen. Die Ausgabe sieht bei angehaltener Ausführung so aus:

$ 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

Wenn die Ausführung über Cloud Shell erfolgt, fahren Sie mit dem Abschnitt "Von Cloud Shell" fort. Scrollen Sie dann zurück und sehen Sie sich die relevanten Bildschirme unter „Aus lokaler Entwicklungsumgebung“ an. wenn es angebracht ist.

Aus der lokalen Entwicklungsumgebung

Das Befehlszeilenskript wird beim Öffnen eines Browserfensters angehalten. Möglicherweise wird eine beängstigende Warnungsseite wie diese angezeigt:

149241d33871a141.png

Das ist gerechtfertigt, da Sie versuchen, eine App auszuführen, die auf Nutzerdaten zugreift. Da es sich nur um eine Demo-App handelt und Sie selbst der Entwickler sind, vertrauen Sie sich hoffentlich genug, dass Sie fortfahren. Versetzen Sie sich in die Lage des Nutzers: Sie werden aufgefordert, dem Code einer anderen Person Zugriff auf Ihre Daten zu gewähren. Wenn Sie eine solche Anwendung veröffentlichen möchten, müssen Sie den Bestätigungsprozess durchlaufen, damit Ihre Nutzer diesen Bildschirm nicht sehen.

Nachdem Sie auf die Schaltfläche „Zu ‚unsafe‘ wechseln“ App“ sehen Sie ein OAuth2-Berechtigungsdialogfeld, das ungefähr so aussieht:

a122eb7468d0d34e.png

Im OAuth2-Vorgangsdialogfeld werden die Berechtigungen angezeigt, die der Entwickler anfordert (über die Variable SCOPES). In diesem Fall ist es die Möglichkeit, Dateien im Google Drive-Konto des Nutzers anzusehen und herunterzuladen. Im Anwendungscode werden diese Berechtigungsbereiche als URIs angezeigt, aber sie werden in die Sprache übersetzt, die in der Sprache des Nutzers angegeben ist. In diesem Fall muss der Nutzer die angeforderte(n) Berechtigung(en) explizit autorisieren. Andernfalls wird eine Ausnahme ausgelöst und das Skript fährt nicht fort.

Möglicherweise wird sogar ein weiteres Dialogfeld angezeigt, in dem Sie um Ihre Bestätigung gebeten werden:

bf171080dcd6ec5.png

HINWEIS: Einige verwenden mehrere Webbrowser, die in verschiedenen Konten angemeldet sind. Daher wird die Autorisierungsanfrage möglicherweise auf dem falschen Browsertab bzw. in dem falschen Browserfenster angezeigt und Sie müssen den Link für diese Anfrage ausschneiden und in einen Browser einfügen, in dem Sie mit dem richtigen Konto angemeldet sind.

Von Cloud Shell

In Cloud Shell öffnet sich kein Browserfenster, sodass Sie nicht weiterkommen. Stellen Sie fest, dass die Diagnosemeldung unten für Sie bestimmt ist:

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

  --noauth_local_webserver

Sie müssen ^C (Strg-C oder eine andere Tastenkombination zum Anhalten der Skriptausführung) drücken und es mit der zusätzlichen Markierung in Ihrer Shell ausführen. Wenn Sie sie auf diese Weise ausführen, erhalten Sie stattdessen die folgende Ausgabe:

$ 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:

(Die Warnung wird ignoriert, da wir wissen, dass storage.json noch nicht erstellt wurde.) Wenn Sie der Anleitung auf einem anderen Browsertab mit dieser URL folgen, ist der Vorgang nahezu identisch mit dem, was oben für lokale Entwicklungsumgebungen beschrieben wurde (siehe Screenshots oben). Am Ende sehen Sie einen letzten Bildschirm mit dem Bestätigungscode, den Sie in Cloud Shell eingeben müssen:

40a567cda0f31cc9.png

Kopieren Sie diesen Code und fügen Sie ihn in das Terminalfenster ein.

Zusammenfassung

Abgesehen von „Authentication successful“ ist keine weitere Ausgabe zu erwarten. Denken Sie daran, das ist nur die Einrichtung... Sie haben noch nichts gemacht. Sie haben den Weg zu etwas gebracht, das mit höherer Wahrscheinlichkeit gleich beim ersten Mal richtig ausgeführt wird. Das Beste ist, dass Sie nur einmal zur Autorisierung aufgefordert wurden. Bei allen nachfolgenden Ausführungen wird diese Autorisierung übersprungen, da Ihre Berechtigungen im Cache gespeichert wurden. Lassen Sie uns nun dafür sorgen, dass der Code echte Arbeit ausführt, was zu einer tatsächlichen Ausgabe führt.

Fehlerbehebung

Wenn Sie anstelle einer Ausgabe einen Fehler erhalten, kann dies an einer oder mehreren Ursachen liegen, zum Beispiel der folgenden:

8. Schritt 1: Bild aus Google Drive herunterladen

Im vorherigen Schritt haben wir empfohlen, den Code als analyze_gsimg.py zu erstellen und den Code dann dort zu bearbeiten. Es ist auch möglich, alles direkt in iPython oder die Standard-Python-Shell ausschneiden und einfügen zu lassen. Dies ist jedoch umständlicher, da wir die Anwendung Stück für Stück erstellen werden.

Angenommen, Ihre Anwendung wurde autorisiert und ein API-Dienstendpunkt erstellt. Im Code wird es durch die Variable DRIVE dargestellt. Suchen wir nun eine Bilddatei in Google Drive

auf eine Variable namens NAME festlegen. Geben Sie das und die folgende drive_get_img()-Funktion direkt unter dem Code aus Schritt 0 ein:

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

Die files()-Sammlung in Google Drive hat eine list()-Methode, mit der eine Abfrage (der Parameter q) für die angegebene Datei ausgeführt wird. Der Parameter fields wird verwendet, um anzugeben, an welchen Rückgabewerten Sie interessiert sind – warum sollten Sie alles zurückerhalten und den Vorgang verlangsamen, wenn Ihnen die anderen Werte nicht wichtig sind? Wenn Sie noch nicht mit Feldmasken zum Filtern von API-Rückgabewerten vertraut sind, lesen Sie diesen Blogpost und Video Führen Sie andernfalls die Abfrage aus und rufen Sie das zurückgegebene Attribut files ab. Wenn keine Übereinstimmungen vorliegen, wird standardmäßig ein leeres Listenarray verwendet.

Wenn keine Ergebnisse vorhanden sind, wird der Rest der Funktion übersprungen und None wird (implizit) zurückgegeben. Andernfalls rufen Sie die erste übereinstimmende Antwort (rsp[0]) ab und geben den Dateinamen, den MIME-Typ, den Zeitstempel der letzten Änderung und schließlich die binäre Nutzlast zurück, die von der Funktion get_media() (über ihre Datei-ID) ebenfalls in der Sammlung files() abgerufen wird. (Methodennamen können sich von Client-Bibliotheken in anderen Sprachen leicht unterscheiden.)

Der letzte Teil ist der „Hauptteil“, für die gesamte Anwendung:

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)

Bei einem Bild namens section-work-card-img_2x.jpg in Google Drive, das auf FILE festgelegt ist, sollte nach erfolgreicher Skriptausführung eine Bestätigung angezeigt werden, dass die Datei zwar aus Drive gelesen, aber nicht auf Ihrem Computer gespeichert wurde:

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

Fehlerbehebung

Wenn Sie die Ausgabe nicht wie oben beschrieben erhalten, kann dies an einer oder mehreren Ursachen liegen, z. B. diesem:

Zusammenfassung

In diesem Abschnitt haben Sie erfahren, wie Sie in zwei separaten API-Aufrufen eine Verbindung zur Drive API herstellen, um eine bestimmte Datei abzufragen und diese dann herunterzuladen. Ein Anwendungsfall für Unternehmen: Drive-Daten archivieren und vielleicht analysieren, z. B. mit Google Cloud-Tools. Der Code für Ihre App sollte in dieser Phase mit dem Code im Repository bei step1-drive/analyze_gsimg.py übereinstimmen.

Weitere Informationen zum Herunterladen von Dateien in Google Drive finden Sie hier. Weitere Informationen finden Sie auch in diesem Blogpost und in Video Dieser Teil des Codelabs ist fast identisch mit dem gesamten Codelab für die Google Workspace APIs. Statt eine Datei herunterzuladen, werden die ersten 100 Dateien/Ordner auf Google Drive eines Nutzers angezeigt und der Bereich wird stärker eingeschränkt.

9. Schritt 2: Datei in Cloud Storage archivieren

Im nächsten Schritt fügen Sie die Unterstützung für Google Cloud Storage hinzu. Dazu müssen wir ein weiteres Python-Paket importieren, io. Überprüfen Sie, ob der obere Bereich Ihrer Importe jetzt so aussieht:

from __future__ import print_function                   
import io

Zusätzlich zum Drive-Dateinamen benötigen wir Informationen darüber, wo diese Datei in Cloud Storage gespeichert werden soll, insbesondere den Namen des „Buckets“ in einem beliebigen übergeordneten Ordner Präfixe. Mehr dazu später:

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

Noch ein Hinweis zu Buckets: Cloud Storage bietet amorphe Blob-Speicher. Beim Hochladen von Dateien ist das Konzept der Dateitypen, Erweiterungen usw. nicht so verständlich, wie es bei Google Drive der Fall ist. Sie sind einfach nur „Blasen“ zu Cloud Storage hinzufügen. Außerdem gibt es in Cloud Storage keine Ordner oder Unterverzeichnisse.

Ja, Sie können Schrägstriche (/) in Dateinamen verwenden, um die Abstraktion mehrerer Unterordner darzustellen. Am Ende des Tages werden jedoch alle Blobs in einen Bucket verschoben und „/“-Elemente sind nur Zeichen in ihren Dateinamen. Weitere Informationen finden Sie auf der Seite Namenskonventionen für Buckets und Objekte.

In Schritt 1 oben wurde der Lesezugriff auf Drive angefordert. Derzeit reicht das aus. Jetzt ist eine Lese-/Schreibberechtigung für das Hochladen in Cloud Storage erforderlich. Ändern Sie SCOPES von einer einzelnen Stringvariable in ein Array (Python-Tupel [oder Liste]) von Berechtigungsbereichen. Dann sieht das so aus:

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

Erstellen Sie jetzt einen Dienstendpunkt für Cloud Storage direkt unter dem für Drive. Beachten Sie, dass wir den Aufruf zur Wiederverwendung desselben HTTP-Clientobjekts leicht geändert haben, da kein neues Objekt erstellt werden muss, wenn es sich um eine gemeinsam genutzte Ressource handeln kann.

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

Fügen Sie jetzt nach drive_get_img() die folgende Funktion hinzu, die in Cloud Storage hochgeladen wird:

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()

Für den objects.().insert()-Aufruf sind der Bucket-Name, die Dateimetadaten und das binäre Blob selbst erforderlich. Zum Herausfiltern der Rückgabewerte fordert die Variable fields nur die Bucket- und Objektnamen an, die von der API zurückgegeben werden. Weitere Informationen zu diesen Feldmasken bei API-Leseanfragen finden Sie in diesem Beitrag und Video

Binden Sie jetzt die Verwendung von gcs_blob_upload() in die Hauptanwendung ein:

        # 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)

Mit der Variable gcsname werden alle „übergeordneten Unterverzeichnisse“ zusammengeführt. Name(n), an den der Dateiname angehängt wird, und mit dem Präfix des Bucket-Namens geben an, dass Sie die Datei unter "/bucket/parent.../filename" archivieren. Fügen Sie diesen Block direkt nach der ersten print()-Funktion direkt über der else-Klausel ein, damit der gesamte sieht so aus:

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)

Angenommen, wir geben einen Bucket namens „vision-demo“ an mit „analyzed_imgs“ als übergeordnetes Unterverzeichnis. Nachdem Sie diese Variablen festgelegt und das Skript noch einmal ausgeführt haben, wird section-work-card-img_2x.jpg aus Drive heruntergeladen und dann in Cloud Storage hochgeladen. Ist das richtig? NICHT!

$ 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">

Der Drive-Download war zwar erfolgreich, der Upload in Cloud Storage ist jedoch fehlgeschlagen. Warum?

Dies liegt daran, dass wir bei der Autorisierung dieser Anwendung für Schritt 1 nur den Lesezugriff auf Google Drive autorisiert haben. Obwohl wir den Lese-/Schreibbereich für Cloud Storage hinzugefügt haben, haben wir den Nutzer nie aufgefordert, diesen Zugriff zu autorisieren. Damit es funktioniert, müssen wir die Datei storage.json, in der dieser Bereich fehlt, aussortieren und noch einmal ausführen.

Nachdem Sie die Autorisierung noch einmal durchgeführt haben, sehen Sie sich die beiden Bereiche in storage.json an und sehen Sie sich die beiden Bereiche an. Die Ausgabe sollte so aussehen:

$ 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'

Zusammenfassung

Das ist ein großer Schritt, denn Sie zeigen Ihnen mit relativ wenigen Codezeilen, wie Sie Dateien zwischen beiden cloudbasierten Speichersystemen übertragen können. Der geschäftliche Anwendungsfall ist hier, eine möglicherweise eingeschränkte Ressource wie bereits erwähnt, preisgünstigeren Speicherplatz. Cloud Storage bietet verschiedene Speicherklassen, je nachdem, ob Sie regelmäßig, monatlich, vierteljährlich oder jährlich auf Ihre Daten zugreifen.

Natürlich fragen uns Entwickler immer wieder, warum sowohl Google Drive als auch Cloud Storage existieren. Befinden sie sich nicht beide Dateispeicher in der Cloud? Deshalb haben wir dieses Video erstellt. Der Code in dieser Phase sollte mit dem Inhalt im Repository unter step2-gcs/analyze_gsimg.py übereinstimmen.

10. Schritt 3: Mit Cloud Vision analysieren

Wir wissen jetzt, dass Sie Daten zwischen Google Cloud und Google Workspace verschieben können. Wir haben jedoch noch keine Analyse durchgeführt. Es ist also an der Zeit, das Bild zur Label-Annotation, auch als Objekterkennung bezeichnet, an Cloud Vision zu senden. Dazu müssen die Daten Base64-codiert werden, d. h. ein weiteres Python-Modul, base64. Überprüfen Sie, ob der wichtigste Importbereich jetzt so aussieht:

from __future__ import print_function
import base64
import io

Standardmäßig gibt die Vision API alle gefundenen Labels zurück. Zur Gewährleistung einer einheitlichen Struktur fordern wir nur die Top 5 an, die natürlich vom Nutzer angepasst werden können. Wir verwenden dafür die konstante Variable TOP. unter allen anderen Konstanten hinzufügen:

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

Wie bei den vorherigen Schritten benötigen wir einen anderen Berechtigungsbereich, diesmal für die Vision API. Aktualisieren Sie SCOPES mit ihrem String:

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

Erstellen Sie nun einen Dienstendpunkt für Cloud Vision, damit er an den anderen ausgeführt wird:

# 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)

Fügen Sie nun die folgende Funktion hinzu, die die Bildnutzlast an Cloud Vision sendet:

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'])

Für den images().annotate()-Aufruf werden die Daten sowie die gewünschten API-Funktionen benötigt. Auch die Top-5-Label Cap ist Teil der Nutzlast (aber optional). Wenn der Aufruf erfolgreich ist, gibt die Nutzlast die ersten 5 Objektlabels sowie einen Konfidenzwert eines Objekts im Bild zurück. Wenn keine Antwort zurückgegeben wird, weisen Sie ein leeres Python-Wörterbuch zu, damit die folgende if-Anweisung nicht fehlschlägt. Diese Funktion führt diese Daten einfach zu einer CSV-Zeichenfolge zusammen, um sie später in unserem Bericht zu verwenden.

Diese fünf Zeilen, die vision_label_img() aufrufen, sollten direkt nach dem erfolgreichen Upload in Cloud Storage platziert werden:

            # 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)

Durch diese Ergänzung sollte der gesamte Haupttreiber so aussehen:

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)

Wenn Sie storage.json löschen, um die Bereiche zu aktualisieren, und die aktualisierte Anwendung noch einmal ausführen, sollte die Ausgabe in etwa so aussehen, wobei die Cloud Vision-Analyse hinzugefügt wurde:

$ 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

Zusammenfassung

Nicht jeder verfügt über die erforderlichen Kenntnisse im Bereich des maschinellen Lernens, um eigene ML-Modelle zur Analyse von Daten zu erstellen und zu trainieren. Das Google Cloud-Team hat einige der vortrainierten Modelle von Google für den allgemeinen Gebrauch zur Verfügung gestellt und hinter APIs platziert, um KI und ML für alle

Wenn Sie Entwickler sind und eine API aufrufen können, steht Ihnen maschinelles Lernen zur Verfügung. Cloud Vision ist nur einer der API-Dienste, mit denen Sie Ihre Daten analysieren können. Weitere Informationen Der Code sollte jetzt mit dem Inhalt im Repository unter step3-vision/analyze_gsimg.py übereinstimmen.

11. Schritt 4: Bericht mit Google Tabellen erstellen

Bisher konnten Sie Unternehmensdaten archivieren und analysieren, aber was fehlt, ist eine Zusammenfassung dieser Arbeit. Fassen wir alle Ergebnisse in einem einzigen Bericht zusammen, den Sie Ihrem Chef vorlegen können. Was eignet sich besser für das Management als eine Tabelle?

Für die Google Sheets API sind keine zusätzlichen Importe erforderlich. Die einzige neue Information ist die Datei-ID einer bereits formatierten Tabelle, die bereits formatiert ist und auf eine neue Datenzeile wartet, daher die Konstante SHEET. Wir empfehlen Ihnen, eine neue Tabelle zu erstellen, die in etwa so aussieht:

4def78583d05300.png

Die URL für diese Tabelle sieht so aus: https://docs.google.com/spreadsheets/d/FILE_ID/edit. Schnapp dir FILE_ID und weise SHEET als String zu.

Wir haben auch eine winzige Funktion namens k_ize() eingefügt, die Byte in Kilobyte umwandelt und sie als Python-lambda definiert, da es sich um eine einfache Einzeiler handelt. Beide zusammen mit den anderen Konstanten sehen so aus:

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                 

Wie bei den vorherigen Schritten benötigen wir einen anderen Berechtigungsbereich, diesmal Lese-/Schreibzugriff für die Sheets API. SCOPES enthält jetzt alle vier erforderlichen:

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',
)                  

Erstellen Sie nun einen Dienstendpunkt für Google Tabellen in der Nähe der anderen, sodass er so aussieht:

# 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)

Die Funktion von sheet_append_row() ist unkompliziert: Nehmen Sie eine Datenzeile und die ID einer Tabelle und fügen Sie diese Zeile dieser Tabelle hinzu:

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')

Für den spreadsheets().values().append()-Aufruf werden die Datei-ID der Tabelle, ein Zellenbereich, die Eingabe der Daten sowie die Daten selbst benötigt. Die Datei-ID ist einfach, der Zellenbereich ist in A1-Schreibweise angegeben. Ein Bereich von „Sheet1“ bedeutet die gesamte Tabelle. Dies signalisiert der API, dass die Zeile nach allen Daten in der Tabelle angehängt werden soll. Es gibt zwei Möglichkeiten, wie die Daten in die Tabelle eingefügt werden sollen: „RAW“ (Geben Sie die Zeichenfolgendaten wörtlich ein) oder "USER_ENTERED". Schreiben Sie die Daten so, als ob ein Nutzer sie mit der Google Tabellen App über die Tastatur eingegeben hätte. Die Zellenformatierungsfunktionen werden dabei beibehalten.

Wenn der Aufruf erfolgreich ist, enthält der Rückgabewert nicht wirklich nützliche Informationen, daher haben wir uns dafür entschieden, die Anzahl der Zellen zu erhalten, die durch die API-Anfrage aktualisiert werden. Mit dem folgenden Code wird diese Funktion aufgerufen:

                # 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')

Die Google-Tabelle enthält Spalten mit Daten wie z. B. jedem übergeordneten „Unterverzeichnis“, den Speicherort der archivierten Datei in Cloud Storage (Bucket + Dateiname), der MIME-Typ der Datei, die Dateigröße (ursprünglich in Byte, aber mit k_ize() in Kilobyte konvertiert) und der Cloud Vision-Labelstring. Beachten Sie auch, dass der archivierte Speicherort ein Hyperlink ist, auf den Ihr Manager klicken kann, um zu bestätigen, dass er sicher gesichert wurde.

Der obige Codeblock wurde direkt nach der Anzeige der Ergebnisse von Cloud Vision hinzugefügt. Damit ist der Hauptteil der Anwendung nun abgeschlossen, auch wenn er strukturell etwas komplex ist:

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)

Wenn Sie storage.json ein letztes Mal löschen und die aktualisierte Anwendung noch einmal ausführen, sollte die Ausgabe in etwa so aussehen, wobei die Cloud Vision-Analyse hinzugefügt wurde:

$ 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

Die zusätzliche Ausgabezeile ist zwar nützlich, wird aber besser visualisiert, indem Sie einen Blick auf die aktualisierte Google-Tabelle werfen. Die letzte Zeile (Zeile 7 im Beispiel unten) wird dem vorhandenen Dataset zuvor hinzugefügt:

b53a5bc944734652.png

Zusammenfassung

In den ersten drei Schritten dieser Anleitung haben Sie eine Verbindung zu Google Workspace und Google Cloud APIs hergestellt, um Daten zu verschieben und zu analysieren. Das macht 80% der gesamten Arbeit aus. Letztendlich bedeutet dies jedoch nichts, wenn Sie nicht dem Management zeigen können, was Sie erreicht haben. Eine Zusammenfassung aller Ergebnisse in einem erstellten Bericht spricht für eine bessere Visualisierung der Ergebnisse.

Um die Nützlichkeit der Analyse weiter zu verbessern, könnte neben dem Schreiben der Ergebnisse in eine Tabelle eine mögliche Verbesserung darin bestehen, diese fünf Top-Labels für jedes Bild zu indexieren, sodass eine interne Datenbank aufgebaut werden kann, mit der autorisierte Mitarbeiter Bilder vom Suchteam abfragen können. Dies wird den Lesern jedoch als Übung überlassen.

Derzeit sind unsere Ergebnisse in einer Tabelle verfügbar, die vom Management aufgerufen werden kann. Der Code für Ihre App sollte in dieser Phase mit dem Code im Repository bei step4-sheets/analyze_gsimg.py übereinstimmen. Im letzten Schritt bereinigen Sie den Code und wandeln ihn in ein brauchbares Skript um.

12. *Letzter Schritt: Refaktorierung

(Optional) Eine funktionierende App ist gut – können wir sie verbessern? Ja, vor allem die Hauptanwendung, die durcheinander geraten scheint. Lassen Sie uns das in eine eigene Funktion einbauen und sie so steuern, dass Nutzereingaben statt fester Konstanten möglich sind. Wir machen das mit dem Modul argparse. Darüber hinaus öffnen wir einen Webbrowser-Tab, um die Tabelle anzuzeigen, nachdem wir die Datenzeile in sie geschrieben haben. Dies ist mit dem Modul webbrowser möglich. Verknüpfen Sie diese Importe mit den anderen, sodass die Top-Importe wie folgt aussehen:

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

Um diesen Code in anderen Anwendungen verwenden zu können, müssen wir die Ausgabe unterdrücken können. Dazu fügen wir das Flag DEBUG hinzu und fügen diese Zeile am Ende des Abschnitts „Konstanten“ oben hinzu:

DEBUG = False

Kommen wir nun zum Hauptteil. Beim Erstellen dieses Beispiels hätten Sie sich „unwohl“ gefühlt haben da unser Code mit jedem hinzugefügten Dienst eine weitere Verschachtelungsebene hinzufügt. Wenn Sie das auch so sehen, sind Sie nicht allein, da dies die Codekomplexität erhöht, wie in diesem Google-Test-Blogpost beschrieben.

Gemäß dieser Best Practice reorganisieren wir den Hauptteil der App in eine Funktion und return an jedem „Breakpoint“. anstelle der Verschachtelung (None, wenn ein Schritt fehlschlägt, und True, wenn alle erfolgreich sind):

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

Sie ist übersichtlicher und übersichtlicher und hinterlässt den rekursiven Eindruck von if-else. Gleichzeitig wird die Codekomplexität reduziert (siehe oben). Der letzte Teil des Puzzles besteht darin, Haupttreiber, die eine Anpassung durch den Nutzer ermöglichen und die Ausgabe minimieren (falls gewünscht):

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)

Wenn alle Schritte erfolgreich waren, startet das Skript einen Webbrowser in der Tabelle, in der die neue Datenzeile hinzugefügt wurde.

Zusammenfassung

storage.json muss nicht gelöscht werden, da keine Bereichsänderungen vorgenommen wurden. Wenn Sie die aktualisierte Anwendung noch einmal ausführen, wird ein neues Browserfenster für das geänderte Tabellenblatt geöffnet. Es werden weniger Ausgabezeilen angezeigt und die Option -h zeigt den Nutzern ihre Optionen, einschließlich -v, um die jetzt unterdrückten Ausgabezeilen wiederherzustellen, die Sie bereits gesehen haben:

$ 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

Mit den anderen Optionen können Nutzer andere Drive-Dateinamen, Cloud Storage-„Unterverzeichnis“ und Bucket-Namen, oben „N“ Ergebnisse aus Cloud Vision und Tabellen-Datei-IDs (Google Tabellen) Nach diesen letzten Updates sollte die endgültige Version Ihres Codes nun vollständig mit dem Inhalt im Repository unter final/analyze_gsimg.py und hier übereinstimmen:

'''
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)

Wir werden versuchen, den Inhalt dieser Anleitung auf dem neuesten Stand zu halten. Es kann jedoch vorkommen, dass das Repository die neueste Version des Codes enthält.

13. Glückwunsch!

In diesem Codelab gab es auf jeden Fall viel zu lernen – und genau das haben Sie erreicht, als Sie in einem der längeren Codelabs überstanden haben. Infolgedessen haben Sie ein mögliches Unternehmensszenario mit etwa 130 Zeilen Python in Angriff genommen, Google Cloud und Google Workspace genutzt und Daten zwischen ihnen verschoben, um eine funktionierende Lösung zu erstellen. Sehen Sie sich das Open-Source-Repository für alle Versionen dieser App an (weitere Informationen siehe unten).

Bereinigen

  1. Die Nutzung der Google Cloud APIs ist nicht kostenlos, solange die Google Workspace APIs durch Ihre monatliche Google Workspace-Abogebühr gedeckt sind (für Gmail-Nutzer gilt eine monatliche Gebühr von null). Für Google Workspace-Nutzer ist also keine API-Bereinigung bzw. Deaktivierung erforderlich. Für Google Cloud können Sie das Dashboard der Cloud Console aufrufen und auf der Karte „Abrechnung“ nachsehen. .
  2. Für Cloud Vision ist eine feste Anzahl von API-Aufrufen pro Monat kostenlos. Solange Sie innerhalb dieser Limits bleiben, müssen Sie weder etwas beenden noch Ihr Projekt deaktivieren oder löschen. Weitere Informationen zur Abrechnung und zum kostenlosen Kontingent der Vision API finden Sie auf der Preisseite der Vision API.
  3. Einige Nutzer von Cloud Storage erhalten pro Monat kostenlosen Speicherplatz. Wenn die Images, die Sie mit diesem Codelab archivieren, dieses Kontingent nicht überschreiten, entstehen Ihnen keine Kosten. Weitere Informationen zur Abrechnung und zum kostenlosen Kontingent von GCS finden Sie auf der Preisseite. Sie können Blobs im Cloud Storage-Browser ansehen und einfach löschen.
  4. Möglicherweise gilt für Ihre Nutzung von Google Drive auch ein Speicherkontingent. Wenn Sie es überschreiten (oder nah daran sind), können Sie in Betracht ziehen, das in diesem Codelab erstellte Tool zu verwenden, um diese Bilder in Cloud Storage zu archivieren, damit Sie mehr Speicherplatz auf Google Drive erhalten. Weitere Informationen zum Google Drive-Speicherplatz finden Sie auf der entsprechenden Preisseite für Google Workspace Basic- oder Gmail-/Privatnutzer.

Die meisten Google Workspace Business- und Enterprise-Abos bieten unbegrenzten Speicherplatz. Das kann jedoch dazu führen, dass Ihre Drive-Ordner unübersichtlich und/oder zu groß werden. Mit der App, die Sie in dieser Anleitung erstellt haben, können Sie überflüssige Dateien archivieren und Google Drive bereinigen.

Alternative Versionen

Während final/analyze_gsimg.py der „letzte“ ist offizielle Version, an der Sie in diesem Tutorial arbeiten, ist aber nicht das Ende der Geschichte. Ein Problem bei der endgültigen Version der App besteht darin, dass sie die älteren Authentifizierungsbibliotheken verwendet, die eingestellt wurden. Wir haben uns für diesen Pfad entschieden, weil die neueren Authentifizierungsbibliotheken zum Zeitpunkt dieses Schreibens einige wichtige Elemente nicht unterstützten: die Verwaltung des OAuth-Tokenspeichers und die Threadsicherheit.

Aktuelle (neuere) Authentifizierungsbibliotheken

Die älteren Authentifizierungsbibliotheken werden jedoch irgendwann nicht mehr unterstützt. Wir empfehlen Ihnen daher, Versionen, die die neueren (aktuellen) Authentifizierungsbibliotheken im Ordner alt des Repositorys verwenden, zu überprüfen, auch wenn sie nicht threadsicher sind (Sie können jedoch Ihre eigene Lösung erstellen). Suchen Sie nach Dateien mit *newauth* im Namen.

Google Cloud-Produkt-Clientbibliotheken

Google Cloud empfiehlt allen Entwicklern, bei der Nutzung von Google Cloud APIs die Produkt-Clientbibliotheken zu verwenden. Leider verfügen andere APIs, die nicht zu Google Cloud gehören, derzeit nicht über solche Bibliotheken. Die Verwendung der untergeordneten Bibliotheken ermöglicht eine konsistente API-Nutzung und bietet eine bessere Lesbarkeit. Ähnlich wie in der Empfehlung oben stehen im Ordner alt des Repositorys alternative Versionen mit Google Cloud-Produkt-Clientbibliotheken zur Verfügung. Suchen Sie nach Dateien mit *-gcp* im Namen.

Autorisierung über ein Dienstkonto

Wenn Sie ausschließlich in der Cloud arbeiten, gibt es in der Regel keine Daten von Menschen oder (menschlichen) Nutzern. Deshalb werden Dienstkonten und die Dienstkontoautorisierung in erster Linie mit Google Cloud verwendet. Da Google Workspace-Dokumente jedoch im Allgemeinen menschlichen Nutzern gehören, wird in dieser Anleitung die Autorisierung von Nutzerkonten verwendet. Das bedeutet aber nicht, dass Google Workspace APIs nicht mit Dienstkonten verwendet werden können. Solange diese Konten über die entsprechende Zugriffsebene verfügen, können sie auf jeden Fall in Anwendungen verwendet werden. Ähnlich wie im obigen Beispiel stehen Ihnen im Ordner alt des Repositorys alternative Versionen zur Verfügung, die die Dienstkontoautorisierung verwenden. Suchen Sie nach Dateien mit *-svc* im Namen.

Katalog der alternativen Versionen

Unten sind alle alternativen Versionen von final/analyze_gsimg.py aufgeführt, die jeweils eine oder mehrere der oben genannten Attribute haben. Suchen Sie im Dateinamen der einzelnen Versionen nach:

  • oldauth“ für Versionen, die die älteren Authentifizierungsbibliotheken verwenden (zusätzlich zu final/analyze_gsimg.py)
  • newauth“ für Nutzer der aktuellen/neueren Authentifizierungsbibliotheken
  • gcp“ für Nutzer von Google Cloud-Produkt-Clientbibliotheken wie google-cloud-storage usw.
  • svc“ für Nutzer, die anstelle eines Nutzerkontos eine Dienstkonto-Authentifizierung („svc acct“) verwenden

Hier sind alle Versionen:

Dateiname

Beschreibung

final/analyze_gsimg.py

Die Hauptstichprobe die älteren Authentifizierungsbibliotheken verwendet.

alt/analyze_gsimg-newauth.py

Wie final/analyze_gsimg.py, verwendet aber die neueren Authentifizierungsbibliotheken

alt/analyze_gsimg-oldauth-gcp.py

Wie final/analyze_gsimg.py, verwendet aber die Clientbibliotheken des Google Cloud-Produkts

alt/analyze_gsimg-newauth-gcp.py

Wie alt/analyze_gsimg-newauth.py, verwendet aber die Clientbibliotheken des Google Cloud-Produkts

alt/analyze_gsimg-oldauth-svc.py

Wie bei final/analyze_gsimg.py, verwendet jedoch SVC-Konto statt Nutzerkonto

alt/analyze_gsimg-newauth-svc.py

Wie bei alt/analyze_gsimg-newauth.py, verwendet jedoch SVC-Kontoauthentifizierung anstelle des Nutzerkontos

alt/analyze_gsimg-oldauth-svc-gcp.py

Wie alt/analyze_gsimg-oldauth-svc.py, verwendet aber die Google Cloud-Produkt-Clientbibliotheken und ist identisch mit alt/analyze_gsimg-oldauth-gcp.py, verwendet jedoch „svc acct auth“ anstelle des Nutzerkontos

alt/analyze_gsimg-newauth-svc-gcp.py

Wie alt/analyze_gsimg-oldauth-svc-gcp.py, verwendet aber die neueren Authentifizierungsbibliotheken

In Verbindung mit der ursprünglichen final/analyze_gsimg.py stehen Ihnen alle möglichen Kombinationen der endgültigen Lösung zur Verfügung , unabhängig von Ihrer Google API-Entwicklungsumgebung, und Sie können diejenige auswählen, die Ihren Anforderungen am besten entspricht. Eine ähnliche Erklärung finden Sie unter alt/README.md.

Zusätzliche Studie

Im Folgenden finden Sie einige Ideen, wie Sie diese Übung einen oder zwei Schritte weiter vorantreiben können. Der Problemsatz, den die aktuelle Lösung bewältigen kann, kann erweitert werden, um folgende Verbesserungen vorzunehmen:

  1. (Mehrere Bilder in Ordnern) Anstatt ein Bild zu verarbeiten, nehmen wir an, Ihre Bilder befinden sich in Google Drive-Ordnern.
  2. Mehrere Bilder in ZIP-Dateien: Wie wäre es mit ZIP-Archiven mit Bilddateien anstatt in einem Ordner mit Bildern? Wenn Sie Python verwenden, sollten Sie das Modul zipfile berücksichtigen.
  3. (Vision-Labels analysieren) Ähnliche Bilder werden in Clustern zusammengefasst. Suchen Sie zum Beispiel zuerst nach den häufigsten, dann nach dem zweithäufigsten usw.
  4. (Diagramme erstellen) Folge Nr. 3: Diagramme mit der Sheets API generieren, die auf der Vision API-Analyse und -Kategorisierung basieren
  5. (Dokumente kategorisieren) Anstatt Bilder mit der Cloud Vision API zu analysieren, nehmen wir an, Sie haben PDF-Dateien, die Sie mit der Cloud Natural Language API kategorisieren können. Mit den oben genannten Lösungen können sich diese PDFs in Drive-Ordnern oder ZIP-Archiven in Drive befinden.
  6. (Präsentationen erstellen) Mit der Slides API können Sie aus den Inhalten des Google Tabellen-Berichts eine Präsentation generieren. Inspiration finden Sie in diesem Blogpost und in Video zum Generieren von Folien aus Tabellendaten.
  7. (Als PDF exportieren) Exportieren Sie die Tabelle und/oder die Präsentation als PDF. Dies ist jedoch weder eine Funktion der Google Tabellen API noch der Google Präsentationen API. Tipp: Google Drive API. Zusätzlicher Schritt: Führen Sie die PDF-Dateien aus Google Tabellen und Google Präsentationen mithilfe von Tools wie Ghostscript (Linux, Windows) oder Combine PDF Pages.action (Mac OS X) zu einer Master-PDF zusammen.

Weitere Informationen

Codelabs

Allgemein

Google Workspace

Google Cloud

Lizenz

Dieser Text ist mit einer Creative Commons Attribution 2.0 Generic License lizenziert.