Archiwizowanie, analizowanie i generowanie raportów w Google Workspace oraz Google Cloud,

1. Omówienie

W ramach tych ćwiczeń w Codelabs przewiduje się możliwy przepływ pracy w firmie: archiwizację obrazów, analizę i generowanie raportów. Wyobraź sobie, że Twoja organizacja ma serię zdjęć zajmujących przestrzeń na ograniczonym zasobie. Chcesz zarchiwizować te dane, przeanalizować te obrazy, a przede wszystkim wygenerować raport z podsumowaniem zarchiwizowanych lokalizacji i wyników analizy, zebrany i gotowy do wykorzystania przez zarządzanie. Google Cloud udostępnia narzędzia, które to umożliwiają, wykorzystując interfejsy API z 2 linii usług: Google Workspace (wcześniej G Suite lub Google Apps) i Google Cloud (wcześniej GCP).

W naszym scenariuszu obrazy użytkownika biznesowego znajdują się na Dysku Google. Warto utworzyć „chłodniejsze” utwory, tańsze miejsce, na przykład klasy pamięci dostępne w Google Cloud Storage. Google Cloud Vision umożliwia programistom łatwą integrację w aplikacjach funkcji wykrywania obrazów, w tym wykrywania obiektów i punktów orientacyjnych, optycznego rozpoznawania znaków (OCR) itp. Arkusz kalkulacyjny w Arkuszach Google jest przydatnym narzędziem do wizualizacji, które podsumowuje wszystkie te informacje dla szefa.

Ukończenie tych ćwiczeń z programowania w celu stworzenia rozwiązania wykorzystującego całą platformę Google Cloud zainspiruje Cię do tworzenia rozwiązań, które będą jeszcze bardziej przydatne dla Twojej organizacji lub klientów.

Czego się nauczysz

  • Jak korzystać z Cloud Shell
  • Jak uwierzytelniać żądania do interfejsu API
  • Jak zainstalować bibliotekę klienta interfejsów API Google dla Pythona
  • Jak włączyć interfejsy API Google
  • Jak pobierać pliki z Dysku Google
  • Jak przesyłać obiekty/bloby do Cloud Storage
  • Jak analizować dane za pomocą Cloud Vision
  • Jak zapisywać wiersze w Arkuszach Google

Czego potrzebujesz

  • konto Google (konta Google Workspace mogą wymagać zatwierdzenia przez administratora),
  • projekt Google Cloud z aktywnym kontem rozliczeniowym Google Cloud,
  • znajomość poleceń terminala/powłoki systemu operacyjnego,
  • podstawowe umiejętności w języku Python (2 lub 3), ale możesz używać dowolnego obsługiwanego języka;

Znajomość 4 usług Google Cloud wymienionych powyżej może być pomocna, ale nie jest konieczna. Jeśli masz czas, żeby zapoznać się z każdym z nich oddzielnie, przed wykonaniem tych zadań możesz wykonać ćwiczenia z programowania:

Ankieta

Jak wykorzystasz ten samouczek?

Tylko do przeczytania Przeczytaj go i wykonaj ćwiczenia

Jak oceniasz swoje doświadczenia z językiem Python?

Początkujący Poziom średnio zaawansowany Biegły

Jak oceniasz korzystanie z usług Google Cloud?

Początkujący Poziom średnio zaawansowany Biegły

Jak oceniasz swoje wrażenia z korzystania z usług Google Workspace dla deweloperów?

Początkujący Poziom średnio zaawansowany Biegły

Czy chcesz zobaczyć więcej kategorii dotyczących działalności biznesowej? z ćwiczeń w Codelabs i tych, które przedstawiają nowe funkcje usługi?

Tak Nie Więcej w obu przypadkach
.

2. Konfiguracja i wymagania

Samodzielne konfigurowanie środowiska

  1. Zaloguj się w konsoli Google Cloud i utwórz nowy projekt lub wykorzystaj już istniejący. Jeśli nie masz jeszcze konta Gmail ani Google Workspace, musisz je utworzyć.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Nazwa projektu jest wyświetlaną nazwą uczestników tego projektu. To ciąg znaków, który nie jest używany przez interfejsy API Google. W każdej chwili możesz ją zmienić.
  • Identyfikator projektu musi być unikalny we wszystkich projektach Google Cloud i nie można go zmienić (nie można go zmienić po ustawieniu). Cloud Console automatycznie wygeneruje unikalny ciąg znaków. zwykle nieważne, co ona jest. W większości ćwiczeń z programowania konieczne jest odwołanie się do identyfikatora projektu (zwykle nazywa się on PROJECT_ID). Jeśli nie podoba Ci się wygenerowany identyfikator, możesz wygenerować kolejny losowy. Możesz też spróbować własnych sił i sprawdzić, czy jest dostępna. Potem nie będzie można go zmienić. Pozostanie ono przez czas trwania projektu.
  • Dostępna jest trzecia wartość, numer projektu, z którego korzystają niektóre interfejsy API. Więcej informacji o wszystkich 3 wartościach znajdziesz w dokumentacji.
  1. Następnie musisz włączyć płatności w Cloud Console, aby korzystać z zasobów Cloud/interfejsów API. Ukończenie tego ćwiczenia z programowania nie powinno kosztować zbyt wiele. Aby wyłączyć zasoby, aby nie naliczać opłat po zakończeniu tego samouczka, możesz usunąć utworzone zasoby lub cały projekt. Nowi użytkownicy Google Cloud mogą skorzystać z programu bezpłatnego okresu próbnego o wartości 300 USD.

Uruchamianie Cloud Shell

Podsumowanie

Kod możesz tworzyć lokalnie na laptopie, ale drugorzędnym celem tego ćwiczenia jest nauczenie się używania Google Cloud Shell – środowiska wiersza poleceń działającego w chmurze w nowoczesnej przeglądarce.

Aktywowanie Cloud Shell

  1. W konsoli Cloud kliknij Aktywuj Cloud Shell 853e55310c205094.png.

55efc1aaa7a4d3ad.png

Jeśli dopiero zaczynasz korzystać z Cloud Shell, wyświetli się ekran pośredni (w części strony widocznej po przewinięciu) z opisem tej funkcji. W takim przypadku kliknij Dalej (nie zobaczysz go więcej). Tak wygląda ten jednorazowy ekran:

9c92662c6a846a5c.png

Uzyskanie dostępu do Cloud Shell i połączenie się z nim powinno zająć tylko kilka chwil.

9f0e51b578fecce5.png

Ta maszyna wirtualna ma wszystkie potrzebne narzędzia dla programistów. Zawiera stały katalog domowy o pojemności 5 GB i działa w Google Cloud, co znacznie zwiększa wydajność sieci i uwierzytelnianie. Większość czynności z tego ćwiczenia z programowania można wykonać w przeglądarce lub na Chromebooku.

Po nawiązaniu połączenia z Cloud Shell powinno pojawić się informacja, że użytkownik jest już uwierzytelniony i że projekt jest już ustawiony na identyfikator Twojego projektu.

  1. Uruchom to polecenie w Cloud Shell, aby potwierdzić, że jesteś uwierzytelniony:
gcloud auth list

Dane wyjściowe polecenia

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

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Uruchom to polecenie w Cloud Shell, aby sprawdzić, czy polecenie gcloud zna Twój projekt:
gcloud config list project

Dane wyjściowe polecenia

[core]
project = <PROJECT_ID>

Jeśli tak nie jest, możesz go ustawić za pomocą tego polecenia:

gcloud config set project <PROJECT_ID>

Dane wyjściowe polecenia

Updated property [core/project].

3. Potwierdź środowisko Pythona

To ćwiczenie w Codelabs wymaga używania języka Python (chociaż wiele języków jest obsługiwanych przez biblioteki klienta interfejsów API Google, więc możesz śmiało stworzyć coś podobnego w swoim ulubionym narzędziu dla programistów i używać Pythona jako pseudokodu. To ćwiczenia z programowania obsługują języki Python 2 i 3, ale zalecamy jak najszybsze przejście na wersję 3.x.

Cloud Shell to wygodne narzędzie dostępne dla użytkowników bezpośrednio z konsoli Google Cloud, które nie wymaga lokalnego środowiska programistycznego, więc cały samouczek można przeprowadzić w całości w chmurze za pomocą przeglądarki. Dokładniej rzecz biorąc, na potrzeby tego ćwiczenia z programowania w Cloud Shell zainstalowano już obie wersje Pythona.

W Cloud Shell jest zainstalowany IPython: interaktywny tłumacz języka Python wyższego poziomu, który zalecamy, zwłaszcza jeśli należysz do społeczności osób zajmujących się badaniami danych lub systemami uczącymi się. Jeśli tak, domyślnym interpreterem notatników Jupyter jest IPython, a także Colab notatników Jupyter hostowanych przez Google Research.

IPython faworyzuje najpierw interpretera Pythona 3, ale jeśli wersja 3.x nie jest dostępna, wraca do Pythona 2. Dostęp do IPython można uzyskać z Cloud Shell, ale można go też zainstalować w lokalnym środowisku programistycznym. Wyjdź za pomocą klawiszy ^D (Ctrl + d) i zaakceptuj ofertę wyjścia. Przykładowe dane wyjściowe uruchamiania funkcji ipython będą wyglądać tak:

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

Jeśli nie podoba Ci się IPython, zdecydowanie możesz użyć standardowego, interaktywnego interpretera Pythona (czyli Cloud Shell lub lokalnego środowiska programistycznego) (wyjście także za pomocą ^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.
>>>

W ćwiczeniach w Codelabs zakładamy też, że masz narzędzie instalacyjne pip (menedżer pakietów Pythona i mechanizm rozwiązywania zależności). Jest on dostarczany w pakiecie z wersją 2.7.9 lub nowszym albo 3.4 i nowszymi. Jeśli masz starszą wersję Pythona, instrukcje instalacji znajdziesz w tym przewodniku. W zależności od uprawnień możesz potrzebować dostępu na poziomie sudo lub superużytkownika, ale zwykle nie jest to konieczne. Możesz też bezpośrednio użyć metody pip2 lub pip3 do wykonania pip na potrzeby określonych wersji Pythona.

Pozostała część ćwiczenia w Codelabs zakłada, że używasz Pythona 3. Jeśli znacznie różnisz się od wersji 3.x, otrzymasz szczegółowe instrukcje dla Pythona 2.

[opcjonalnie] Tworzenie i używanie środowisk wirtualnych

Ta sekcja jest opcjonalna i bardzo wymagana tylko dla tych, którzy muszą używać środowiska wirtualnego w tych ćwiczeniach z programowania (zgodnie z informacjami na pasku bocznym ostrzeżenia powyżej). Jeśli masz na komputerze tylko język Python 3, po prostu uruchom to polecenie, by utworzyć środowisko wirtualne o nazwie my_env (w razie potrzeby możesz wybrać inną nazwę):

virtualenv my_env

Jeśli jednak masz zarówno język Python 2, jak 3 na komputerze, zalecamy zainstalowanie środowiska wirtualnego w języku Python 3, co można zrobić za pomocą -p flag w ten sposób:

virtualenv -p python3 my_env

„Aktywuj”, aby wpisać nowo utworzony virtualenv w następujący sposób:

source my_env/bin/activate

Potwierdź, że jesteś w środowisku, obserwując prompt powłoki, który jest poprzedzony nazwą środowiska, np.

(my_env) $ 

Teraz powinno być już możliwe pip install wszystkie wymagane pakiety, wykonanie kodu w ramach tego rozwiązania itp. Inną korzyścią jest to, że w przypadku całkowitego bałaganu Twoja instalacja Pythona może być uszkodzona itd., możesz zniszczyć całe środowisko bez wpływu na pozostałą część systemu.

4. Zainstaluj bibliotekę klienta interfejsów API Google dla Pythona

To ćwiczenie w Codelabs wymaga użycia biblioteki klienta interfejsów API Google dla Pythona, więc jest to prosty proces instalacji lub nie musisz nic robić.

Wcześniej zalecamy korzystanie z Cloud Shell. Cały samouczek możesz ukończyć w przeglądarce w chmurze. Innym powodem, dla którego warto korzystać z Cloud Shell, jest to, że wiele popularnych narzędzi dla programistów i niezbędnych bibliotek jest już wstępnie zainstalowanych.

*Instalowanie bibliotek klienta

(Opcjonalnie) Możesz pominąć ten krok, jeśli używasz Cloud Shell lub środowiska lokalnego, w którym masz już zainstalowane biblioteki klienta. Zrobisz to tylko wtedy, gdy programujesz lokalnie i nie masz (lub nie masz pewności) takiej instalacji. Najłatwiej jest użyć dodatku pip (lub pip3) do instalacji (w razie potrzeby także aktualizacji samego programu pip):

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

Potwierdź instalację

To polecenie instaluje bibliotekę klienta oraz wszystkie pakiety, od których zależy. Niezależnie od tego, czy używasz Cloud Shell, czy własnego środowiska, sprawdź, czy biblioteka klienta jest zainstalowana, importując niezbędne pakiety i czy nie występują błędy importu (ani dane wyjściowe):

python3 -c "import googleapiclient, httplib2, oauth2client"

Jeśli zamiast tego używasz Pythona 2 (z Cloud Shell), zobaczysz ostrzeżenie, że obsługa została wycofana:

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

Gdy będzie można uruchomić ten import, przeprowadź „test” (brak błędów/danych wyjściowych), możesz zacząć komunikować się z interfejsami API Google.

Podsumowanie

Ponieważ jest to ćwiczenia z programowania na poziomie średnio zaawansowanym, zakładamy, że masz już doświadczenie w tworzeniu za pomocą projektów w konsoli. Jeśli dopiero zaczynasz korzystać z interfejsów API Google, a w szczególności z interfejsów Google Workspace API, zapoznaj się najpierw z ćwiczeniem z programowania dla interfejsów Google Workspace API. Jeśli wiesz, jak utworzyć (lub wykorzystać ponownie istniejące) dane logowania na konto użytkownika (nie konto usługi), upuść plik client_secret.json do katalogu służbowego, pomiń następny moduł i przejdź do sekcji „Włącz interfejsy API Google”.

5. *Autoryzacja żądań do interfejsu API (autoryzacja użytkownika)

Możesz pominąć tę sekcję, jeśli masz już utworzone dane logowania do autoryzacji konta użytkownika i znasz ten proces. Różni się ona od autoryzacji konta usługi, której technika się różni, dlatego przejdź dalej poniżej.

Wprowadzenie do autoryzacji (oraz niektóre uwierzytelnianie)

Aby móc wysyłać żądania do interfejsów API, aplikacja musi mieć odpowiednią autoryzację. Uwierzytelnianie, podobnie jak tu, opisuje dane logowania. Musisz się uwierzytelnić, gdy logujesz się na konto Google za pomocą loginu. hasła. Po uwierzytelnieniu kolejnym krokiem jest sprawdzenie, czy masz uprawnienia do uzyskiwania dostępu do danych, takich jak pliki blob w Cloud Storage czy osobiste pliki użytkownika na Dysku Google, czy też Twój kod.

Interfejsy API Google obsługują kilka typów autoryzacji, ale w przypadku użytkowników interfejsu G Suite API najczęściej używana jest autoryzacja, ponieważ przykładowa aplikacja objęta tym ćwiczeniem uzyskuje dostęp do danych należących do użytkowników. Ci użytkownicy muszą zezwolić aplikacji na dostęp do swoich danych. Oznacza to, że kod musi uzyskać dane logowania OAuth2 do konta użytkownika.

Aby uzyskać dane logowania OAuth2 do autoryzacji użytkownika, wróć do menedżera API i wybierz „Dane logowania” na lewym panelu nawigacyjnym:

635af008256d323.png

Wszystkie swoje dane logowania zobaczysz w trzech osobnych sekcjach:

fd2f4133b406d572.png

Pierwsze dotyczy kluczy interfejsu API, drugiego identyfikatora klienta OAuth 2.0, a ostatnich kont usługi OAuth2 – tego, który znajduje się w środku.

Tworzę dane logowania

U góry strony Dane logowania kliknij przycisk + Utwórz dane logowania. Otworzy się okno, w którym wybierz opcję „Identyfikator klienta OAuth”.

b17b663668e38787.png

Na następnym ekranie są do wyboru 2 działania: skonfigurowanie „ekranu zgody” autoryzacji aplikacji. oraz typ aplikacji:

4e0b967c9d70d262.png

Jeśli nie masz ustawionego ekranu zgody, zobaczysz w konsoli ostrzeżenie. Musisz to zrobić teraz. (Pomiń te kroki, jeśli Twój ekran zgody został już skonfigurowany).

Kliknij „Skonfiguruj ekran zgody”. w którym należy wybrać „Z zewnątrz” app (lub „Wewnętrzna”, jeśli korzystasz z G Suite):

f17e97b30d994b0c.png

Na potrzeby tego ćwiczenia nie ma znaczenia, którą opcję wybierzesz, ponieważ nie publikujesz przykładowego ćwiczenia z programowania. Większość użytkowników wybierze „Z zewnątrz” może pojawić się bardziej złożony ekran, ale tak naprawdę wystarczy wpisać „Nazwa aplikacji” u góry:

b107ab81349bdad2.png

Na razie potrzebujesz jedynie nazwy aplikacji, więc wybierz osobę, która będzie wykorzystywała wykonywane przez Ciebie ćwiczenia, a następnie kliknij Zapisz.

Tworzę identyfikator klienta OAuth (uwierzytelnianie konta użytkownika)

Teraz wróć na kartę Dane logowania, aby utworzyć identyfikator klienta OAuth2. Tutaj znajdziesz różne identyfikatory klienta OAuth, które możesz utworzyć:

5ddd365ac0af1e34.png

Opracowujemy narzędzie wiersza poleceń – Inne. Wybierz je, a następnie kliknij przycisk Utwórz. Wybierz nazwę identyfikatora klienta odpowiadającą tworzonej aplikacji lub po prostu użyj nazwy domyślnej, którą zwykle jest „Inny klient N”.

Zapisuję dane logowania

  1. Pojawi się okno z nowymi danymi logowania. kliknij OK, aby zamknąć

8bec84d82cb104d7

  1. Wróć na stronę Dane logowania i przewiń w dół do sekcji „Identyfikatory klienta OAuth2”. znajdź i kliknij ikonę pobierania f54b28417901b3aa.png w prawym dolnym rogu nowo utworzonego identyfikatora klienta. 1b4e8d248274a338.png
  2. Otworzy się okno umożliwiające zapisanie pliku o nazwie client_secret-LONG-HASH-STRING.apps.googleusercontent.com.json, który prawdopodobnie znajduje się w folderze Pobrane. Zalecamy skrócenie nazwy do prostszej nazwy, na przykład client_secret.json (z której korzysta przykładowa aplikacja), a następnie zapisanie jej w katalogu lub folderze, w którym będziesz tworzyć przykładową aplikację w ramach tego ćwiczenia w programie.

Podsumowanie

Teraz możesz włączyć interfejsy API Google wykorzystywane w tym ćwiczeniu z programowania. Dodatkowo jako nazwę aplikacji na ekranie akceptacji OAuth wybraliśmy „Demonstrację interfejsu Vision API”, więc będzie to widoczne na następnych zrzutach ekranu.

6. Włączanie interfejsów API Google

W ramach tego ćwiczenia w Codelabs używane są 4 (4) interfejsy API Google Cloud, parę z Google Cloud (Cloud Storage i Cloud Vision) oraz druga para z Google Workspace (Dysk Google i Arkusze Google). Poniżej znajdziesz ogólne instrukcje włączania interfejsów API Google. Gdy już wiesz, jak włączyć jeden interfejs API, pozostałe działają podobnie.

Niezależnie od tego, którego interfejsu API Google chcesz używać w aplikacji, muszą one być włączone. Interfejsy API można włączać z poziomu wiersza poleceń lub konsoli Cloud. Proces włączania interfejsów API przebiega w taki sam sposób, więc po włączeniu jednego z nich możesz w podobny sposób włączać inne.

Opcja 1. Interfejs wiersza poleceń gcloud (Cloud Shell lub środowisko lokalne)

Chociaż włączanie interfejsów API z poziomu konsoli Cloud jest bardziej powszechne, niektórzy deweloperzy wolą robić wszystko z poziomu wiersza poleceń. Aby to zrobić, musisz wyszukać „nazwę usługi” interfejsu API. To wygląda na adres URL: SERVICE_NAME.googleapis.com. Znajdziesz je na wykresie obsługiwanych usług. Możesz też automatycznie wysyłać zapytania na ich temat za pomocą interfejsu Google Discovery API.

Dzięki tym informacjom za pomocą Cloud Shell (lub lokalnego środowiska programistycznego z zainstalowanym narzędziem wiersza poleceń gcloud) możesz włączyć interfejs API lub usługę w ten sposób:

gcloud services enable SERVICE_NAME.googleapis.com

Przykład 1: włączanie interfejsu Cloud Vision API

gcloud services enable vision.googleapis.com

Przykład 2: włączanie bezserwerowej platformy obliczeniowej Google App Engine

gcloud services enable appengine.googleapis.com

Przykład 3: włączenie wielu interfejsów API za pomocą jednego żądania. Jeśli na przykład w ramach tego ćwiczenia w Codelabs znajdują się osoby wdrażające aplikację za pomocą interfejsu Cloud Translation API w App Engine, Cloud Functions i Cloud Run, wiersz poleceń będzie wyglądać tak:

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

To polecenie włącza platformy App Engine, Cloud Functions, Cloud Run i Cloud Translation API. Dodatkowo umożliwia korzystanie z Cloud Artifact Registry, ponieważ tam też obrazy kontenerów muszą być zarejestrowane przez system Cloud Build, aby możliwe było wdrożenie w Cloud Run.

Możesz także skorzystać z kilku poleceń, aby wyświetlić interfejsy API do włączenia lub które interfejsy API zostały już włączone w Twoim projekcie.

Przykład 4: Zapytanie o interfejsy API Google dostępne do włączenia w projekcie

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

Przykład 5: zapytanie dotyczące interfejsów API Google włączone w projekcie

gcloud services list

Więcej informacji o powyższych poleceniach znajdziesz w dokumentacji dotyczącej włączania i wyłączania usług oraz usług informacji o produktach.

Opcja 2. Konsola Cloud

Interfejsy API Google możesz też włączyć w menedżerze interfejsów API. W konsoli Cloud otwórz Menedżer interfejsów API. Na tej stronie panelu znajdziesz informacje o ruchu w aplikacji, wykresy przedstawiające żądania i błędy generowane przez aplikację oraz czas odpowiedzi aplikacji:

df4a0a5e00d29ffc.png

Poniżej tych wykresów znajdziesz listę interfejsów API Google włączonych w Twoim projekcie:

5fcf10e5a05cfb97.png

Aby włączyć (lub wyłączyć) interfejsy API, kliknij Włącz interfejsy API i usługi u góry strony:

eef4e5e863f4db66.png

Możesz też kliknąć lewy pasek nawigacyjny i wybrać Interfejsy API UsługiBiblioteka:

6eda5ba145b30b97.png

W obu przypadkach otworzy się strona Biblioteka interfejsów API:

5d4f1c8e7cf8df28.png

Wpisz nazwę interfejsu API, aby wyszukać i zobaczyć pasujące wyniki:

35bc4b9cf72ce9a4.png

Wybierz interfejs API, który chcesz włączyć, i kliknij przycisk Włącz:

9574a69ef8d9e8d2.png

Proces włączania wszystkich interfejsów API przebiega podobnie niezależnie od tego, którego interfejsu API Google chcesz używać.

Koszt

Wielu interfejsów API Google można używać bez opłat, jednak korzystanie z większości interfejsów API i usług Google Cloud wiąże się z pewnymi kosztami. Podczas włączania Cloud APIs może pojawić się prośba o podanie aktywnego konta rozliczeniowego. Jednak niektóre usługi Google Cloud mają atrybut „Zawsze bezpłatne” tier, który musisz przekroczyć, aby naliczać opłaty.

Nowi użytkownicy Google Cloud kwalifikują się do skorzystania z bezpłatnego okresu próbnego. Obecnie cena wynosi 300 USD przez pierwsze 90 dni. Ćwiczenia z programowania zazwyczaj nie wiążą się z żadnymi opłatami, dlatego zalecamy, aby wstrzymać się z bezpłatnym okresem próbnym, dopóki nie zdecydujesz się na wypróbowanie go, zwłaszcza że jest to oferta jednorazowa. Limity poziomu bezpłatnego nie wygasają i nie mają zastosowania niezależnie od tego, czy korzystasz z bezpłatnego okresu próbnego.

Przed włączeniem interfejsu API użytkownicy powinni zapoznać się z informacjami o cenach dowolnego interfejsu API (np. stronie z cennikiem Cloud Vision API ), szczególnie zwracając uwagę na to, czy jest to poziom bezpłatny, a jeśli tak, to co to jest. Dopóki nie zmieścisz się w ustalonych limitach dziennych lub miesięcznych, nie poniesiesz żadnych opłat. Ceny i poziomy bezpłatne różnią się w zależności od interfejsów API grup produktów Google. Przykłady:

Różne usługi Google są rozliczane w różny sposób, dlatego zapoznaj się z odpowiednią dokumentacją.

Podsumowanie

Po włączeniu Cloud Vision włącz w ten sam sposób 3 pozostałe interfejsy API (Dysk Google, Cloud Storage, Arkusze Google). W Cloud Shell użyj narzędzia gcloud services enable lub konsoli Cloud:

  1. Wróć do biblioteki interfejsów API
  2. Rozpocznij wyszukiwanie, wpisując kilka liter jego nazwy
  3. Wybierz odpowiedni interfejs API i
  4. Włącz

Powtarzaj aż do skutku. W przypadku Cloud Storage jest kilka możliwości: wybierz „Google Cloud Storage JSON API”. Interfejs Cloud Storage API będzie też oczekiwać aktywnego konta rozliczeniowego.

7. Krok 0. Skonfiguruj importowanie i kod autoryzacji

To początek średniej wielkości fragmentu kodu, więc stosowanie się do elastycznych metod pomaga zapewnić powszechną, stabilną i działającą infrastrukturę przed wdrożeniem głównej aplikacji. Sprawdź, czy plik client_secret.json jest dostępny w bieżącym katalogu i podczas uruchamiania ipython oraz wpisz ten fragment kodu lub zapisz go w pliku analyze_gsimg.py i uruchom go z powłoki (preferowana jest ta druga opcja, ponieważ nadal będziemy dodawać kod do przykładowego kodu):

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)

Ten podstawowy komponent zawiera bloki kodu do importowania modułów i pakietów, przetwarzania danych uwierzytelniających użytkowników i tworzenia punktów końcowych usługi interfejsu API. Najważniejsze fragmenty kodu, które należy sprawdzić:

  • Zaimportowanie funkcji print() zapewnia zgodność tego przykładowego języka Python 2–3 z językiem Python 2–3, a zaimportowanie z biblioteki Google zapewnia dostęp do wszystkich narzędzi niezbędnych do komunikowania się z interfejsami API Google.
  • Zmienna SCOPES reprezentuje uprawnienia, o które prosi użytkownik – na razie istnieje tylko jedno: uprawnienie do odczytu danych z jego Dysku Google
  • Pozostała część kodu przetwarzania danych logowania jest odczytywana w tokenach OAuth2 zapisanych w pamięci podręcznej i może zostać zaktualizowana do nowego tokena dostępu z tokenem odświeżania, jeśli pierwotny token dostępu wygasł.
  • Jeśli nie utworzono żadnych tokenów lub nie udało się pobrać prawidłowego tokena dostępu z innego powodu, użytkownik musi przejść przez trzyetapowy proces OAuth2 (3LO): utwórz okno z prośbami o uprawnienia i poproś użytkownika o jego zaakceptowanie. Gdy to zrobi, aplikacja będzie kontynuowana. W przeciwnym razie tools.run_flow() zgłosi wyjątek i zatrzymanie wykonywania.
  • Gdy użytkownik przyzna uprawnienia, tworzony jest klient HTTP komunikujący się z serwerem. Ze względów bezpieczeństwa wszystkie żądania są podpisywane przy użyciu danych logowania użytkownika. Następnie tworzony jest punkt końcowy usługi Google Drive API (wersja 3) z tym klientem HTTP i przypisany do DRIVE.

Uruchamianie aplikacji

Gdy pierwszy raz uruchomisz skrypt, nie będzie on miał dostępu do plików użytkownika na Dysku (w Twoim). Dane wyjściowe wyglądają tak, gdy wykonywanie jest wstrzymane:

$ 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

Jeśli pracujesz z Cloud Shell, przejdź od razu do sekcji „Z Cloud Shell”. a następnie przewiń do odpowiednich ekranów w sekcji „Z lokalnego środowiska programistycznego”. w razie potrzeby.

Z lokalnego środowiska programistycznego

Skrypt wiersza poleceń jest wstrzymany podczas otwierania okna przeglądarki. Może wyświetlić się przerażająca strona z ostrzeżeniem, która będzie wyglądać tak:

149241d33871a141.png

Jest to uzasadnione, ponieważ próbujesz uruchomić aplikację, która uzyskuje dostęp do danych użytkownika. To jest tylko aplikacja w wersji demonstracyjnej, a to Ty jesteś jej deweloperem, więc mamy nadzieję, że ufasz na tyle, by kontynuować. Aby to lepiej zrozumieć, postaw się na miejscu użytkownika: zobaczysz prośbę o zezwolenie innej osobie na dostęp do Twoich danych. Jeśli zamierzasz opublikować taką aplikację, musisz przejść proces weryfikacji, aby użytkownicy nie widzieli tego ekranu.

Po kliknięciu linku „Przejdź do niebezpiecznych” aplikacja” pojawi się okno uprawnień OAuth2, które będzie wyglądać mniej więcej tak:

a122eb7468d0d34e.png

Okno procesu OAuth2 odzwierciedla uprawnienia, o które prosi deweloper (za pomocą zmiennej SCOPES). W tym przypadku jest to możliwość wyświetlania i pobierania plików z Dysku Google użytkownika. W kodzie aplikacji te zakresy uprawnień są wyświetlane jako identyfikatory URI, ale są tłumaczone na język określony przez język użytkownika. W tym przypadku użytkownik musi jednoznacznie autoryzować wymagane uprawnienia. W przeciwnym razie zostanie zgłoszony wyjątek, który uniemożliwi kontynuowanie działania skryptu.

Może się nawet pojawić jeszcze jedno okno z prośbą o potwierdzenie:

bf171080dcd6ec5.png

UWAGA: niektóre przeglądarki korzystają z wielu przeglądarek zalogowanych na różnych kontach, więc to żądanie autoryzacji może trafić do niewłaściwej karty lub niewłaściwego okna przeglądarki. Być może trzeba będzie wyciąć i wkleić link tego żądania w przeglądarce, na której zalogujesz się na właściwe konto.

Z Cloud Shell

W Cloud Shell nie pojawia się żadne okno przeglądarki, przez co utkniesz w jakimś miejscu. Zwróć uwagę, że komunikat diagnostyczny u dołu strony był przeznaczony dla Ciebie:

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

  --noauth_local_webserver

Musisz nacisnąć ^C (Ctrl+C lub nacisnąć inny klawisz, aby zatrzymać wykonywanie skryptu) i uruchomić go z powłoki z dodatkową flagą. Po uruchomieniu w ten sposób otrzymasz następujące dane wyjściowe:

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

(Ignorujemy ostrzeżenie, ponieważ wiemy, że środowisko storage.json nie zostało jeszcze utworzone.) Jeśli wykonasz instrukcje podane w innej karcie przeglądarki z tym adresem URL, w przypadku lokalnych środowisk programistycznych interfejs będzie wyglądać prawie tak samo jak powyżej (patrz zrzuty ekranu powyżej). Na końcu wyświetla się ostatni ekran z kodem weryfikacyjnym, który należy wpisać w Cloud Shell:

40a567cda0f31cc9.png

Skopiuj ten kod i wklej go w oknie terminala.

Podsumowanie

Oprócz „Authentication successful” nie będą oczekiwać żadnych dodatkowych danych wyjściowych. Pamiętaj, że to tylko konfiguracja... Nie zrobiono jeszcze niczego. Udało Ci się z powodzeniem rozpocząć podróż do czegoś, co za pierwszym razem prawdopodobnie zadziała poprawnie. (Najlepsze jest to, że prośba o autoryzację wyświetliła się tylko raz – wszystkie kolejne uruchomienia pomijają tę czynność, bo Twoje uprawnienia zostały zapisane w pamięci podręcznej). Teraz czas trochę popracować nad kodem.

Rozwiązywanie problemów

Jeśli zamiast danych wyjściowych widzisz błąd, może to być spowodowane przez co najmniej jedną z tych przyczyn:

8. Krok 1. Pobierz obraz z Dysku Google

W poprzednim kroku zalecamy utworzenie kodu jako analyze_gsimg.py i edytowanie go na tej podstawie. Można też skopiować i wkleić wszystko bezpośrednio do iPythona lub standardowej powłoki w Pythonie, jednak jest to bardziej niewygodne, ponieważ będziemy rozwijać aplikację krok po kroku.

Załóżmy, że aplikacja została autoryzowana, a punkt końcowy usługi API został utworzony. W kodzie jest ona reprezentowana przez zmienną DRIVE. Znajdźmy plik graficzny na Dysku Google i

ustaw ją na zmienną o nazwie NAME. Wpisz plus tę funkcję drive_get_img() tuż pod kodem z kroku 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

Kolekcja files() na Dysku ma metodę list(), która wykonuje zapytanie (parametr q) dla określonego pliku. Parametr fields służy do określania, które wartości zwracają interesujące Cię wyniki. Dlaczego nie chcesz odwracać wszystkiego i spowalniać działania, jeśli nie interesują Cię inne wartości? Jeśli nie korzystasz jeszcze z masek pól do filtrowania wartości zwracanych przez interfejs API, przeczytaj ten post na blogu film. W przeciwnym razie wykonaj zapytanie i pobierz atrybut files, a w przypadku braku dopasowań domyślną tablicę będzie pusta tablica.

Jeśli nie ma żadnych wyników, reszta funkcji jest pomijana i zwracana jest domyślnie funkcja None. W przeciwnym razie pobierz pierwszą pasującą odpowiedź (rsp[0]), zwróci nazwę pliku, jego typ MIME, sygnaturę czasową ostatniej modyfikacji, a na koniec ładunek binarny pobrany przez funkcję get_media() (przez jej identyfikator pliku), także w kolekcji files(). (Nazwy metod mogą się nieznacznie różnić od nazw innych bibliotek klienta).

Ostatnia część jest „główna” który napędza całą aplikację:

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)

Przy założeniu, że na Dysku obraz o nazwie section-work-card-img_2x.jpg jest ustawiony na FILE, po wykonaniu skryptu powinny wyświetlić się dane wyjściowe potwierdzające, że udało mu się odczytać plik z Dysku (ale nie został on zapisany na komputerze):

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

Rozwiązywanie problemów

Jeśli nie otrzymasz pomyślnego wyniku takiego jak podany powyżej, może to być spowodowane przez co najmniej jedną z tych przyczyn:

Podsumowanie

W tej sekcji pokazaliśmy, jak (w 2 osobnych wywołaniach interfejsu API) utworzyć połączenie z zapytaniem interfejsu Drive API dotyczące konkretnego pliku, a następnie go pobrać. Zastosowanie w firmie: archiwizowanie danych z Dysku i ich analizowanie, np. przy użyciu narzędzi Google Cloud. Kod aplikacji na tym etapie powinien być zgodny z tym, co znajduje się w repozytorium w step1-drive/analyze_gsimg.py.

Więcej informacji o pobieraniu plików z Dysku Google znajdziesz tutaj, a także w tym poście na blogu i film. Ta część ćwiczenia w Codelabs jest niemal identyczna z całym wprowadzeniem do ćwiczeń z programowania interfejsów API Google Workspace – zamiast pobierać plik, wyświetla pierwsze 100 plików lub folderów na Dysku Google użytkownika i wykorzystuje bardziej restrykcyjny zakres.

9. Krok 2. Zarchiwizuj plik w Cloud Storage

Następnym krokiem jest dodanie obsługi Google Cloud Storage. W tym celu musimy zaimportować kolejny pakiet Pythona: io. Upewnij się, że górna sekcja importowanych danych wygląda tak:

from __future__ import print_function                   
import io

Oprócz nazwy pliku na Dysku potrzebujemy też informacji o tym, gdzie w Cloud Storage zapisać ten plik, a konkretnie o nazwie „zasobnika”. który umieścisz w folderze nadrzędnym prefiks(y). Więcej informacji na ten temat:

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

Kilka słów o zasobnikach: Cloud Storage zapewnia amorficzną pamięć masową blob. Podczas przesyłania plików do tego miejsca nie rozumie koncepcji typów plików, rozszerzeń itp., tak jak robi to Dysk Google. To po prostu „bloby”. do Cloud Storage. W Cloud Storage nie ma też folderów ani podkatalogów.

Tak. Możesz używać ukośników (/) w nazwach plików, aby odzwierciedlić abstrakcję wielu podfolderów, ale pod koniec dnia wszystkie obiekty blob trafiają do zasobnika, a „/” to tylko znaki w ich nazwach. Więcej informacji znajdziesz na stronie z konwencjami nazewnictwa zasobników i obiektów.

W kroku 1 powyżej zażądano zakresu Dysku tylko do odczytu. Obecnie to wystarczy. Teraz wymagane są uprawnienia do przesyłania (odczytu i zapisu) do Cloud Storage. Zmień parametr SCOPES ze zmiennej z pojedynczym ciągiem znaków na tablicę (krotka Pythona [lub lista]) zakresów uprawnień, aby wyglądała tak:

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

Teraz utwórz punkt końcowy usługi w Cloud Storage tuż pod tym dla Dysku. Uwaga: w niewielkim stopniu zmieniliśmy wywołanie, aby ponownie wykorzystać ten sam obiekt klienta HTTP, ponieważ nie ma potrzeby tworzenia nowego obiektu, gdy jest to zasób współużytkowany.

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

Teraz dodaj tę funkcję (po drive_get_img()), która przesyła dane do 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()

Wywołanie objects.().insert() wymaga nazwy zasobnika, metadanych pliku i samego binarnego obiektu blob. Aby odfiltrować zwracane wartości, zmienna fields wysyła żądanie tylko do nazw zasobników i obiektów zwróconych przez interfejs API. Więcej informacji o tych maskach pól w żądaniach odczytu interfejsu API znajdziesz w tym poście i film.

Teraz zintegruj interfejs gcs_blob_upload() z główną aplikacją:

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

Zmienna gcsname scala „podkatalog nadrzędny” nazwy z dodanymi samą nazwą pliku oraz poprzedzeniem nazwą zasobnika daje wrażenie, że archiwizowany jest plik w folderze „/bucket/parent.../filename”. Umieść ten fragment tuż za pierwszą funkcją print(), tuż nad klauzulą else, tak aby cały element „main” wygląda tak:

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)

Załóżmy, że określamy zasobnik o nazwie „vision-demo” z „analyzed_imgs” jako „podkatalog nadrzędny”. Gdy ustawisz te zmienne i ponownie uruchomisz skrypt, plik section-work-card-img_2x.jpg zostanie pobrany z Dysku, a następnie przesłany do Cloud Storage. Zgadza się? NIE!

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

Sprawdź dokładnie, czy pobieranie z Dysku się udało, ale nie udało się przesłać do Cloud Storage. Dlaczego?

Powodem jest to, że podczas autoryzowania tej aplikacji w kroku 1 autoryzowaliśmy dostęp tylko do odczytu do Dysku Google. Mimo że dodaliśmy zakres odczytu i zapisu do Cloud Storage, nigdy nie poprosiliśmy użytkownika o autoryzację dostępu. Aby wszystko działało, musimy usunąć plik storage.json, który nie ma tego zakresu, i uruchomić go ponownie.

Po ponownej autoryzacji (sprawdź w storage.json i sprawdź oba zakresy) dane wyjściowe będą zgodne z oczekiwaniami:

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

Podsumowanie

To poważna sprawa, która pokazuje (za pomocą kilku linijek) kodu, jak przenosić pliki między oboma systemami pamięci masowej działającymi w chmurze. Biznesowy przypadek użycia polega na tworzeniu kopii zapasowych prawdopodobnie ograniczonych zasobów w celu „zimniejszego” tańsza, jak wspomnieliśmy wcześniej. Cloud Storage udostępnia różne klasy pamięci w zależności od tego, czy korzystasz z danych regularnie, co miesiąc, co kwartał czy co rok.

Oczywiście deweloperzy od czasu do czasu pytają nas, dlaczego istnieje jednocześnie Dysk Google i Cloud Storage. Czy przecież to obie to miejsce do przechowywania plików w chmurze? Dlatego nagraliśmy ten film. Kod na tym etapie powinien być zgodny z tym, co znajduje się w repozytorium w step2-gcs/analyze_gsimg.py.

10. Krok 3. Przeprowadź analizę za pomocą Cloud Vision

Wiemy, że możesz przenosić dane między Google Cloud a Google Workspace, ale nie przeprowadziliśmy jeszcze żadnych analiz, więc czas wysłać obraz do Cloud Vision w celu dodania adnotacji z etykietą lub wykrywania obiektów. W tym celu musimy zakodować dane w standardzie Base64, co oznacza inny moduł Pythona: base64. Upewnij się, że główna sekcja importowania wygląda teraz tak:

from __future__ import print_function
import base64
import io

Domyślnie Vision API zwraca wszystkie znalezione etykiety. Aby zachować spójność, wybierz 5 pierwszych pozycji (oczywiście użytkownik może je dostosować). Do tego celu użyjemy stałej zmiennej TOP. dodaj go pod wszystkimi pozostałymi stałymi:

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

Tak jak w poprzednich krokach, potrzebujemy innego zakresu uprawnień, tym razem dla interfejsu Vision API. Zaktualizuj pole SCOPES za pomocą swojego ciągu znaków:

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

Teraz utwórz punkt końcowy usługi w Cloud Vision, aby wyrównać go z innymi:

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

Teraz dodaj tę funkcję, która wysyła ładunek obrazu do 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'])

Wywołanie images().annotate() wymaga danych oraz odpowiednich funkcji interfejsu API. Końcówka 5 pierwszych etykiet również stanowi część ładunku (ale jest to całkowicie opcjonalne). Jeśli wywołanie się powiedzie, ładunek zwróci 5 pierwszych etykiet obiektów oraz wskaźnik ufności obiektu na obrazie. Jeśli nie otrzymasz odpowiedzi, przypisz pusty słownik Pythona, aby ta instrukcja if nie kończyła się niepowodzeniem. Ta funkcja po prostu łączy dane w ciąg CSV, by później użyć ich w naszym raporcie.

Te 5 wierszy wywołujących funkcję vision_label_img() należy umieścić zaraz po pomyślnym przesłaniu danych do 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)

Po dołączeniu cały główny sterownik powinien wyglądać tak:

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)

Usunięcie reguły storage.json w celu odświeżenia zakresów i ponownego uruchomienia zaktualizowanej aplikacji powinno spowodować wyświetlenie danych wyjściowych podobnych do poniższych (z uwzględnieniem analizy 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

Podsumowanie

Nie każdy użytkownik ma wiedzę o systemach uczących się, aby tworzyć i trenować własne modele ML na potrzeby analizowania danych. Zespół Google Cloud udostępnił niektóre z wytrenowanych modeli Google do ogólnego użytku i umieścił je w interfejsach API, aby zdemokratyzować AI oraz ML dla każdego.

Jeśli jesteś deweloperem i możesz wywołać interfejs API, możesz korzystać z systemów uczących się. Cloud Vision to tylko jedna z usług interfejsów API, za pomocą której możesz analizować dane. Informacje o pozostałych znajdziesz tutaj. Twój kod powinien być teraz zgodny z informacjami w repozytorium w witrynie step3-vision/analyze_gsimg.py.

11. Krok 4. Wygeneruj raport w Arkuszach Google

Do tej pory można było archiwizować i analizować dane firmowe, ale brakuje tu podsumowania. Zorganizujmy wszystkie wyniki w jednym raporcie, który możesz przekazać szefowi. Czy istnieje coś, co bardziej nadaje się do zarządzania niż arkusz kalkulacyjny?

W przypadku interfejsu API Arkuszy Google nie są potrzebne dodatkowe importy. Jedyną nową wartością jest identyfikator pliku istniejącego arkusza kalkulacyjnego, który został już sformatowany i oczekuje na nowy wiersz danych, dlatego stała się SHEET. Zalecamy utworzenie nowego arkusza kalkulacyjnego, który wygląda podobnie do tego:

4def78583d05300.png

Adres URL tego arkusza kalkulacyjnego będzie wyglądał tak: https://docs.google.com/spreadsheets/d/FILE_ID/edit. Chwyć FILE_ID i przypisz je jako żądło SHEET.

Dodaliśmy również małą funkcję o nazwie k_ize(), która konwertuje bajty na kilobajty i zdefiniowana jest jako lambda w języku Python, ponieważ jest to prosty jednowierszowy tekst. Oba elementy zintegrowane z innymi stałymi wyglądają tak:

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                 

Tak jak w poprzednich krokach, potrzebujemy innego zakresu uprawnień – tym razem do odczytu i zapisu w interfejsie Arkuszy API. SCOPES ma teraz wszystkie 4 potrzebne elementy:

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

Teraz utwórz punkt końcowy usługi w Arkuszach Google w pobliżu innych usług. Będzie to wyglądało tak:

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

Funkcja sheet_append_row() jest prosta: dodaj wiersz danych i identyfikator arkusza, a następnie dodaj ten wiersz do tego arkusza:

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

Wywołanie spreadsheets().values().append() wymaga identyfikatora pliku arkusza, zakresu komórek, sposobu wprowadzania danych oraz samych danych. Identyfikator pliku jest prosty, a zakres komórek jest podany w notacji A1. Zakres „Sheet1” oznacza cały arkusz. Wskazuje to interfejsowi API, że ma dołączyć wiersz po wszystkich danych arkusza. Dostępne są 2 opcje dodawania danych do arkusza: „RAW”. (wpisz dosłownie dane ciągu) lub „USER_ENTERED” (zapisz dane tak, jakby użytkownik wpisał je na klawiaturze w aplikacji Arkusze Google, zachowując funkcje formatowania komórek).

Jeśli wywołanie się powiedzie, zwrócona wartość nie będzie w zasadzie żadnych użytecznych funkcji, więc postanowiliśmy zaktualizować liczbę komórek w żądaniu do interfejsu API. Poniżej znajduje się kod wywołujący tę funkcję:

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

Arkusz Google zawiera kolumny reprezentujące dane, takie jak dowolny nadrzędny „podkatalog”, lokalizację zarchiwizowanego pliku w Cloud Storage (zasobnik i nazwa pliku), typ MIME pliku, rozmiar pliku (pierwotnie w bajtach, ale przekonwertowany na kilobajty w przypadku funkcji k_ize()) oraz ciąg etykiet Cloud Vision. Pamiętaj też, że zarchiwizowana lokalizacja jest hiperlinkiem, dzięki któremu menedżer może kliknąć, aby sprawdzić, czy kopia zapasowa została utworzona.

Dodanie powyższego bloku kodu zaraz po wyświetleniu wyników z Cloud Vision – główna część napędzająca aplikację jest już gotowa, choć strukturalna jest nieco złożona:

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)

Ostatnie usunięcie aplikacji storage.json i ponowne uruchomienie zaktualizowanej aplikacji powinno spowodować wygenerowanie danych wyjściowych podobnych do poniższych (z uwzględnieniem analizy 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

Dodatkowy wiersz danych wyjściowych, choć jest przydatny, można lepiej zwizualizować, patrząc na zaktualizowany arkusz Google – ostatni wiersz (wiersz 7 w poniższym przykładzie) dodany do istniejącego zbioru danych wcześniej:

b53a5bc944734652.png

Podsumowanie

W pierwszych 3 krokach tego samouczka połączono Google Workspace i interfejsy Google Cloud API w celu przenoszenia danych i ich analizowania, co stanowiło 80% całej pracy. Ostatecznie to jednak nie będzie to miało żadnego znaczenia, jeśli nie możesz zaprezentować kierownictwu swoich osiągnięć. Aby lepiej zwizualizować wyniki, zawiera podsumowanie wszystkich wyników w wygenerowanym raporcie.

Aby jeszcze bardziej zwiększyć użyteczność analizy, oprócz zapisania wyników w arkuszu kalkulacyjnym jednym z możliwych ulepszeń jest zindeksowanie 5 pierwszych etykiet dla każdego zdjęcia w celu zbudowania wewnętrznej bazy danych umożliwiającej upoważnionym pracownikom wysyłanie zapytań o zdjęcia do zespołu wyszukiwarki. Pozostawiamy jednak ten zapis jako ćwiczenie dla czytelników.

Obecnie wyniki są zapisane w arkuszu, a zarządzane nimi mogą zarządzać. Kod aplikacji na tym etapie powinien być zgodny z tym, co znajduje się w repozytorium w step4-sheets/analyze_gsimg.py. Ostatnim krokiem jest oczyszczenie kodu i przekształcenie go w użyteczny skrypt.

12. *Ostatni krok: refaktoryzacja

(opcjonalnie) Dobrze jest mieć działającą aplikację, ale czy można ją ulepszyć? Tak, zwłaszcza w głównej aplikacji, która wydaje się chaotyczna. Wykorzystamy to w osobnej funkcji i umożliwimy to użytkownikowi, a nie na stałe. Wykorzystamy do tego moduł argparse. Uruchommy też kartę przeglądarki, w której wyświetlimy arkusz, gdy zapiszemy w nim wiersz danych. Użyjesz do tego modułu webbrowser. Połącz te importy z pozostałymi, aby główne importy wyglądały tak:

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

Aby móc używać tego kodu w innych aplikacjach, musimy mieć możliwość pomijania danych wyjściowych, dlatego dodajmy flagę DEBUG, aby to umożliwić, dodając ten wiersz na końcu sekcji ze stałymi na górze:

DEBUG = False

A teraz o głównym ciele. Ponieważ pracowaliśmy nad tą próbką, powinno być dla Ciebie to „niekomfortowe” ponieważ nasz kod dodaje kolejny poziom zagnieżdżenia z każdą dodaną usługą. Jeśli tak uważasz, nie jesteś jedyną osobą, która zwiększa złożoność kodu. Więcej informacji znajdziesz w tym poście na blogu Google Testing na blogu.

Zgodnie z tą sprawdzonymi metodami uporządkujemy główną część aplikacji, dodając do niej funkcję return w poszczególnych „punktach przerwania”. zamiast zagnieżdżania (zwraca wartość None, jeśli którykolwiek krok się nie powiódł, oraz True, jeśli wszystko się udało):

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

Kod jest bardziej schludny i czystszy, a jednocześnie powtarza rekurencyjny charakter łańcucha if-else, a jednocześnie zmniejsza złożoność kodu w sposób opisany powyżej. Ostatnim elementem łamigłówki jest stworzenie „prawdziwego” główny sterownik, który umożliwia dostosowanie go przez użytkownika i minimalizację danych wyjściowych (chyba że jest to konieczne):

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)

Jeśli wszystkie kroki zakończą się powodzeniem, skrypt uruchomi przeglądarkę i wyświetli arkusz kalkulacyjny w miejscu, w którym dodano nowy wiersz danych.

Podsumowanie

Nie trzeba usuwać zakresu storage.json, ponieważ nie wprowadzono żadnych zmian zakresu. Ponowne uruchomienie zaktualizowanej aplikacji spowoduje wyświetlenie nowego okna przeglądarki ze zmodyfikowanym arkuszem, mniejszą liczbę wierszy danych wyjściowych, a po uruchomieniu opcji -h użytkownicy zobaczą dostępne opcje, w tym -v, które umożliwiają przywrócenie pominiętych wierszy danych wyjściowych, które pojawiły się wcześniej:

$ 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

Inne opcje pozwalają użytkownikom wybierać różne nazwy plików na Dysku oraz „podkatalog” Cloud Storage. i nazwy zasobników, górne „N” wyników z Cloud Vision i identyfikatorów plików arkuszy kalkulacyjnych (Arkuszy). Po tych ostatnich aktualizacjach ostateczna wersja kodu powinna w całości odpowiadać zawartości repozytorium w final/analyze_gsimg.py oraz w całości:

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

Dołożymy wszelkich starań, aby zawartość tego samouczka była aktualna, ale niekiedy może się zdarzyć, że repozytorium będzie zawierać najnowszą wersję kodu.

13. Gratulacje!

Ten kurs wymagał dużo nauki w programie i udało Ci się przetrwać jeden z dłuższych sesji z programowania. W rezultacie udało Ci się zrealizować potencjalny scenariusz biznesowy, wykorzystując około 130 wierszy języka Python, wykorzystując wszystkie możliwości Google Cloud i Google Workspace oraz przenosząc dane między nimi w celu stworzenia działającego rozwiązania. Przejrzyj repozytorium open source dotyczące wszystkich wersji tej aplikacji (więcej informacji znajdziesz poniżej).

Czyszczenie danych

  1. Korzystanie z interfejsów Google Cloud API jest bezpłatne, a interfejsy Google Workspace API są objęte miesięczną opłatą za subskrypcję Google Workspace (użytkownicy Gmaila w Google Workspace otrzymują zerową miesięczną opłatę). W związku z tym w przypadku użytkowników Google Workspace nie trzeba czyścić ani wyłączać interfejsów API. W przypadku Google Cloud możesz otworzyć panel konsoli Google Cloud i sprawdzić „kartę Płatności” aby poznać szacunkowe opłaty.
  2. W przypadku Cloud Vision możesz bezpłatnie wykonywać określoną liczbę wywołań interfejsu API miesięcznie. Dopóki nie przekroczysz tych limitów, nie musisz niczego wyłączać. Nie musisz też wyłączać ani usuwać projektu. Więcej informacji na temat płatności i bezpłatnego limitu interfejsu Vision API znajdziesz na stronie z cennikiem.
  3. Niektórzy użytkownicy Cloud Storage otrzymują co miesiąc bezpłatną ilość miejsca na dane. Jeśli obrazy, które archiwizujesz za pomocą tego ćwiczenia, nie spowodują przekroczenia limitu, nie naliczymy żadnych opłat. Więcej informacji o płatnościach za GCS i bezpłatnym limicie znajdziesz na stronie z cennikiem. Obiekty blob możesz wyświetlać i łatwo usuwać w przeglądarce Cloud Storage.
  4. Podczas korzystania z Dysku Google może obowiązywać limit miejsca na dane. Jeśli go przekroczysz (lub zbliżasz się do niego), warto rozważyć skorzystanie z wbudowanego w programie narzędzia, aby zarchiwizować te obrazy w Cloud Storage, aby uzyskać więcej miejsca na Dysku. Więcej informacji o miejscu na Dysku Google znajdziesz na odpowiedniej stronie z cennikiem dla użytkowników Google Workspace Basic i Gmaila/klientów indywidualnych.

Chociaż większość abonamentów Google Workspace Business i Enterprise ma nieograniczone miejsce na dane, może to spowodować zaśmiecanie folderów na Dysku. Wbudowana przez Ciebie aplikacja to świetny sposób na archiwizowanie zbędnych plików i oczyszczanie Dysku Google.

Wersje alternatywne

final/analyze_gsimg.py jest „ostatnim” oficjalnej wersji, nad którą pracujesz w tym samouczku, to nie koniec historii. Problem w końcowej wersji aplikacji polega na tym, że używa ona starszych bibliotek uwierzytelniania, które zostały wycofane. Wybraliśmy tę ścieżkę, ponieważ w momencie tworzenia tego tekstu nowsze biblioteki uwierzytelniania nie obsługiwały kilku kluczowych elementów: zarządzania miejscem na tokeny OAuth i bezpieczeństwa wątków.

Bieżące (nowsze) biblioteki uwierzytelniania

Jednak w pewnym momencie starsze biblioteki uwierzytelniania przestaną być obsługiwane, dlatego zachęcamy do przejrzenia wersji korzystających z nowszych (bieżących) bibliotek uwierzytelniania w folderze alt repozytorium, nawet jeśli nie zapewniają one zabezpieczenia Thread (ale możesz utworzyć własne rozwiązanie). Wyszukaj pliki, których nazwy zawierają *newauth*.

Biblioteki klienta usługi Google Cloud

Google Cloud zaleca wszystkim deweloperom korzystanie z bibliotek klienta usługi podczas korzystania z interfejsów Google Cloud API. Interfejsy API spoza Google Cloud nie mają obecnie takich bibliotek. Użycie bibliotek niższego poziomu pozwala na spójne korzystanie z interfejsu API i zwiększa czytelność funkcji. Podobnie jak w przypadku powyższej rekomendacji, w folderze alt repozytorium dostępne są alternatywne wersje korzystające z bibliotek klienta usługi Google Cloud. Wyszukaj pliki, których nazwy zawierają *-gcp*.

Autoryzacja konta usługi

W chmurze zwykle nie ma ludzi ani danych należących do użytkowników. Dlatego konta usługi i autoryzacja na koncie usługi są używane przede wszystkim w Google Cloud. Jednak dokumenty Google Workspace są przeważnie własnością użytkowników, dlatego w tym samouczku używamy autoryzacji konta użytkownika. Nie oznacza to, że nie można używać interfejsów Google Workspace API na kontach usługi. Jeśli konta mają odpowiedni poziom dostępu, można z nich korzystać w aplikacjach. Podobnie jak powyżej, w folderze alt repozytorium dostępne są alternatywne wersje używające autoryzacji konta usługi. Wyszukaj pliki, których nazwy zawierają *-svc*.

Katalog wersji alternatywnych

Poniżej znajdziesz wszystkie alternatywne wersje atrybutu final/analyze_gsimg.py, z których każda ma co najmniej jedną z powyższych właściwości. W nazwach plików każdej wersji poszukaj:

  • oldauth” dla wersji korzystających ze starszych bibliotek uwierzytelniania (oprócz final/analyze_gsimg.py)
  • newauth” dla osób korzystających z obecnych/nowszych bibliotek uwierzytelniania
  • gcp” dla osób korzystających z bibliotek klienta usługi Google Cloud, np. google-cloud-storage itp.
  • svc” dla użytkowników korzystających z uwierzytelniania konta usługi („svc acct”) zamiast konta użytkownika

Oto wszystkie wersje:

Nazwa pliku

Opis

final/analyze_gsimg.py

próbkę główną; korzysta ze starszych bibliotek uwierzytelniania

alt/analyze_gsimg-newauth.py

Ta sama funkcja co final/analyze_gsimg.py, ale korzysta z nowszych bibliotek uwierzytelniania

alt/analyze_gsimg-oldauth-gcp.py

Taki sam jak w final/analyze_gsimg.py, ale korzysta z bibliotek klienta usługi Google Cloud.

alt/analyze_gsimg-newauth-gcp.py

Taki sam jak w alt/analyze_gsimg-newauth.py, ale korzysta z bibliotek klienta usługi Google Cloud.

alt/analyze_gsimg-oldauth-svc.py

Taka sama jak final/analyze_gsimg.py, ale używa konta svc zamiast konta użytkownika

alt/analyze_gsimg-newauth-svc.py

Taki sam jak alt/analyze_gsimg-newauth.py, ale zamiast konta użytkownika używa uwierzytelniania konta svc

alt/analyze_gsimg-oldauth-svc-gcp.py

Element taki sam jak alt/analyze_gsimg-oldauth-svc.py, ale korzysta z bibliotek klienta usługi Google Cloud i tych samych co alt/analyze_gsimg-oldauth-gcp.py, ale korzysta z uwierzytelniania konta svc zamiast konta użytkownika

alt/analyze_gsimg-newauth-svc-gcp.py

Ta sama funkcja co alt/analyze_gsimg-oldauth-svc-gcp.py, ale korzysta z nowszych bibliotek uwierzytelniania

W połączeniu z pierwotną wersją final/analyze_gsimg.py dają Ci dostęp do wszystkich możliwych kombinacji ostatecznych rozwiązań, niezależnie od środowiska programistycznego interfejsu API Google. Możesz wybrać takie, które najlepiej odpowiada Twoim potrzebom. Podobne wyjaśnienie znajdziesz też na stronie alt/README.md.

Badanie dodatkowe

Poniżej znajdziesz kilka pomysłów, jak wykonać to ćwiczenie o krok lub o dwa. Zestaw problemów, które może rozwiązać bieżące rozwiązanie, można rozszerzyć, wprowadzając następujące ulepszenia:

  1. (wiele obrazów w folderach) Zamiast przetwarzać jeden obraz, załóżmy, że znajdowały się w folderach Dysku Google.
  2. (wiele obrazów w plikach ZIP) Co zrobić z archiwami ZIP zawierającymi pliki obrazów zamiast folderu z obrazami? Jeśli używasz Pythona, rozważ zastosowanie modułu zipfile.
  3. (Analiza etykiet Vision) Pogrupuj podobne obrazy, zaczynając od wyszukania najpopularniejszych etykiet, następnie od 2 najpopularniejszych itd.
  4. (tworzenie wykresów) Odpowiedź nr 3, generowanie wykresów za pomocą interfejsu Arkuszy API na podstawie analizy i kategoryzacji Vision API.
  5. (Kategoryzowanie dokumentów) Zamiast analizować obrazy za pomocą Cloud Vision API, załóżmy, że chcesz kategoryzować pliki PDF za pomocą Cloud Natural Language API. W przypadku powyższych rozwiązań te pliki PDF mogą znajdować się w folderach na Dysku lub w archiwach ZIP na Dysku.
  6. (tworzenie prezentacji) Interfejs API Prezentacji Google umożliwia wygenerowanie prezentacji na podstawie zawartości raportu Arkuszy Google. W poszukiwaniu inspiracji przeczytaj ten post na blogu i film o generowaniu slajdów na podstawie danych z arkuszy kalkulacyjnych.
  7. (wyeksportuj jako PDF) Wyeksportuj arkusz kalkulacyjny lub prezentację do pliku PDF, ale nie jest to możliwe w interfejsach API Arkuszy ani Prezentacji. Wskazówka: Google Drive API. Dodatkowe informacje: scal pliki PDF z Arkuszy i Prezentacji w jeden główny plik PDF za pomocą narzędzi takich jak Ghostscript (Linux, Windows) lub Combine PDF Pages.action (Mac OS X).

Więcej informacji

Codelabs

Ogólne

Google Workspace

Google Cloud

Licencja

To zadanie jest licencjonowane na podstawie ogólnej licencji Creative Commons Attribution 2.0.