1. Обзор
В этой кодовой лаборатории представлен возможный рабочий процесс предприятия: архивирование изображений, анализ и создание отчетов. Представьте, что в вашей организации есть серия изображений, занимающих место на ограниченном ресурсе. Вы хотите заархивировать эти данные, проанализировать эти изображения и, что наиболее важно, создать отчет, в котором суммируются заархивированные местоположения, а также результаты анализа, сопоставленные и готовые для использования руководством. Google Cloud предоставляет инструменты для этого, используя API двух линеек своих продуктов: Google Workspace (ранее G Suite или Google Apps) и Google Cloud (ранее GCP).
В нашем сценарии у бизнес-пользователя будут изображения на Google Диске . Имеет смысл выполнить резервное копирование в более «холодное» и более дешевое хранилище, например, в классы хранения, доступные в Google Cloud Storage . Google Cloud Vision позволяет разработчикам легко интегрировать функции обнаружения изображений в приложения, включая обнаружение объектов и ориентиров, оптическое распознавание символов (OCR) и т. д. Наконец, электронная таблица Google Sheets — это полезный инструмент визуализации, позволяющий обобщить все это для вашего начальника.
Мы надеемся, что после завершения этой лабораторной работы по созданию решения, использующего все возможности Google Cloud, вы вдохновитесь на создание чего-то еще более эффективного для вашей организации или ваших клиентов.
Что вы узнаете
- Как использовать Cloud Shell
- Как аутентифицировать запросы API
- Как установить клиентскую библиотеку Google API для Python
- Как включить API Google
- Как скачать файлы с Google Диска
- Как загрузить объекты/блобы в облачное хранилище
- Как анализировать данные с помощью Cloud Vision
- Как писать строки в Google Sheets
Что вам понадобится
- Учетная запись Google (для учетных записей Google Workspace может потребоваться одобрение администратора)
- Проект Google Cloud с активной платежной учетной записью Google Cloud.
- Знание команд терминала/оболочки операционной системы.
- Базовые навыки работы с Python (2 или 3), но вы можете использовать любой поддерживаемый язык.
Опыт работы с четырьмя продуктами Google Cloud, перечисленными выше, будет полезен, но не обязателен. Если время позволяет вам сначала ознакомиться с ними по отдельности, вы можете выполнить лабораторные работы по каждому из них, прежде чем приступить к упражнению здесь:
- Введение в Google Диск (с использованием API Google Workspace) (Python)
- Использование Cloud Vision с Python (Python)
- Создавайте собственные инструменты отчетности с помощью Sheets API (JS/Node).
- Загружать объекты в Google Cloud Storage (кодирование не требуется)
Опрос
Как вы будете использовать этот урок?
Как бы вы оценили свой опыт работы с Python?
Как бы вы оценили свой опыт использования сервисов Google Cloud?
Как бы вы оценили свой опыт использования сервисов для разработчиков Google Workspace?
Хотели бы вы видеть больше «бизнес-ориентированных» программных лабораторий по сравнению с теми, которые посвящены знакомству с функциями продукта?
2. Настройка и требования
Самостоятельная настройка среды
- Войдите в Google Cloud Console и создайте новый проект или повторно используйте существующий. Если у вас еще нет учетной записи Gmail или Google Workspace, вам необходимо ее создать .
- Имя проекта — это отображаемое имя для участников этого проекта. Это строка символов, не используемая API Google. Вы можете обновить его в любое время.
- Идентификатор проекта должен быть уникальным для всех проектов Google Cloud и неизменяемым (нельзя изменить после его установки). Cloud Console автоматически генерирует уникальную строку; обычно тебя не волнует, что это такое. В большинстве лабораторий кода вам потребуется указать идентификатор проекта (обычно он обозначается как
PROJECT_ID
). Если вам не нравится сгенерированный идентификатор, вы можете создать другой случайный идентификатор. Кроме того, вы можете попробовать свой собственный и посмотреть, доступен ли он. Его нельзя изменить после этого шага, и он останется в силе на протяжении всего проекта. - К вашему сведению, есть третье значение — номер проекта , который используют некоторые API. Подробнее обо всех трех этих значениях читайте в документации .
- Затем вам необходимо включить выставление счетов в Cloud Console, чтобы использовать облачные ресурсы/API. Прохождение этой лаборатории кода не должно стоить много, если вообще стоит. Чтобы отключить ресурсы и избежать выставления счетов за пределами этого руководства, вы можете удалить созданные вами ресурсы или удалить весь проект. Новые пользователи Google Cloud имеют право на участие в программе бесплатной пробной версии стоимостью 300 долларов США .
Запустить Cloud Shell
Краткое содержание
Хотя вы можете разрабатывать код локально на своем ноутбуке, дополнительная цель этой лаборатории — научить вас использовать Google Cloud Shell , среду командной строки, работающую в облаке через ваш современный веб-браузер.
Активировать Cloud Shell
- В Cloud Console нажмите «Активировать Cloud Shell». .
Если вы никогда раньше не запускали Cloud Shell, вам будет представлен промежуточный экран (ниже сгиба) с описанием того, что это такое. В этом случае нажмите «Продолжить» (и вы больше никогда его не увидите). Вот как выглядит этот одноразовый экран:
Подготовка и подключение к Cloud Shell займет всего несколько минут.
Эта виртуальная машина оснащена всеми необходимыми инструментами разработки. Он предлагает постоянный домашний каталог объемом 5 ГБ и работает в Google Cloud, что значительно повышает производительность сети и аутентификацию. Большую часть, если не всю, работу в этой лаборатории кода можно выполнить с помощью просто браузера или Chromebook.
После подключения к Cloud Shell вы увидите, что вы уже прошли аутентификацию и что для проекта уже установлен идентификатор вашего проекта.
- Выполните следующую команду в Cloud Shell, чтобы подтвердить, что вы прошли аутентификацию:
gcloud auth list
Вывод команды
Credentialed Accounts ACTIVE ACCOUNT * <my_account>@<my_domain.com> To set the active account, run: $ gcloud config set account `ACCOUNT`
- Выполните следующую команду в Cloud Shell, чтобы убедиться, что команда gcloud знает о вашем проекте:
gcloud config list project
Вывод команды
[core] project = <PROJECT_ID>
Если это не так, вы можете установить его с помощью этой команды:
gcloud config set project <PROJECT_ID>
Вывод команды
Updated property [core/project].
3. Подтвердите среду Python.
Эта лаборатория кода требует от вас использования языка Python (хотя многие языки поддерживаются клиентскими библиотеками API Google, поэтому не стесняйтесь создавать что-то эквивалентное в своем любимом инструменте разработки и просто использовать Python в качестве псевдокода). В частности, эта лаборатория кода поддерживает Python 2 и 3, но мы рекомендуем как можно скорее перейти на версию 3.x.
Cloud Shell — это удобный инструмент, доступный пользователям непосредственно из Cloud Console и не требующий локальной среды разработки, поэтому это руководство можно выполнить полностью в облаке с помощью веб-браузера. Если говорить более конкретно, для этой лаборатории в Cloud Shell уже предварительно установлены обе версии Python.
В Cloud Shell также установлен IPython : это интерактивный интерпретатор Python более высокого уровня, который мы рекомендуем, особенно если вы являетесь частью сообщества специалистов по науке о данных или машинному обучению. Если да, то IPython является интерпретатором по умолчанию для Jupyter Notebooks, а также для Colab , Jupyter Notebooks, размещенных в Google Research.
IPython сначала отдает предпочтение интерпретатору Python 3, но возвращается к Python 2, если версия 3.x недоступна. Доступ к IPython можно получить из Cloud Shell, но его также можно установить в локальной среде разработки. Выйдите с помощью ^D (Ctrl-d) и примите предложение выйти. Пример вывода запуска ipython
будет выглядеть так:
$ 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]:
Если вы не предпочитаете IPython, вполне приемлемо использование стандартного интерактивного интерпретатора Python (либо Cloud Shell, либо вашей локальной среды разработки) (также выйдите с помощью ^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. >>>
В лаборатории кода также предполагается, что у вас есть инструмент установки pip
(менеджер пакетов Python и преобразователь зависимостей). Он поставляется в комплекте с версиями 2.7.9+ или 3.4+. Если у вас более старая версия Python, инструкции по установке см. в этом руководстве. В зависимости от ваших разрешений вам может потребоваться доступ sudo
или суперпользователя, но обычно это не так. Вы также можете явно использовать pip2
или pip3
для выполнения pip
для определенных версий Python.
В оставшейся части лабораторной работы предполагается, что вы используете Python 3 — для Python 2 будут предоставлены конкретные инструкции, если они существенно отличаются от версии 3.x.
[необязательно] Создание и использование виртуальных сред
Этот раздел является необязательным и действительно необходим только тем, кому необходимо использовать виртуальную среду для этой лаборатории кода (согласно предупреждению на боковой панели выше). Если на вашем компьютере установлен только Python 3, вы можете просто ввести эту команду, чтобы создать виртуальную среду с именем my_env
(при желании вы можете выбрать другое имя):
virtualenv my_env
Однако, если на вашем компьютере установлены Python 2 и 3, мы рекомендуем вам установить виртуальную среду Python 3, что можно сделать с помощью -p flag
следующим образом:
virtualenv -p python3 my_env
Войдите в свой недавно созданный виртуальный мир, «активировав» его следующим образом:
source my_env/bin/activate
Подтвердите, что вы находитесь в среде, наблюдая, что приглашению оболочки теперь предшествует имя вашей среды, т. е.
(my_env) $
Теперь вы сможете pip install
любые необходимые пакеты, выполнять код внутри этого eivonment и т. д. Еще одним преимуществом является то, что если вы полностью все испортите, попадете в ситуацию, когда ваша установка Python повреждена и т. д., вы можете сбросить это всю среду, не затрагивая остальную часть вашей системы.
4. Установите клиентскую библиотеку API Google для Python.
Для этой лаборатории кода требуется использование клиентской библиотеки Google API для Python , поэтому либо это простой процесс установки, либо вам вообще ничего не придется делать.
Ранее мы рекомендовали вам рассмотреть возможность использования Cloud Shell для удобства. Вы можете пройти все руководство из веб-браузера в облаке. Еще одна причина использовать Cloud Shell — многие популярные инструменты разработки и необходимые библиотеки уже предустановлены .
*Установка клиентских библиотек.
( необязательно ) Это можно пропустить, если вы используете Cloud Shell или локальную среду, в которой уже установлены клиентские библиотеки. Вам нужно это сделать только в том случае, если вы разрабатываете локально и не установили их (или не уверены, что установили). Самый простой способ — использовать pip
(или pip3
) для установки (включая обновление самого pip
при необходимости):
pip install -U pip google-api-python-client oauth2client
Подтвердить установку
Эта команда устанавливает клиентскую библиотеку, а также все пакеты, от которых она зависит. Независимо от того, используете ли вы Cloud Shell или свою собственную среду, убедитесь, что клиентская библиотека установлена, импортировав необходимые пакеты, и убедитесь, что нет ошибок импорта (и вывода):
python3 -c "import googleapiclient, httplib2, oauth2client"
Если вместо этого вы используете Python 2 (из Cloud Shell), вы получите предупреждение о том, что его поддержка устарела:
******************************************************************************* 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. *******************************************************************************
Как только вы сможете успешно выполнить команду импорта «test» (без ошибок/вывода), вы готовы начать общение с API Google!
Краткое содержание
Поскольку это промежуточная лаборатория кода, предполагается, что у вас уже есть опыт создания и использования проектов в консоли. Если вы новичок в API Google и, в частности, в API Google Workspace, сначала попробуйте вводную лабораторию кода API Google Workspace . Кроме того, если вы знаете, как создавать (или повторно использовать существующие) учетные данные учетной записи пользователя ( не учетной записи службы ), поместите файл client_secret.json
в свой рабочий каталог, пропустите следующий модуль и перейдите к «Включить API Google».
5. *Авторизация запросов API (авторизация пользователя)
Этот раздел можно пропустить, если вы уже создали учетные данные для авторизации учетной записи пользователя и знакомы с процессом. Это отличается от авторизации учетной записи службы, метод которой отличается, поэтому продолжайте ниже.
Введение в авторизацию (плюс некоторую аутентификацию)
Чтобы отправлять запросы к API, ваше приложение должно иметь соответствующую авторизацию . Аналогичное слово «Аутентификация» описывает учетные данные для входа — вы подтверждаете свою подлинность при входе в свою учетную запись Google с помощью логина и пароля. После аутентификации следующим шагом будет определение того, авторизованы ли вы (точнее, ваш код ) на доступ к данным, таким как файлы больших двоичных объектов в облачном хранилище или личные файлы пользователя на Google Диске.
API Google поддерживают несколько типов авторизации, но наиболее распространенным среди пользователей API G Suite является авторизация пользователя , поскольку пример приложения в этой лаборатории кода обращается к данным, принадлежащим конечным пользователям. Эти конечные пользователи должны предоставить вашему приложению разрешение на доступ к их данным . Это означает, что ваш код должен получить учетные данные учетной записи пользователя OAuth2.
Чтобы получить учетные данные OAuth2 для авторизации пользователя, вернитесь в диспетчер API и выберите вкладку «Учетные данные» в левой навигационной панели:
Когда вы доберетесь туда, вы увидите все свои учетные данные в трех отдельных разделах:
Первый предназначен для ключей API , второй — для идентификаторов клиентов OAuth 2.0 и последний — для учетных записей службы OAuth2 — мы используем тот, что посередине.
Создание учетных данных
На странице «Учетные данные» нажмите кнопку «+ Создать учетные данные» вверху, после чего появится диалоговое окно, в котором вы должны выбрать «Идентификатор клиента OAuth:».
На следующем экране у вас есть 2 действия: настройка «экрана согласия» авторизации вашего приложения и выбор типа приложения:
Если вы не установили экран согласия, вы увидите предупреждение в консоли, и вам нужно будет сделать это сейчас. (Пропустите следующие шаги, если экран согласия уже настроен.)
Экран согласия OAuth
Нажмите «Настроить экран согласия», где выберите «Внешнее» приложение (или «Внутреннее», если вы являетесь клиентом G Suite):
Обратите внимание, что для целей этого упражнения не имеет значения, что вы выберете, поскольку вы не публикуете образец своей лаборатории кода. Большинство людей выберут «Внешний», чтобы перейти к более сложному экрану, но вам действительно нужно заполнить только поле «Имя приложения» вверху:
Единственное, что вам нужно на данный момент, — это просто имя приложения, поэтому выберите кого-нибудь, кто соответствует вашей кодовой лаборатории, и нажмите « Сохранить» .
Создание идентификатора клиента OAuth (авторизация учетной записи пользователя)
Теперь вернитесь на вкладку «Учетные данные», чтобы создать идентификатор клиента OAuth2 . Здесь вы увидите различные идентификаторы клиентов OAuth, которые вы можете создать:
Мы разрабатываем инструмент командной строки Other , поэтому выберите его и нажмите кнопку «Создать» . Выберите имя идентификатора клиента, соответствующее создаваемому вами приложению, или просто выберите имя по умолчанию, обычно «Другой клиент N ».
Сохранение ваших учетных данных
- Появится диалоговое окно с новыми учетными данными; нажмите ОК , чтобы закрыть
- Вернувшись на страницу «Учетные данные», прокрутите вниз до раздела «Идентификаторы клиентов OAuth2», найдите и щелкните значок загрузки. в крайнем правом нижнем углу вашего вновь созданного идентификатора клиента.
- Откроется диалоговое окно для сохранения файла с именем
client_secret-
LONG-HASH-STRING
.apps.googleusercontent.com.json
, скорее всего, в папке «Загрузки» . Мы рекомендуем сократить имя до более простого, напримерclient_secret.json
(именно его использует пример приложения), а затем сохранить его в каталоге/папке, где вы будете создавать пример приложения в этой лаборатории кода.
Краткое содержание
Теперь вы готовы включить API Google, используемые в этой лаборатории кода. Кроме того, в качестве имени приложения на экране согласия OAuth мы выбрали «Демоверсия Vision API», поэтому ожидайте увидеть это на некоторых из следующих снимков экрана.
6. Включите API Google.
В этой лаборатории кода используются четыре (4) API Google Cloud: пара из Google Cloud (Cloud Storage и Cloud Vision) и еще одна пара из Google Workspace (Google Drive и Google Sheets). Ниже приведены общие инструкции по включению API Google. Как только вы узнаете, как включить один API, остальные будут аналогичны.
Независимо от того, какие API Google вы хотите использовать в своем приложении, они должны быть включены . API можно включить из командной строки или из облачной консоли. Процесс включения API идентичен, поэтому, включив один API, вы можете включить другие аналогичным образом.
Вариант 1. Интерфейс командной строки gcloud
(Cloud Shell или локальная среда).
Хотя включение API из облачной консоли встречается чаще, некоторые разработчики предпочитают делать все из командной строки. Для этого вам нужно найти «имя службы» API. Это выглядит как URL: SERVICE_NAME
.googleapis.com
. Их можно найти в таблице «Поддерживаемые продукты» или программно запросить их с помощью Google Discovery API .
Вооружившись этой информацией, с помощью Cloud Shell (или локальной среды разработки с установленным инструментом командной строки gcloud
) вы можете включить API или службу следующим образом:
gcloud services enable SERVICE_NAME.googleapis.com
Пример 1. Включение Cloud Vision API
gcloud services enable vision.googleapis.com
Пример 2. Включение платформы бессерверных вычислений Google App Engine
gcloud services enable appengine.googleapis.com
Пример 3. Включите несколько API одним запросом. Например, если в этой лаборатории кода зрители развертывают приложение с помощью Cloud Translation API в App Engine, Cloud Functions и Cloud Run, командная строка будет такой:
gcloud services enable appengine.googleapis.com cloudfunctions.googleapis.com artifactregistry.googleapis.com run.googleapis.com translate.googleapis.com
Эта команда включает App Engine, Cloud Functions, Cloud Run и Cloud Translation API. Кроме того, он активирует реестр облачных артефактов, поскольку именно здесь образы контейнеров должны быть зарегистрированы в системе Cloud Build для развертывания в Cloud Run.
Есть также несколько команд для запроса API, которые нужно включить, или того, какие API уже включены для вашего проекта.
Пример 4. Запрос API Google, доступных для включения в вашем проекте.
gcloud services list --available --filter="name:googleapis.com"
Пример 5. Запрос API Google, включенных для вашего проекта.
gcloud services list
Дополнительную информацию о приведенных выше командах см. в документации по включению и отключению служб , а также листингу служб .
Вариант 2. Облачная консоль.
Вы также можете включить API Google в диспетчере API. В облачной консоли перейдите в API Manager . На этой странице панели мониторинга вы увидите некоторую информацию о трафике вашего приложения, графики, показывающие запросы приложения, ошибки, сгенерированные вашим приложением, и время ответа вашего приложения:
Ниже этих диаграмм приведен список API Google, включенных для вашего проекта:
Чтобы включить (или отключить) API, нажмите «Включить API и службы» вверху:
Либо перейдите на левую панель навигации и выберите API и сервисы → Библиотека :
В любом случае вы попадете на страницу библиотеки API :
Введите имя API для поиска и просмотра соответствующих результатов:
Выберите API, который вы хотите включить, и нажмите кнопку «Включить» :
Процесс включения всех API одинаков, независимо от того, какой API Google вы хотите использовать.
Расходы
Многие API Google можно использовать бесплатно, однако за использование большинства продуктов и API Google Cloud взимается плата. При включении Cloud API вас могут попросить указать активную учетную запись для выставления счетов. Однако некоторые продукты Google Cloud имеют уровень «Всегда бесплатно» , который необходимо превысить, чтобы взиматься плата за выставление счетов.
Новые пользователи Google Cloud имеют право на бесплатную пробную версию , стоимость которой в настоящее время составляет 300 долларов США за первые 90 дней. Codelabs, как правило, не требует больших затрат или каких-либо счетов, поэтому мы предлагаем вам отложить использование бесплатной пробной версии до тех пор, пока вы действительно не будете готовы провести ее тест-драйв, тем более что это разовое предложение. Квоты уровня бесплатного пользования не имеют срока действия и применяются независимо от того, используете ли вы бесплатную пробную версию или нет.
Перед включением пользователям следует ознакомиться с информацией о ценах на любой API (пример: страница цен на Cloud Vision API ), особенно отметив, есть ли у него уровень бесплатного пользования, и если да, то какой он. Пока вы остаетесь в пределах установленных дневных или ежемесячных лимитов в совокупности, вы не должны нести никаких расходов. Цены и уровни бесплатного пользования различаются в зависимости от API группы продуктов Google. Примеры:
- Google Cloud — счета за каждый продукт выставляются по-разному и, как правило, с оплатой по факту использования; см. информацию об уровне бесплатного пользования выше.
- Карты Google — содержат набор API-интерфейсов и предлагают пользователям общий бесплатный ежемесячный кредит в размере 200 долларов США .
- API Google Workspace (ранее G Suite) — использование (в пределах определенных ограничений) покрывается ежемесячной абонентской платой Google Workspace , поэтому за использование API для таких приложений, как Gmail, Google Диск, Календарь, Документы, Таблицы и т. д., не взимается прямая оплата. Слайды.
Различные продукты Google оплачиваются по-разному, поэтому обязательно ознакомьтесь с соответствующей документацией для получения этой информации.
Краткое содержание
Теперь, когда Cloud Vision включено, таким же образом включите остальные три API (Google Drive, Cloud Storage, Google Sheets). В Cloud Shell используйте gcloud services enable
или в Cloud Console:
- Вернитесь в библиотеку API.
- Начните поиск, набрав несколько букв его названия.
- Выберите нужный API и
- Давать возможность
Вспеньте, промойте и повторите. Для облачного хранилища есть несколько вариантов: выберите «JSON API Google Cloud Storage». API Cloud Storage также ожидает активную учетную запись для выставления счетов.
7. Шаг 0. Настройте импорт и код авторизации.
Это начало фрагмента кода среднего размера, поэтому следование гибким практикам помогает обеспечить общую, стабильную и работающую часть инфраструктуры, прежде чем приступить к основному приложению. Doublecheck client_secret.json
доступен в вашем текущем каталоге; либо запустите ipython
и введите следующий фрагмент кода, либо сохраните его в analyze_gsimg.py
и запустите из оболочки (последнее предпочтительнее, поскольку мы продолжим добавлять в пример кода ):
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)
Этот основной компонент включает блоки кода для импорта модулей/пакетов, обработки учетных данных пользователя и создания конечных точек службы API. Ключевые части кода, которые вам следует просмотреть:
- Импорт функции
print()
делает этот пример совместимым с Python 2–3, а импорт библиотеки Google включает все инструменты, необходимые для взаимодействия с API Google. - Переменная
SCOPES
представляет разрешения, которые запрашивает пользователь. На данный момент есть только одно: разрешение на чтение данных с его Google Диска. - Оставшаяся часть кода обработки учетных данных считывается из кэшированных токенов OAuth2, возможно, обновляясь до нового токена доступа с помощью токена обновления, если срок действия исходного токена доступа истек.
- Если токены не были созданы или получение действительного токена доступа не удалось по другой причине, пользователь должен пройти трехэтапный поток OAuth2 (3LO): создать диалоговое окно с запрошенными разрешениями и предложить пользователю принять его. Как только они это сделают, приложение продолжит работу, в противном случаеtools.run_flow
tools.run_flow()
выдаст исключение и выполнение остановится. - Как только пользователь предоставляет разрешение, создается HTTP-клиент для связи с сервером, и все запросы подписываются учетными данными пользователя в целях безопасности. Затем создается конечная точка службы для Google Drive API (версия 3) с этим HTTP-клиентом, а затем назначается
DRIVE
.
Запуск приложения
При первом запуске скрипта у него не будет прав на доступ к файлам пользователя на Диске (вашим). Вывод выглядит следующим образом с приостановленным выполнением:
$ 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
Если вы работаете из Cloud Shell, перейдите к разделу «Из Cloud Shell», а затем прокрутите назад, чтобы просмотреть соответствующие экраны в разделе «Из локальной среды разработки», если это необходимо.
Из локальной среды разработки
Выполнение сценария командной строки приостанавливается, когда открывается окно браузера. Вы можете увидеть устрашающую страницу с предупреждением, которая выглядит следующим образом:
Это вполне обоснованное беспокойство, поскольку вы пытаетесь запустить приложение, которое обращается к пользовательским данным. Поскольку это всего лишь демонстрационное приложение, а вы — его разработчик, надеемся, вы достаточно доверяете себе, чтобы продолжить. Чтобы лучше это понять, поставьте себя на место вашего пользователя: вас просят разрешить чужому коду доступ к вашим данным. Если вы собираетесь опубликовать подобное приложение, вам придется пройти процедуру проверки , чтобы ваши пользователи не видели этот экран.
Нажав ссылку «Перейти к «небезопасному» приложению», вы увидите диалоговое окно разрешений OAuth2, которое выглядит примерно так, как показано ниже — мы постоянно совершенствуем наш пользовательский интерфейс, поэтому не волнуйтесь, если оно не совпадает:
Диалоговое окно потока OAuth2 отражает разрешения, которые запрашивает разработчик (через переменную SCOPES
). В данном случае это возможность просмотра и скачивания с Google Диска пользователя. В коде приложения эти области разрешений отображаются как URI, но они переводятся на язык, указанный языковым стандартом пользователя. Здесь пользователь должен явно предоставить авторизацию для запрошенных разрешений, в противном случае будет выдано исключение, и сценарий не сможет продолжить работу.
Вы даже можете получить еще одно диалоговое окно с запросом подтверждения:
ПРИМЕЧАНИЕ . Некоторые используют несколько веб-браузеров с входом в разные учетные записи, поэтому этот запрос на авторизацию может перейти на неправильную вкладку/окно браузера, и вам, возможно, придется вырезать и вставлять ссылку для этого запроса в браузер, в котором выполнен вход с правильными учетными записями. счет.
Из Cloud Shell
В Cloud Shell не появляется окно браузера, и вы застреваете. Помните, что диагностическое сообщение внизу предназначалось именно вам:
If your browser is on a different machine then exit and re-run this application with the command-line parameter --noauth_local_webserver
Вам придется нажать ^C (Ctrl-C или другую клавишу, чтобы остановить выполнение сценария) и запустить его из своей оболочки с дополнительным флагом. Когда вы запустите его таким образом, вместо этого вы получите следующий вывод:
$ 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:
(Игнорируем предупреждение, поскольку мы знаем, что storage.json
еще не создан и) Следуя инструкциям на другой вкладке браузера с этим URL-адресом, вы получите опыт, почти идентичный тому, что был описан выше для локальных сред разработки (см. снимки экрана выше). ). В конце находится последний экран с кодом подтверждения, который нужно ввести в Cloud Shell:
Скопируйте и вставьте этот код в окно терминала.
Краткое содержание
Кроме « Authentication successful
», не ожидайте никаких дополнительных результатов. Помните, что это всего лишь настройка... вы еще ничего не сделали. То, что вы сделали , — это успешное начало пути к чему-то, что с большей вероятностью будет выполнено правильно с первого раза. (Самое приятное то, что вам было предложено авторизоваться только один раз; все последующие выполнения пропускают его, поскольку ваши разрешения были кэшированы.) Теперь давайте заставим код выполнить настоящую работу, приводящую к фактическому выводу.
Поиск неисправностей
Если вместо отсутствия вывода вы получаете сообщение об ошибке, это может быть связано с одной или несколькими причинами, например, с этой:
8. Шаг 1. Загрузите изображение с Google Диска.
На предыдущем шаге мы рекомендовали создать код в виде analyze_gsimg.py
и редактировать его оттуда. Также возможно просто вырезать и вставить все непосредственно в iPython или стандартную оболочку Python, однако это более громоздко, поскольку мы собираемся продолжать создавать приложение по частям.
Предположим, ваше приложение авторизовано и конечная точка службы API создана. В вашем коде это представлено переменной DRIVE
. Теперь давайте найдем файл изображения на вашем Google Диске и
установите его в переменную с именем NAME
. Введите это плюс следующую функцию drive_get_img()
чуть ниже кода из шага 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
В коллекции Drive files()
имеется метод list()
, который выполняет запрос (параметр q
) для указанного файла. Параметр fields
используется для указания того, какие возвращаемые значения вас интересуют — зачем возвращать все обратно и замедлять работу, если вас не волнуют другие значения? Если вы новичок в использовании масок полей для фильтрации возвращаемых значений API, ознакомьтесь с этой записью в блоге и видео . В противном случае выполните запрос и получите возвращенный атрибут files
, по умолчанию используя пустой массив списка, если совпадений нет.
Если результатов нет, остальная часть функции пропускается и возвращается None
(неявно). В противном случае возьмите первый соответствующий ответ ( rsp[0]
), верните имя файла, его MIME-тип, временную метку последней модификации и, наконец, его двоичную полезную нагрузку, полученную функцией get_media()
(через ее идентификатор файла), также в files()
коллекция. (Имена методов могут немного отличаться в клиентских библиотеках других языков.)
Последняя часть — это «основная» часть всего приложения:
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)
Предполагая, что изображение с section-work-card-img_2x.jpg
на Диске находится на Диске и установлено значение FILE
, после успешного выполнения сценария вы должны увидеть выходные данные, подтверждающие, что он смог прочитать файл с Диска (но не сохранить его на вашем компьютере):
$ python3 analyze_gsimg.py Downloaded 'section-work-card-img_2x.jpg' (image/jpeg, 2020-02-27T09:27:22.095Z, size: 27781)
Поиск неисправностей
Если вы не получили успешный результат, подобный приведенному выше, это может быть связано с одной или несколькими причинами, например, с этой:
Краткое содержание
В этом разделе вы узнали, как (с помощью двух отдельных вызовов API) подключиться к Drive API, запросив определенный файл и затем загрузив его. Вариант использования для бизнеса: архивируйте данные вашего Диска и, возможно, анализируйте их, например, с помощью инструментов Google Cloud. Код вашего приложения на этом этапе должен совпадать с тем, что находится в репозитории по адресу step1-drive/analyze_gsimg.py
.
Узнайте больше о загрузке файлов на Google Диск здесь или посмотрите эту публикацию в блоге и видео . Эта часть кодовой лаборатории практически идентична всей вводной кодовой лаборатории Google Workspace API — вместо загрузки файла она отображает первые 100 файлов/папок на Google Диске пользователя и использует более ограниченную область действия.
9. Шаг 2. Архивируйте файл в облачное хранилище.
Следующим шагом будет добавление поддержки Google Cloud Storage . Для этого нам нужно импортировать другой пакет Python, io
. Убедитесь, что верхняя часть вашего импорта теперь выглядит так:
from __future__ import print_function
import io
Помимо имени файла на Диске, нам нужна информация о том, где хранить этот файл в облачном хранилище, в частности, имя «корзины», в которую вы собираетесь его поместить, и префикс(ы) «родительской папки». Подробнее об этом чуть позже:
FILE = 'YOUR_IMG_ON_DRIVE'
BUCKET = 'YOUR_BUCKET_NAME'
PARENT = '' # YOUR IMG FILE PREFIX
Несколько слов о сегментах: Cloud Storage предоставляет аморфное хранилище BLOB-объектов. При загрузке туда файлов он не понимает концепцию типов файлов, расширений и т. д., как это делает Google Drive. Они просто «капли» для Cloud Storage. Более того, в Cloud Storage нет понятия папок или подкаталогов.
Да, вы можете использовать косую черту ( /
) в именах файлов, чтобы представить абстракцию нескольких подпапок, но в конце концов все ваши большие двоичные объекты попадают в корзину, а « /
» — это просто символы в их именах файлов. Дополнительную информацию можно найти на странице соглашений об именах сегментов и объектов .
На шаге 1 выше запросили область действия Диска только для чтения. На тот момент это все, что вам нужно. Теперь требуется разрешение на загрузку (чтение и запись) в Cloud Storage. Измените SCOPES
с одной строковой переменной на массив (кортеж [или список] Python) областей разрешений, чтобы он выглядел следующим образом:
SCOPES = (
'https://www.googleapis.com/auth/drive.readonly',
'https://www.googleapis.com/auth/devstorage.full_control',
)
Теперь создайте конечную точку службы для Cloud Storage прямо под точкой для Диска. Примечание Мы слегка изменили вызов, чтобы повторно использовать тот же клиент -объект HTTP, поскольку нет необходимости делать новый, когда он может быть общим ресурсом.
# create API service endpoints
HTTP = creds.authorize(Http())
DRIVE = discovery.build('drive', 'v3', http=HTTP)
GCS = discovery.build('storage', 'v1', http=HTTP)
Теперь добавьте эту функцию (после drive_get_img()
), которая загружается в облачное хранилище:
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()
objects.().insert()
требует имени ведра, метаданных файлов и самого двоичного капли. Чтобы отфильтровать возвращаемые значения, переменная fields
запрашивает только имена ведра и объектов, возвращаемых из API. Чтобы узнать больше об этих полевых масках по запросам для чтения API, ознакомьтесь с этим сообщением и видео .
Теперь интегрируйте использование gcs_blob_upload()
в основное приложение:
# 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)
Переменная gcsname
объединяет любое «родительское подкаталорие», добавленные с самим именем файла, и при префиксе с именем ведра выдается впечатление, что вы архивируете файл в " /bucket/parent.../filename
". Слитите этот кусок сразу после первой print()
чуть выше предложения else
, чтобы весь «основной» выглядел следующим образом:
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)
Допустим, мы указываем ведро с именем « vision-demo
» с « analyzed_imgs
» как «родительский подкаталог». После того, как вы установите эти переменные и снова запустите скрипт, section-work-card-img_2x.jpg
будет загружен с диска, а затем загружена на облачное хранилище, верно? НЕТ!
$ 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">
Посмотрите внимательно, в то время как загрузка диска преуспела, загрузка в облачное хранилище не удалась. Почему?
Причина в том, что когда мы авторизовали это приложение изначально для шага 1, мы только разрешили доступ только для чтения к Google Drive. В то время как мы добавили сферу считываемой записи для облачного хранилища, мы никогда не побуждали пользователя разрешить этот доступ. Чтобы заставить его работать, нам нужно взорвать файл storage.json
, в котором отсутствует этот объем и повторный разряд.
После повторного выхода (подтвердите это, заглядывая в storage.json
и увидите там обе сферы), ваш вывод будет тогда, как и ожидалось:
$ 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'
Краткое содержание
Это большое дело, показывая вам относительно мало строк кода, как передавать файлы между обеими облачными системами хранения. Приведенный бизнес здесь предназначен для резервного копирования, возможно, ограниченного ресурса для «холодного», более дешевого хранилища, как упоминалось ранее. Cloud Storage предлагает различные классы хранения в зависимости от того, получаете ли вы доступ к вашим данным регулярно, ежемесячно, ежеквартально или ежегодно.
Конечно, разработчики время от времени спрашивают нас, почему существуют и Google Drive, и облачное хранилище. В конце концов, разве они оба хранит хранилище в облаке? Вот почему мы сделали это видео . Ваш код на этом этапе должен соответствовать тому, что находится в репо с step2-gcs/analyze_gsimg.py
.
10. Шаг 3: анализировать с помощью облачного видения
Несмотря на то, что мы теперь знаем, что вы можете перемещать данные между Google Cloud и Google Workspace, мы еще не провели никакого анализа, поэтому время отправить изображение в Cloud Vision для аннотации метки AKA обнаружение объекта. Для этого нам нужно основываться на 64-й данных, что означает другой модуль Python, base64
. Убедитесь, что ваш главный раздел импорта теперь выглядит так:
from __future__ import print_function
import base64
import io
По умолчанию API Vision возвращает все этикетки, которые он находит. Чтобы сохранить ситуацию в соответствии, давайте запросим только топ -5 (конечно, регулируемый пользователем). Для этого мы TOP
использовать постоянную переменную; Добавьте его под все остальные константы:
FILE = 'YOUR_IMG_ON_DRIVE'
BUCKET = 'YOUR_BUCKET_NAME'
PARENT = '' # YOUR IMG FILE PREFIX
TOP = 5 # TOP # of VISION LABELS TO SAVE
Как и в предыдущих шагах, нам нужна еще одна область разрешения, на этот раз для API Vision. Обновить SCOPES
со своей строкой:
SCOPES = (
'https://www.googleapis.com/auth/drive.readonly',
'https://www.googleapis.com/auth/devstorage.full_control',
'https://www.googleapis.com/auth/cloud-vision',
)
Теперь создайте конечную точку службы для Cloud Vision, чтобы она соответствовала остальным, как это:
# 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)
Теперь добавьте эту функцию, которая отправляет полезную нагрузку изображения в 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'])
Вызов images().annotate()
требует данных плюс желаемые функции API. Верхняя пятерка метки также является частью полезной нагрузки (но совершенно необязательно). Если вызов успешным, полезная нагрузка возвращает 5 лучших меток объектов плюс оценка доверия. На изображении объект. (Если ответ не вернется, назначьте пустой словарь Python, поэтому следующее оператор if
оператор не работает.) Эта функция просто сочетает эти данные в строку CSV для возможного использования в нашем отчете.
Эти 5 строк, которые называют vision_label_img()
должны быть размещены сразу после успешной загрузки в облачное хранилище:
# 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)
С этим дополнением весь основной драйвер должен выглядеть так:
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)
Удаление storage.json
, чтобы обновить область и повторное использование обновленного приложения, должно привести к выводу, аналогично следующему, отметив добавление анализа облачного зрения:
$ 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
Краткое содержание
Не у всех есть опыт машинного обучения, чтобы создать и обучать свои собственные модели ML для анализа их данных. Команда Google Cloud предоставила некоторые из предварительно обученных моделей Google для общего использования и поставила их за API, помогая демократизировать AI & ML для всех.
Если вы разработчик и можете вызвать API, вы можете использовать машинное обучение. Cloud Vision - это лишь одна из сервисов API, с которыми вы можете использовать для анализа ваших данных. Узнайте о других здесь . Ваш код должен теперь соответствовать тому, что находится в репо с step3-vision/analyze_gsimg.py
.
11. Шаг 4: Создайте отчет с Google Sheets
На данный момент вы смогли архивировать корпоративные данные и проанализировать их, но то, чего не хватает, является кратким изложением этой работы. Давайте организуем все результаты в один отчет, который вы можете передать своему боссу. Что может быть более презентабельно для управления, чем электронная таблица?
Для API Google Sheets не требуется дополнительного импорта, и единственная новая необходимая информация - это идентификатор файла существующей электронной таблицы, уже отформатированной и ожидающей новой строки данных, отсюда постоянная SHEET
. Мы рекомендуем вам создать новую таблицу, которая похожа на следующее:
URL -адрес для этой электронной таблицы будет выглядеть следующим образом: https://docs.google.com/spreadsheets/d/
FILE_ID
/edit
. Возьмите этот FILE_ID
и назначьте его в качестве укуса на SHEET
.
Мы также пробили крошечную функцию с именем k_ize()
, которая преобразует байты в килобиты, определяя ее как Python lambda
, поскольку это простой 1-линер. Оба из них интегрированы с другими константами, выглядят так:
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
Как и в предыдущих шагах, нам нужна еще одна область разрешения, на этот раз чтение-запись для API Sheets. SCOPES
теперь имеют все 4 необходимости:
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',
)
Теперь создайте конечную точку службы для Google Sheets рядом с другими, так что это выглядит так:
# 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)
Функциональность sheet_append_row()
проста: возьмите ряд данных и идентификатор листа, затем добавьте эту строку в этот лист:
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')
Для вызова spreadsheets().values().append()
требуется идентификатор файла листа, диапазон ячеек, как следует ввести данные, и сами данные. Идентификатор файла прост, диапазон ячеек приведен в обозначениях A1 . Диапазон « Sheet1
» означает весь лист - это сигнализирует в API, чтобы добавить строку после всех данных в листе. Существует пара вариантов того , как данные должны быть добавлены в лист , « RAW
» (введите словесные данные строковых данных) или « USER_ENTERED
» (напишите данные, как если бы пользователь ввел их на клавиатуре с приложением Google Sheets, Сохранение любых функций форматирования ячейки).
Если вызов успешным, возвращаемое значение на самом деле не имеет ничего очень полезного, поэтому мы решили получить количество ячеек, обновленных по запросу API. Ниже приведен код, который вызывает эту функцию:
# 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')
Лист Google имеет столбцы, представляющие такие данные, как любой родительский «подкаталог», местоположение архивного файла на облачном хранилище (ковш + имя файла), миметип файла, размер файла (первоначально в байтах, но преобразован в килобиты с k_ize()
) и строка меток облачного видения. Также обратите внимание, что архивное местоположение является гиперссылкой, поэтому ваш менеджер может нажать, чтобы подтвердить, что оно было безопасно.
Добавление блока кода выше сразу после отображения результатов Cloud Vision, основная часть, управляемая приложением, теперь завершена, хотя структурно немного сложна:
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)
Удаление storage.json
в последний раз и повторное выполнение обновленного приложения должно привести к выводу, аналогично следующему, отметив добавление анализа облачного зрения:
$ 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
Дополнительная линия вывода, хотя и полезна, лучше визуализируется, заглядывая на обновленный лист Google, причем последняя строка (строка 7 в примере ниже) добавлена к существующему набору данных, добавленному ранее:
Краткое содержание
В первых 3 этапах этого урока вы подключились к Google Workspace и Google Cloud API, чтобы перемещать данные и проанализировать их, что представляет 80% всей работы. Однако, в конце концов, ничего из этого ничего не означает, если вы не можете представить руководству все, что вы достигли. Чтобы лучше визуализировать результаты, суммирование всех результатов в сгенерированном отчете говорит о многом.
Для дальнейшего повышения полезности анализа, в дополнение к написанию результатов в электронную таблицу, одним из возможных улучшений было бы индексировать эти 5 лучших метков. Команда, но мы оставляем это в качестве упражнения для читателей.
На данный момент наши результаты находятся в листе и доступны для управления. Код для вашего приложения на этом этапе должен соответствовать тому, что находится в репо на step4-sheets/analyze_gsimg.py
. Последний шаг-очистить код и превратить его в полезный сценарий.
12. *Последний шаг: рефактор
(Необязательно) Хорошо иметь рабочее приложение, однако можем ли мы улучшить его? Да, особенно главное применение, которое кажется беспорядочным беспорядком. Давайте поместим это в свою собственную функцию и приводим это к тому, чтобы получить пользовательский ввод, а не фиксированные константы. Мы сделаем это с модулем argparse
. Кроме того, давайте запустим вкладку Web Browser, чтобы отобразить лист, как только мы записали на него наш строку данных. Это выполнимо с модулем webbrowser
. Сплеть эти импорты с другими, чтобы лучший импорт выглядел следующим образом:
from __future__ import print_function
import argparse
import base64
import io
import webbrowser
Чтобы использовать этот код в других приложениях, нам нужна возможность подавить вывод, поэтому давайте добавим флаг DEBUG
, чтобы это произошло, добавив эту линию в конце секции констант рядом с верхом:
DEBUG = False
Теперь о главном теле. Когда мы строили этот образец, вы должны были начать чувствовать себя «некомфортно», поскольку наш код добавляет еще один уровень гнездования с каждой добавленной службой. Если вы чувствовали себя так, вы не одиноки, так как это добавляет сложности кода, как описано в этом блоге Google Testing .
Следуя этой наилучшей практике, давайте реорганизуем основную часть приложения в функцию и return
в каждой «точке разрыва» вместо гнездования (не возвращает None
, если какой -либо шаг не удастся, и True
если все это удастся):
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
Это аккуратно и чище, оставляя позади это рекурсивное ощущение цепи if-else
, а также снижение сложности кода, как описано выше. Последний кусок головоломки - создать «реальный» основной драйвер, позволяющий настраивать пользователь и минимизировать вывод (если не желательно):
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)
Если все шаги успешны, сценарий запускает веб -браузер в электронную таблицу, указанную там, где была добавлена новая строка данных.
Краткое содержание
Нет необходимости удалять storage.json
, поскольку никаких изменений в области масштабов не произошло. Перезагрузка обновленного приложения раскрывает новое окно браузера, открытое для модифицированного листа, меньше выводов, а выпуск опции -h
показывает пользователям их параметры, в том числе -v
для восстановления ныне подавленных линий вывода, которые можно увидеть ранее:
$ 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
Другие параметры позволяют пользователям выбирать разные имена файлов диска, облачное хранилище «подкаталогация» и имена ведер, топ «N» результаты из Cloud Vision и идентификатора файлов электронной таблицы (листы). С этими последними обновлениями окончательная версия вашего кода теперь должна соответствовать тому, что находится в репо в final/analyze_gsimg.py
, а также здесь, в полном объеме:
'''
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)
Мы предпримем каждую попытку поддерживать содержимое этого урока в актуальном состоянии, но будут случаи, когда репо будет иметь самую последнюю версию кода.
13. Поздравляю!
В этом коделабе, безусловно, было много обучения, и вы достигли этого, выжив один из более длинных коделабов. В результате вы взяли на себя возможный сценарий предприятия с примерно ~ 130 строк Python, используя все Google Cloud и Google Workspace, и перемещающиеся данные между ними для создания рабочего решения. Не стесняйтесь исследовать репо с открытым исходным кодом для всех версий этого приложения (подробнее ниже).
Очистить
- Использование API Google Cloud не является бесплатным, в то время как API Google Workspace охватываются вашей ежемесячной платой за подписку Google Workspace (пользователи потребителей Gmail имеют ежемесячную плату в рамках нуля), поэтому для пользователей Google Workspace не требуется оборудование API. Для Google Cloud вы можете перейти на панель панели Cloud Console и проверить биллинговую карту »на предмет оценочных сборов.
- Для облачного видения вам разрешено фиксированное количество вызовов API в месяц бесплатно. Поэтому, пока вы остаетесь в этих пределах, нет необходимости что -то закрывать, и вы не должны отключить/удалить свой проект. Более подробную информацию о выставлении счетов и бесплатной квоты API Vision можно найти на его странице ценообразования .
- Некоторые пользователи облачного хранилища получают бесплатное количество хранения в месяц. Если изображения, которые вы архивируете, используя этот CodeLab, не заставляют вас превышать эту квоту, вы не будете нести каких -либо обвинений. Более подробную информацию о выставлении счетов GCS и бесплатной квоты можно найти на его странице ценообразования . Вы можете просмотреть и легко удалять капли из браузера облачного хранения .
- Ваше использование Google Drive также может иметь квоту хранения, и если вы превышаете его (или находитесь близко к нему), вы можете фактически рассмотреть возможность использования инструмента, который вы встроили в этот кодовой Водить машину. Более подробную информацию о хранилище Google Drive можно найти на соответствующей странице ценообразования для Google Workspace Basic пользователей или пользователей Gmail/Consumer .
В то время как большинство бизнес-планов Google Workspace и предприятия имеют неограниченное хранилище, это может привести к загромождению и/или ошеломляющему, а приложение, которое вы построили в этом уроке, является отличным способом архивирования посторонних файлов и очистки вашего Google Drive.
Альтернативные версии
В то время как final/analyze_gsimg.py
- это «последняя» официальная версия, над которой вы работаете в этом уроке, это не конец истории. Одна из проблем с окончательной версией приложения заключается в том, что оно использует более старые библиотеки авторов, которые устарели. Мы выбрали этот путь, потому что на момент написания этой статьи более новые библиотеки авторов не поддерживали несколько ключевых элементов: управление хранилищем токенов OAuth и безопасность потоков.
Текущие (новые) библиотеки авторов
Тем не менее, в какой -то момент более старые библиотеки авторов больше не будут поддерживать, поэтому мы рекомендуем вам просмотреть версии, которые используют более новые (текущие) библиотеки автоза alt
собственное решение, которое есть). Ищите файлы с *newauth*
в их именах.
Google Cloud Product Client Libraries
Google Cloud рекомендует всем разработчикам использовать клиентские библиотеки продукта при использовании API Google Cloud. К сожалению, в настоящее время API не Google Cloud не имеют таких библиотек. Использование библиотек нижнего уровня позволяет обеспечить последовательное использование API и функции лучше читаемости. Подобно рекомендации выше, альтернативные версии с использованием клиентов Google Cloud Product Bibraries доступны в alt
Polder's для репо для просмотра. Ищите файлы с *-gcp*
в их именах.
Авторизация учетной записи услуги
Работая исключительно в облаке, обычно нет ни людей, ни (человеческих) данных, принадлежащих пользователю, поэтому именно поэтому учетные записи услуг и авторизация учетной записи услуг используются в первую очередь с Google Cloud. Тем не менее, документы Google Workspace, как правило, принадлежат (человеческим) пользователям, поэтому в этом руководстве используется авторизация учетной записи пользователя. Это не означает, что невозможно использовать API Google Workspace с учетными записями. Пока эти учетные записи имеют соответствующий уровень доступа, они, безусловно, могут использоваться в приложениях. Подобно вышеупомянутому, альтернативные версии с использованием авторизации учетной записи службы доступны в alt
Polder для репо для просмотра. Ищите файлы с *-svc*
в их именах.
Альтернативный каталог версий
Ниже вы найдете все альтернативные версии final/analyze_gsimg.py
, каждый из которых имеет один или несколько из вышеприведенных свойств. В имени файла каждой версии ищите:
- «
oldauth
» для версий, используя более старые библиотеки Auth (в дополнение кfinal/analyze_gsimg.py
) - «
newauth
» для тех, кто использует текущие/более новые библиотеки автоза. - «
gcp
» для тех, кто использует клиентские библиотеки Google Cloud Product, IE, Google-Cloud-Storage и т. Д. - «
svc
» для тех, кто использует учетную запись службы («SVC Acct») Auth вместо учетной записи пользователя
Вот все версии:
Имя файла | Описание |
| Основной образец; использует более старые библиотеки авторов |
| То же самое, что и |
| То же самое, что и |
| То же, что и |
| То же самое, что и |
| То же, что и |
| То же, что и |
| То же самое, что и |
В сочетании с оригинальной final/analyze_gsimg.py
у вас есть все возможные комбинации окончательного решения, независимо от вашей среды разработки Google API, и вы можете выбрать тот, который наилучшим образом соответствует вашим потребностям. Также см. alt/README.md
для аналогичного объяснения.
Дополнительное исследование
Ниже приведены несколько идей о том, как вы можете сделать это упражнение еще дальше. Установка задачи, которое может обработать текущее решение, может быть расширено, что позволяет сделать эти улучшения:
- ( Несколько изображений в папках ) Вместо того, чтобы обрабатывать одно изображение, допустим, у вас были изображения в папках Google Drive .
- ( Несколько изображений в zip -файлах ) вместо папки изображений, как насчет архивов Zip, содержащих файлы изображений? При использовании Python рассмотрите модуль
zipfile
. - ( Анализируйте этикетки зрения ), кластер, похожие изображения вместе, возможно, начните с поиска наиболее распространенных метков, а затем второго наиболее распространенного и так далее.
- ( Создать диаграммы ) Последующее наблюдение № 3, генерируйте диаграммы с API листа на основе анализа и категоризации API видения видения.
- ( Категоризируйте документы ) . Используя ваши решения выше, эти PDF -файлы могут находиться в папках привода или на zip Archives на диске.
- ( Создание презентаций ) Используйте API слайдов, чтобы генерировать слайд -колоду из содержимого отчета Google Sheet. Для вдохновения, ознакомьтесь с этим сообщением и видео о создании слайдов из данных электронных таблиц.
- ( Экспорт как PDF ) Экспортируйте электронную таблицу и/или слайд -палубу в качестве PDF, однако это не особенность листов или скольжения API. Подсказка : Google Drive API. Дополнительный кредит : объедините как листы, так и слайды PDF -файлов в один мастер PDF с такими инструментами, как Ghostscript (Linux, Windows) или
Combine PDF Pages.action
.
Узнать больше
Кодлабы
- Intro в Google Workspace API (Google Drive API) (Python)
- Использование облачного видения с Python (Python)
- Создайте индивидуальные инструменты отчетности (Google Sheets API) (JS/Node)
- Загрузить объекты в Google Cloud Storage (кодирование не требуется)
Общий
Google Рабочая область
- Главная страница Google Drive API
- Google Sheets API домашняя страница
- Обзор и документация разработчика Google Workspace и документация
Google Облако
- Домашняя страница Google Cloud Storage
- Google Cloud Vision Home Page и живая демонстрация
- Документация API Cloud Vision
- Vision API -изображение
- Python на Google Cloud
- Google Cloud Product Client Libraries
- Документация Google Cloud
Лицензия
Эта работа распространяется под лицензией Creative Commons Attribution 2.0 Generic License.