Archivo de imágenes, análisis y generación de informes con G Suite y GCP

Este codelab imagina un posible flujo de trabajo empresarial: archivo de imágenes, análisis y generación de informes. Imagine a su organización que tiene una serie de imágenes que ocupan espacio en un recurso limitado. Deseas archivar esos datos, analizar esas imágenes y, lo que es más importante, generar un informe que resuma las ubicaciones archivadas y los resultados del análisis, recopilados y preparado para el consumo. Google Cloud proporciona las herramientas para que esto suceda, utilizando API de dos de sus líneas de productos, G Suite y Google Cloud Platform (GCP).

En este caso, el usuario de la empresa tendrá imágenes en Google Drive. Se recomienda realizar una copia de seguridad de un almacenamiento más "crático" más económico, como las clases de almacenamiento disponibles en Google Cloud Storage. Google Cloud Vision permite a los desarrolladores integrar fácilmente las funciones de detección de visión en las aplicaciones, como la detección de objetos y puntos de referencia, el reconocimiento óptico de caracteres (OCR), etc. Por último, una Hojas de cálculo de Google. Esta es una herramienta de visualización útil que permite resumir todo esto para su jefe.

Después de completar este codelab para crear una solución que aproveche todos los beneficios de Google Cloud, esperamos que le sirva de inspiración para crear un producto mucho más impactante para su organización o sus clientes.

Qué aprenderá

  • Cómo usar Cloud Shell
  • Cómo autenticar las solicitudes a la API
  • Cómo instalar la biblioteca cliente de las API de Google para Python
  • Cómo habilitar las API de Google
  • Cómo descargar archivos de Google Drive
  • Cómo subir objetos o BLOB a Cloud Storage
  • Cómo analizar datos con Cloud Vision
  • Cómo escribir filas en Hojas de cálculo de Google

Qué necesitará

  • Una Cuenta de Google (es posible que las cuentas de G Suite requieran la aprobación del administrador)
  • Un proyecto de Google Cloud Platform con una cuenta de facturación de GCP activa
  • Conocimientos de comandos de shell/terminal de sistema operativo
  • Habilidades básicas en Python (2 o 3), pero puedes usar cualquier lenguaje compatible

Sería útil tener experiencia con los cuatro productos de Google Cloud mencionados anteriormente, pero no es obligatorio. Si el tiempo te permite familiarizarte con ellos por separado, puedes hacer codelabs de cada uno antes de abordar el ejercicio aquí:

Encuesta

¿Cómo usarás este instructivo?

Ler Leer y completar los ejercicios

¿Cómo calificarías tu experiencia con Python?

Principiante Intermedio Avanzado

¿Cómo calificarías tu experiencia con los servicios de Google Cloud Platform?

Principiante Intermedio Avanzado

¿Cómo calificaría su experiencia con los servicios para desarrolladores de G Suite?

Principiante Intermedio Avanzado

¿Desea ver más codelabs "orientados a empresas" en comparación con aquellos que son presentaciones de funciones del producto?

No Más

Configuración del entorno a su propio ritmo

  1. Accede a Cloud Console y crea un proyecto nuevo o reutiliza uno existente. (Si todavía no tiene una cuenta de Gmail o de G Suite, debe crear una).

dMbN6g9RawQj_VXCSYpdYncY-DbaRzr2GbnwoV7jFf1u3avxJtmGPmKpMYgiaMH-qu80a_NJ9p2IIXFppYk8x3wyymZXavjglNLJJhuXieCem56H30hwXtd8PvXGpXJO9gEUDu3cZw

ci9Oe6PgnbNuSYlMyvbXF1JdQyiHoEgnhl4PlV_MFagm2ppzhueRkqX4eLjJllZco_2zCp0V0bpTupUSKji9KkQyWqj11pqit1K1faS1V6aFxLGQdkuzGp4rsQTan7F01iePL5DtqQ

8-tA_Lheyo8SscAVKrGii2coplQp2_D1Iosb2ViABY0UUO1A8cimXUu6Wf1R9zJIRExL5OB2j946aIiFtyKTzxDcNnuznmR45vZ2HMoK3o67jxuoUJCAnqvEX6NgPGFjCVNgASc-lg

Recuerde el ID de proyecto, un nombre único en todos los proyectos de Google Cloud (el nombre anterior ya se encuentra en uso y no lo podrá usar). Se mencionará más adelante en este codelab como PROJECT_ID.

  1. A continuación, deberá habilitar la facturación en Cloud Console para usar los recursos de Google Cloud.

Ejecutar este codelab debería costar mucho, si nada. Asegúrate de seguir las instrucciones de la sección "Limpieza", que te aconseja cómo cerrar recursos para que no se te facture más allá de este instructivo. Los usuarios nuevos de Google Cloud son aptos para participar en el programa Prueba gratuita de USD 300.

Iniciar Cloud Shell

Resumen

Aunque puede desarrollar código de manera local en su laptop, un objetivo secundario de este codelab es enseñarle a usar Google Cloud Shell, un entorno de línea de comandos que se ejecuta en la nube a través de su navegador web moderno.

Activar Cloud Shell

  1. En Cloud Console, haz clic en Activar Cloud ShellH7JlbhKGHITmsxhQIcLwoe5HXZMhDlYue4K-SPszMxUxDjIeWfOHBfxDHYpmLQTzUmQ7Xx8o6OJUlANnQF0iBuUyfp1RzVad_4nCa0Zz5LtwBlUZFXFCWFrmrWZLqg1MkZz2LdgUDQ.

zlNW0HehB_AFW1qZ4AyebSQUdWm95n7TbnOr7UVm3j9dFcg6oWApJRlC0jnU1Mvb-IQp-trP1Px8xKNwt6o3pP6fyih947sEhOFI4IRF0W7WZk6hFqZDUGXQQXrw21GuMm2ecHrbzQ

Si nunca ha iniciado Cloud Shell, aparecerá una pantalla intermedia (debajo de la mitad inferior de la página) que describe la información. Si ese es el caso, haga clic en Continuar (y no volverá a verlo). Así es como se ve la pantalla única:

kEPbNAo_w5C_pi9QvhFwWwky1cX8hr_xEMGWySNIoMCdi-Djx9AQRqWn-__DmEpC7vKgUtl-feTcv-wBxJ8NwzzAp7mY65-fi2LJo4twUoewT1SUjd6Y3h81RG3rKIkqhoVlFR-G7w

El aprovisionamiento y la conexión a Cloud Shell solo tomará unos minutos.

pTv5mEKzWMWp5VBrg2eGcuRPv9dLInPToS-mohlrqDASyYGWnZ_SwE-MzOWHe76ZdCSmw0kgWogSJv27lrQE8pvA5OD6P1I47nz8vrAdK7yR1NseZKJvcxAZrPb8wRxoqyTpD-gbhA

Esta máquina virtual está cargada con todas las herramientas para desarrolladores que necesitará. Ofrece un directorio principal persistente de 5 GB y se ejecuta en Google Cloud, lo que permite mejorar considerablemente el rendimiento de la red y la autenticación. Gran parte de su trabajo en este codelab, si no todo, se puede hacer simplemente con un navegador o su Chromebook.

Una vez conectado a Cloud Shell, debería ver que ya está autenticado y que el proyecto ya está configurado con su ID del proyecto.

  1. En Cloud Shell, ejecute el siguiente comando para confirmar que está autenticado:
gcloud auth list

Resultado del comando

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

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
gcloud config list project

Resultado del comando

[core]
project = <PROJECT_ID>

De lo contrario, puede configurarlo con este comando:

gcloud config set project <PROJECT_ID>

Resultado del comando

Updated property [core/project].

Este codelab requiere que uses el lenguaje Python (aunque muchos idiomas son compatibles con las bibliotecas cliente de las API de Google, por lo que puedes compilar algo equivalente en tu herramienta de desarrollo favorita y simplemente usar Python como seudocódigo). En particular, este codelab admite Python 2 y 3, pero te recomendamos que cambies a 3.x lo antes posible.

Cloud Shell es una opción disponible para los usuarios directamente desde Cloud Console, pero no requiere un entorno de desarrollo local, por lo que este instructivo se puede realizar por completo en la nube con un navegador web. Cloud Shell es particularmente útil si estás desarrollando o planeas continuar desarrollando con productos y API de GCP. Más específicamente para este codelab, Cloud Shell ya instaló ambas versiones de Python.

Cloud Shell también tiene instalado IPython... es un intérprete de Python interactivo de nivel superior que recomendamos, sobre todo si formas parte de la comunidad de ciencia de datos o de aprendizaje automático. Si es así, IPython es el intérprete predeterminado para Notebooks de Jupyter y Colab, notebooks de Jupyter alojados en Google Research.

IPython favorece un intérprete de Python 3 primero, pero recurre a Python 2 si 3.x no está disponible. Se puede acceder a IPython desde Cloud Shell, pero también se puede instalar en un entorno de desarrollo local. Sal con ^D (Ctrl-d) y acepta la oferta para salir. El resultado de ejemplo de inicio de ipython tendrá el siguiente aspecto:

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

Si IPython no es su preferencia, el uso de un intérprete interactivo estándar de Python (ya sea Cloud Shell o su entorno de desarrollo local) es perfectamente aceptable (también sal con ^D):

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

El codelab también supone que tienes la herramienta de instalación pip (administrador de paquetes de Python y agente de resolución de dependencias). Viene con las versiones 2.7.9 (o versiones posteriores) o 3.4+. Si tienes una versión de Python anterior, consulta esta guía para obtener instrucciones de instalación. Según tus permisos, es posible que necesites sudo o acceso de superusuario, pero en general este no es el caso. También puedes usar pip2 o pip3 de forma explícita a fin de ejecutar pip para versiones específicas de Python.

En el resto del codelab, se supone que estás usando Python 3 (se proporcionarán instrucciones específicas para Python 2 si difieren de forma significativa de 3.x).

*Crea y usa entornos virtuales

Esta sección es opcional y solo es necesaria para quienes deben usar un entorno virtual para este codelab (según la barra lateral de advertencia que se muestra arriba). Si solo tienes Python 3 en tu computadora, puedes emitir este comando para crear un virtualenv llamado my_env (puedes elegir otro nombre si lo deseas):

virtualenv my_env

Sin embargo, si tienes Python 2 y 3 en tu computadora, te recomendamos que instales un virtualenv de Python 3 que puedes hacer con -p flag de la siguiente manera:

virtualenv -p python3 my_env

Para ingresar a su virtualenv recién creado, "actívalo" de la siguiente manera:

source my_env/bin/activate

Para confirmar que está en el entorno, observe que el indicador de shell ya está precedido por el nombre de su entorno, por ejemplo,

(my_env) $

Ahora deberías poder pip install realizar la instalación de los paquetes requeridos, ejecutar el código dentro de este proceso, etc. Otro beneficio es que, si la abrumas por completo, entra en una situación en la que la instalación de Python está dañada, etcétera. a este entorno sin afectar el resto del sistema.

Este codelab requiere el uso de la biblioteca cliente de las API de Google para Python, por lo que se trata de un proceso de instalación sencillo o que no necesitas hacer nada.

Anteriormente, te recomendamos que uses Cloud Shell para tu comodidad. Puedes completar el instructivo completo desde un navegador web en la nube. Otro motivo para usar Cloud Shell es que muchas herramientas de desarrollo populares y las bibliotecas necesarias ya están instaladas.

*Instalar bibliotecas cliente

Esto es opcional. Esto se puede omitir si usas Cloud Shell o un entorno local en el que ya instalaste las bibliotecas cliente. Solo debes hacer esto si desarrollas de manera local y no tienes (o no sabes si las instalaste). La manera más sencilla es usar pip (o pip3) para realizar la instalación (incluida la actualización de pip si es necesario):

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

Confirmar instalación

Con este comando, se instala la biblioteca cliente y todos los paquetes de los que depende. Ya sea que uses Cloud Shell o tu propio entorno, verifica que la biblioteca cliente esté instalada mediante la importación de los paquetes necesarios y confirma que no haya errores de importación (no output):

python3 -c "import googleapiclient, httplib2, oauth2client"

Si usa Python 2 en lugar de Cloud Shell, recibirá una advertencia que indica que la asistencia dejó de estar disponible:

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

Cuando pueda ejecutar correctamente el comando "test" de importación (sin errores/salida), estará listo para comenzar a hablar con las API de Google.

Resumen

Como este es un codelab intermedio, la suposición de que ya tiene experiencia con la creación y el uso de proyectos en la consola. Si no está familiarizado con las API de Google y con las API de G Suite específicamente, pruebe con el codelab introductorio de las G Suite. Además, si sabes cómo crear (o volver a usar) las cuentas de usuario existentes (no la cuenta de servicio), descarta el archivo client_secret.json en tu directorio de trabajo, omite el siguiente módulo y ve a “Habilitar las API de Google”.

Esta sección se puede omitir si ya creaste las credenciales de autorización de cuentas de usuario y estás familiarizado con el proceso. Este proceso es diferente a la autorización de la cuenta de servicio cuya técnica es diferente, por lo que continúa.

Introducción a la autorización (además de una autenticación)

Para hacer solicitudes a las API, tu aplicación debe tener la autorización adecuada. La autenticación, una palabra similar, describe las credenciales de acceso. El proceso de autenticación se lleva a cabo cuando usted accede a su cuenta de Google con un nombre de usuario y una contraseña. Una vez autenticado, el paso siguiente es si usted (o, en cambio, su código) está autorizado para acceder a los datos, como archivos BLOB en Cloud Storage o los archivos personales de un usuario. en Google Drive.

Las API de Google admiten varios tipos de autorización, pero la más común para los usuarios de la API de G Suite es la autorización del usuario, ya que la aplicación de ejemplo en este codelab accede a datos que pertenecen a usuarios finales. Esos usuarios finales deben otorgar permiso para que su aplicación acceda a sus datos. Esto significa que tu código debe obtener credenciales OAuth2 de cuentas de usuario.

Para obtener las credenciales de OAuth2 para la autorización de usuario, regrese al administrador de la API y seleccione la pestaña "Credenciales" en el panel de la izquierda:

Y33PZ_rJC1y7NH7Rrvq1kN_WxZ9CppDGJK8tTSaha298Jlm5pMqgnyweIO4oX34fcLy0_VI4gihYu5wpEM_LeJg1iDAFoidhUVyfqJX3QTzODQ_OGjHLXYBxPpUvihCJi9JGwvMREw

Cuando vea allí, verá todas sus credenciales en tres secciones separadas:

ComE4qh76dwZbIehkDUm1QawHGia_qVe7w7rkmgbeo_wjWS--kqXCt4_zvm55iy_RXA8dKYKvBxIKazkcYQ8871SA_kNslbvum_n1Ju4k9qJJSMtDhPAnofcvIlqlKm1nu7PBQhmEg

La primera es para las claves de API, el segundo ID de cliente de OAuth 2.0 y las últimas cuentas de servicio de OAuth2: utilizamos la de en el medio

Crea las credenciales

En la página Credenciales, haga clic en el botón + Crear credenciales en la parte superior. Allí, verá un diálogo donde debería elegir "ID de cliente de OAuth":

C7jTddfrczo3GewPGCxbxX13GawtFc6FGvAPFusPc_IW-tr5M6xgXd1OzOHOUTo86WDa9fXiCITogv9b3wAgOcYM7xS3AmVNaPdTxbAynIe_sia2_x3LEPsBrdbX8NjeI2WaHRioOA

En la pantalla siguiente, tienes 2 acciones: configurar la autorización de consentimiento de tu aplicación y seleccionar el tipo de aplicación:

El9_aqPQ6Q9hOsOp3JUC5qnCm_A_BVI-oCEfPk_MsvybnWBmC5lT6CtXSoZ7EQoFzrcBEzo4zF9s8CbhXyo0e-eSY3pZ1zg0BRvT0YssMMhbzEG-gP_jiO8v9q9HYTjg-QW5jJ0RDA

Si no configuró una pantalla de consentimiento, verá una advertencia en la consola y deberá hacerlo en este momento. (Omita estos pasos siguientes si su pantalla de consentimiento ya se configuró).

Haga clic en "Configurar pantalla de consentimiento" en la que seleccione una aplicación "Externa" (o "Interno" si es cliente de G Suite):

5w-9R6gPvUHFzODZxXy-0GEhL8ZGDGNea3QtMp1FFYDv5DJ_MIDD21NEh3CzI-GKNzy6bkhH7bohxOG8icQTegiWlavOQhQqhSy7K31Ma3YTI9aAP3P-LmTBanPslX1cnjKLVZBi8A

Ten en cuenta que, para los fines de este ejercicio, no importa cuál elijas porque no publicas tu muestra de codelab. La mayoría de las personas seleccionarán "Externo" para que se dirijan a una pantalla más compleja, pero solo necesitas completar el campo "Nombre de la aplicación" en la parte superior:

8e9z_RQz8lumYbDIcBvm57_Gpptn9uhrVQHoRzJ01AJNOFmXloDO7Eg3hhzJZZIU2F5rR0MxTCw-oXVFCq683xUwD4O33pXeuFsOMtM8EZhyjDoYc8Kv4hEoaG0Ztq9ePx6De7YmfA

En este momento, lo único que necesitas es solo el nombre de una aplicación. Por lo tanto, elige a alguien que refleje el codelab que estás haciendo y haz clic en Guardar.

Creación de ID de cliente de OAuth (autenticación de cuenta de usuario)

Ahora, regrese a la pestaña Credenciales para crear un ID de cliente de OAuth2. Aquí encontrarás una variedad de ID de cliente de OAuth que puedes crear:

f8reuhsxOUNLcVrEIyRVsmP_fX_ceIlLvEKql1YHwSPW9jk9Mm9fJ0UlfUoi8eRN3QQXar4xtpo071zj6LSczNN7TYY8zB96Dn6ICZuvCAtjIgJSKdMSlX-ZhMuSWFpxxv661aUemw

Estamos desarrollando una herramienta de línea de comandos, que es Other, por lo que debes elegirla y hacer clic en el botón Create. Elige un nombre de ID de cliente que refleje la app que estás creando o simplemente toma el nombre predeterminado, que suele ser "Otro cliente N".

Guarda tus credenciales

  1. Aparecerá un diálogo con las credenciales nuevas. Haz clic en Aceptar para cerrar.

rAwekj_GNEuVwGbZOYYlGDQjlu4flE61OPEZIUmwMI5vGi3W365UwVCxi0mVNhg4WZSSczZywrZZ6NDM_U0FJ4b-TOIMEC189uybOJjgn8F_axesVMopel9RlehRBXdEFhN4d41WGQ

  1. Regrese a la página Credenciales, desplácese hasta la sección "ID de cliente de OAuth2" y haga clic en el ícono de descarga aAmje6kT_xSUM4BKIlPREpjosx7C_xxwpWqBgiGVfVWxQ8nnQOfxTPhuU0QwSnmbjykZffGrqyP1nnKrEQ7D7OqYaGw_Uzscs9gX2RwwP4AmvtHIiTFLa0gkprzJSjG9pQSx7HtmSQ en el extremo inferior derecho de su ID de cliente recientemente creado. x-vb-sKZy-X8a1X4uTsBWotSd4wn0PGt4mHMNv6DUrq5J5ihpujUyTiIVr5SHw0p2ZDy0KTP-zqOaFX-Az9BYDWG90KNFmsRLTUOo1mUVk7dYRJiK3VwYJNU0bbxjsbbpqcTr5_oLw
  2. Se abrirá un cuadro de diálogo para guardar un archivo llamado client_secret-LONG-HASH-STRING.apps.googleusercontent.com.json, probable en tu carpeta Descargas. Te recomendamos acortar a un nombre más fácil, como client_secret.json (que es lo que usa la aplicación de muestra), y luego lo guardes en el directorio o carpeta donde crearás la app de muestra en este codelab.

Resumen

Ya está listo para habilitar las API de Google empleadas en este codelab. Además, para el nombre de la aplicación en la pantalla de consentimiento de OAuth, seleccionamos "Demostración de la API de Vision", por lo que esperamos ver esto en las siguientes capturas de pantalla.

Introducción

En este codelab, se usan cuatro (4) API de Google Cloud, un par de GCP (Cloud Storage y Cloud Vision) y otro par de G Suite (Google Drive y Hojas de cálculo de Google). A continuación, encontrará instrucciones para habilitar solo la API de Vision. Una vez que sepas cómo habilitar una API, debes habilitar las otras 3 por tu cuenta.

Antes de comenzar a usar las API de Google, debes habilitarlas. En el siguiente ejemplo, se muestra lo que haría para habilitar la API de Cloud Vision. En este codelab, puedes usar una o más API y seguir los pasos similares para habilitarlas antes de su uso.

Desde Cloud Shell

Con Cloud Shell, puedes habilitar la API con el siguiente comando:

gcloud services enable vision.googleapis.com

Desde Cloud Console

También puedes habilitar la API de Vision en el Administrador de API. En Cloud Console, vaya al Administrador de API y seleccione “Biblioteca”.

mg03by3QV6kco0rVVV_8IA6VobAoMG4Yoyl-PofNM0dHK8IcoDmpoLUwWeiKFFjpxHWlS1td5-0n7kNkfqHVhSsTSW_hUMvRu3D72g3LCFb7u4v4bla_Z4XyonTVK8PpigMLJcE01g

En la barra de búsqueda, comience a escribir "vision" y, luego, seleccione la API de Vision cuando aparezca. Puede verse de la siguiente manera cuando escribas:

B6fWWsVhymufgQx6oGIq4sgukK6JQ1VoguVOrSNf_anQb6Cv6RTLtsjx5Qdeu3-uO8-8PyqwZLYdDDjYW5o56R47cnsd_88RKTMqNkpFeDESW2hmBM_7FK2UAMz1_216yXERYSp_JA

Seleccione la API de Cloud Vision para obtener el diálogo que se muestra a continuación y, luego, haga clic en el botón "Enable":

D-MONPLi0UWH6Dp607Dod6JF-LJQZIiUQEPQNKM4Y0mSt09KfipbeeXRAE6cokArBYTfL9VQoONc4L0jlnsUYLsNytQIPfSKr9lCDrXmrrx-1w64LeWWa-byDxcyYWZdCI0mAcVzBw

Costo

Aunque muchas API de Google se pueden usar sin tarifas, el uso de GCP (productos y API) no es gratuito. Cuando habilites la API de Vision (como se describe arriba), es posible que se te solicite una cuenta de facturación activa. El usuario debe hacer referencia a la información de precios de la API de Vision antes de habilitarla. Ten en cuenta que ciertos productos de Google Cloud Platform (GCP) tienen un nivel"Siempre gratuito" para el que debes exceder los límites de la facturación. Para los fines del codelab, cada llamada a la API de Vision se descuenta de ese nivel gratuito y, siempre que permanezcas dentro de los límites agregados (dentro de cada mes), no se te cobrará ningún cargo.

Algunas API de Google, p.ej., G Suite tiene un uso cubierto por la suscripción mensual, por lo que no hay facturación directa para el uso de las API de Gmail, Google Drive, Calendario, Documentos, Hojas de cálculo y Presentaciones. Los distintos productos de Google se facturan de manera diferente. Por lo tanto, asegúrate de consultar la documentación de tu API para obtener más información.

Resumen

Ahora que Cloud Vision se habilitó, active las otras tres API (Google Drive, Cloud Storage y Hojas de cálculo de Google) de la misma manera... desde Cloud Shell, use gcloud services enable o desde Cloud Console:

  1. Volver a la biblioteca de la API
  2. Para comenzar una búsqueda, escribe algunas letras de su nombre
  3. Selecciona la API deseada.
  4. Habilitar

Derriva, ríe y repite. Para Cloud Storage, hay varias opciones... elige la “API de JSON de Google Cloud Storage”. La API de Cloud Storage también espera una cuenta de facturación activa.

Este es el comienzo de un fragmento de código mediano, por lo que queremos poner en práctica algunas prácticas ágiles y garantizar una infraestructura común, estable y funcional antes de abordar la aplicación principal. Verifique que client_secret.json esté disponible en su directorio actual y inicie ipython y, luego, ingrese el siguiente fragmento de código, o guárdalo en analyze_gsimg.py y ejecútelo desde el shell (es preferible este último porque seguiremos recibiendo agregar a la muestra de código):

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)

Este componente central incluye bloques de código para importaciones de módulos o paquetes, procesar credenciales de autenticación de usuarios y crear extremos de servicio de API. Las partes clave del código que debes revisar:

  • Importar la función print() hace que este ejemplo de Python sea compatible con Python 2 y 3 unidades, y las importaciones de biblioteca de Google ofrecen todas las herramientas necesarias para comunicarse con las API de Google.
  • La variable SCOPES representa los permisos para solicitar al usuario, por lo que solo hay uno por ahora: el permiso para leer datos de su Google Drive
  • El resto de las credenciales de procesamiento de credenciales leen en tokens OAuth2 almacenados en caché, posiblemente se actualizan a un nuevo token de acceso con el token de actualización si el token de acceso original caducó.
  • Si no se creó ningún token o no se recuperó un token de acceso válido por otro motivo, el usuario debe realizar el flujo de OAuth 2 para 3 (3LO): crear el diálogo con los permisos solicitados y solicitarle al usuario que acepte la solicitud. Una vez que lo hacen, la app continúa, de lo contrario, tools.run_flow() muestra una excepción y se detiene la ejecución.
  • Una vez que el usuario otorga permiso, se crea un cliente HTTP para comunicarse con el servidor y todas las solicitudes se firman con las credenciales del usuario para mayor seguridad. Luego, se crea un extremo de servicio para la API de Google Drive (versión 3) y, a continuación, se asigna a DRIVE.

Ejecuta la aplicación

La primera vez que ejecute la secuencia de comandos, esta no tendrá autorización para acceder a los archivos del usuario en Drive (la suya). El resultado se ve así con la ejecución en pausa:

$ 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

Si ejecuta la ejecución de Cloud Shell, vaya a la sección "Desde Cloud Shell" y desplácese hacia abajo para revisar las pantallas relevantes en "Desde el entorno de desarrollo local" cuando corresponda.

Desde el entorno de desarrollo local

La secuencia de comandos de la línea de comandos se pausa cuando se abre la ventana del navegador. Es posible que veas una página de advertencia de aspecto espeluznante:

250b74709b3737dc.png

Esta es una preocupación legítima, ya que estás tratando de ejecutar una app que accede a datos del usuario. Dado que esta es solo una app de demostración y eres el desarrollador, esperamos que confieras lo suficiente para continuar. Para comprender mejor esta situación, ponte en el lugar de tus usuarios: se te pedirá que permitas que el código de otra persona acceda a tus datos. Si deseas publicar una app como esta, deberás realizar el proceso de verificación para que tus usuarios no vean esta pantalla.

Después de hacer clic en el vínculo "Ir a la aplicación "no seguro"", verás un cuadro de diálogo de permisos de OAuth2, que tiene un aspecto similar al siguiente. Siempre mejoramos la interfaz de usuario, así que no te preocupes si no es una coincidencia exacta:

e3e6ef5503b2af1b.png

El diálogo de flujo de OAuth2 refleja los permisos que solicita el desarrollador (a través de la variable SCOPES). En este caso, se puede ver y descargar desde la unidad de Google Drive del usuario. En el código de la aplicación, estos permisos de permisos aparecen como URI, pero se traducen al idioma especificado por la configuración regional del usuario. Aquí, el usuario debe otorgar autorización explícita para los permisos solicitados. De lo contrario, se producirá una excepción para que la secuencia de comandos no continúe.

Incluso puedes recibir un diálogo más que solicite tu confirmación:

b91997983fdc1889.png

NOTA: Algunos navegadores web abiertos a diferentes cuentas, por lo que esta solicitud de autorización puede ir a la pestaña o ventana del navegador incorrecta, y es posible que deba cortar y pegar el vínculo para esta solicitud en un navegador con la que se accedió con la cuenta correcta.

Desde Cloud Shell

Desde Cloud Shell, no aparecerá una ventana del navegador, lo que quedará bloqueado. Imagina que el mensaje de diagnóstico que se encuentra en la parte inferior corresponde a ti... este:

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

  --noauth_local_webserver

Deberá detener ^C (Ctrl+C o presionar otra tecla) para detener la ejecución de la secuencia de comandos, y ejecutarla desde su shell con el indicador adicional. Cuando lo ejecutes de esta manera, obtendrás el siguiente resultado:

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

(Ignora la advertencia porque sabemos que storage.json todavía no se creó y) si sigues las instrucciones de otra pestaña del navegador con esa URL, obtendrás una experiencia casi idéntica a la que se describió anteriormente para los entornos de desarrollo local (consulta los análisis). arriba). Al final hay una pantalla final con el código de verificación para ingresar en Cloud Shell:

f6da2c335fb7c6a.png

Copie este código y péguelo en la ventana de la terminal.

Resumen

Excepto por "Authentication successful", no se espera ningún resultado adicional. Recuerda que esta es solo la configuración... aún no has realizado ninguna acción. Lo que ha hecho comenzó con éxito su recorrido hacia algo más probable que se ejecute correctamente la primera vez. (La mejor parte es que solo se te solicitó autorización una vez; todas las ejecuciones sucesivos las omiten porque se almacenan en caché tus permisos). Ahora vamos a hacer que el código haga un trabajo real, dando como resultado resultados reales.

Solución de problemas

Si se produce un error en lugar de no generar resultados, puede deberse a una o más de las causas, tal vez esta:

En el paso anterior, recomendamos crear el código como analyze_gsimg.py y editarlo desde allí. También es posible simplemente cortar y pegar todo directamente en shell de Python I o Python estándar. Sin embargo, es más complicado, ya que continuaremos desarrollando la pieza de aplicaciones por pieza.

Supongamos que tu app se autorizó y se creó el extremo del servicio de API. En tu código, se representa con la variable DRIVE. Ahora buscaremos un archivo de imagen en Google Drive y

configúralo como una variable llamada NAME. Ingresa esa función drive_get_img() más abajo justo debajo del código del paso 0.

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

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

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

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

La colección files() de Drive tiene un método list() que realiza una consulta (el parámetro q) para el archivo especificado. El parámetro fields se usa para especificar qué valores de retorno te interesan. ¿Por qué vale la pena retroceder y reducir la velocidad si no te interesan los otros valores? Si eres nuevo en las máscaras de campo para filtrar los valores de retorno de la API, consulta esta entrada de blog y video. De lo contrario, ejecuta la consulta y toma el atributo files que se muestra, si no hay coincidencias, se adopta un arreglo de lista vacío.

Si no hay resultados, se omite el resto de la función y se muestra None (de forma implícita). De lo contrario, toma la primera respuesta que coincide (rsp[0]), muestra el nombre de archivo, su tipo de MIME, la última marca de tiempo de modificación y, por último, su carga útil binaria, que recupera la función get_media() (a través de su ID de archivo), también en el colección files(). (Los nombres de los métodos pueden variar un poco con otras bibliotecas cliente de lenguaje).

La última parte es el cuerpo "principal" que impulsa toda la aplicación:

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)

Si suponemos que una imagen llamada section-work-card-img_2x.jpg en Drive está configurada como FILE, cuando la ejecución de la secuencia de comandos sea exitosa, deberías ver un resultado que confirme que pudo leer el archivo de Drive (pero no se guardó en tu computadora):

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

Solución de problemas

Si no obtienes un resultado exitoso como el anterior, es posible que se deba a una o varias causas, tal vez a la siguiente:

Resumen

En esta sección, aprendió cómo (en 2 llamadas independientes a la API) para conectarse a la consulta de la API de Drive correspondiente a un archivo específico y descargarlo. Caso práctico empresarial: Archive sus datos de Drive y, luego, analizarlos, como con las herramientas de GCP. El código de tu app en esta etapa debe coincidir con el contenido del repositorio en step1-drive/analyze_gsimg.py.

Para obtener más información sobre cómo descargar archivos en Google Drive, haga clic aquí o consulte esta entrada de blog y video. Esta parte del codelab es casi idéntica al codelab de G Suite APIs, ya que, en lugar de descargar un archivo, muestra los primeros 100 archivos y carpetas en la unidad de Google Drive de un usuario y usa un alcance más restrictivo.

El siguiente paso es agregar compatibilidad con Google Cloud Storage. Para esto, necesitamos importar otro paquete de Python, io. Asegúrese de que la sección superior de sus importaciones se vea de la siguiente manera:

from __future__ import print_function
import io

Además del nombre de archivo de Drive, necesitamos información sobre dónde almacenar este archivo en Cloud Storage, específicamente el nombre del "depósito" en el que se colocará el archivo y los prefijos de "carpetas principales". más adelante en un momento:

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

Una palabra en depósitos... Cloud Storage proporciona un almacenamiento de BLOB moroso. Cuando subes archivos, no se entiende el concepto de tipos de archivo, extensiones, etc., como lo hace Google Drive. Simplemente son "BLOB" en Cloud Storage. Además, no hay concepto de carpetas o subdirectorios en Cloud Storage.

Sí, puedes tener barras (/) en los nombres de archivo para representar la abstracción de varias subcarpetas, pero al final del día, todos tus BLOB se ubican en un depósito y "/" se acaban de caracteres en sus nombres. A fin de obtener más información, consulta la página de convenciones de nombres de depósitos y objetos.

El paso 1 anterior solicitó el alcance de solo lectura de Drive. En ese momento, eso es todo lo que necesitas. Ahora es obligatorio el permiso de carga (lectura y escritura) para Cloud Storage. Cambia SCOPES de una variable de string única a un arreglo (tupla de Python [o lista]) de alcances de permisos para que se vea de la siguiente manera:

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

Ahora, cree un extremo de servicio en Cloud Storage justo debajo del que se busca en Drive. Ten en cuenta que modificamos ligeramente la llamada para reutilizar el mismo objeto de cliente HTTP, ya que no es necesario crear uno nuevo cuando puede ser un recurso compartido.

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

Ahora, agregue esta función (después de drive_get_img()) que se sube a Cloud Storage:

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

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

La llamada objects.().insert() requiere el nombre del depósito, los metadatos del archivo y el BLOB binario en sí. Para filtrar los valores que se muestran, la variable fields solicita solo los nombres de depósito y objeto que muestra la API. Para obtener más información sobre estas máscaras de campo en las solicitudes de lectura de API, consulta esta publicación y este video.

Ahora integra el uso de gcs_blob_upload() en la aplicación principal:

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

La variable gcsname combina los nombres de los "subdirectorios principales" con el nombre del archivo en sí mismo y, cuando se agrega el prefijo con el nombre del depósito, se quita la impresión que archivas el archivo en "/bucket/parent.../filename". Quita este fragmento justo después de la primera función print() justo encima de la cláusula else para que toda la "principal" se vea de la siguiente manera:

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)

Supongamos que especificábamos un depósito llamado "vision-demo" con "analyzed_imgs" como "subdirectorio superior". Una vez que configure esas variables y vuelva a ejecutar la secuencia de comandos, section-work-card-img_2x.jpg se descargará desde Drive y, luego, se subirá a Cloud Storage. NOT

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

Mire detenidamente, mientras falla la descarga de Drive, la carga a Cloud Storage falló. ¿Por qué?

Esto se debe a que, cuando originalmente autorizamos esta aplicación para el Paso 1, solo autorizamos el acceso de solo lectura a Google Drive. Aunque agregamos el alcance de lectura y escritura para Cloud Storage, nunca le hemos pedido al usuario que autorice ese acceso. Para que funcione, debemos quitar el archivo storage.json, que no tiene este alcance y volver a ejecutarlo.

Después de volver a autorizar (confirmo dentro de storage.json y ver ambos alcances), el resultado será el siguiente:

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

Resumen

Esto es un gran inconveniente, ya que muestra relativamente pocas líneas de código cómo transferir archivos entre ambos sistemas de almacenamiento de Cloud. El caso práctico del negocio aquí es hacer una copia de seguridad de un recurso limitado que puede llegar a un almacenamiento "más antiguo", más barato, como se mencionó anteriormente. Cloud Storage ofrece diferentes clases de almacenamiento en función de si accedes a tus datos de forma periódica, mensual, trimestral o anual.

Por supuesto, los desarrolladores nos preguntan ocasionalmente el motivo por el cual Google Drive y Cloud Storage existen... después de todo, ¿no son ambos almacenamiento de archivos en la nube? Es por eso que hicimos este video. Tu código en esta etapa debe coincidir con el contenido del repositorio en step2-gcs/analyze_gsimg.py.

Si bien ya sabemos que es posible transferir datos entre GCP y G Suite, aún no hemos realizado ningún análisis, por lo que debe enviar la imagen a Cloud Vision para la detección de etiquetas, también conocida como detección de objetos. Para hacerlo, necesitamos codificar los datos en Base64; es decir, otro módulo de Python, base64. Asegúrese de que la sección de importación principal se vea así:

from __future__ import print_function
import base64
import io

De manera predeterminada, la API de Vision muestra todas las etiquetas que encuentra. Para mantener la coherencia, solicitemos solo los 5 primeros (que puede ajustar el usuario). Para ello, usaremos una variable constante TOP. agrégala debajo de las otras constantes:

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

Al igual que con los pasos anteriores, necesitamos otro alcance de permisos, pero esta vez para la API de Vision. Actualiza SCOPES con la string its:

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

Ahora, cree un extremo de servicio en Cloud Vision para que coincida con otros como estos:

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

Ahora, agregue esta función que envía la carga útil de la imagen a Cloud Vision:

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

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

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

La llamada a images().annotate() requiere los datos más las funciones de la API deseadas. El límite superior de 5 etiquetas es también parte de la carga útil (pero completamente opcional). Si la llamada es exitosa, la carga útil muestra las 5 etiquetas principales de objetos más una puntuación de confianza que un objeto está en la imagen. (Si no se muestra una respuesta, asigna un diccionario de Python vacío para que la siguiente declaración if no falle). Esta función simplemente agrupa los datos en una string CSV para usarlos en un informe.

Estas 5 líneas que llaman a vision_label_img() deben colocarse justo después de la carga correcta a Cloud Storage:

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

Con esa adición, todo el controlador principal debería verse así:

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)

Si borras storage.json para actualizar los alcances y volver a ejecutar la aplicación actualizada, se debería obtener un resultado similar al siguiente, lo que indica la adición de análisis de 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

Resumen

No todos tienen la experiencia de aprendizaje automático a fin de crear y entrenar sus propios modelos de AA para analizar sus datos. El equipo de Google Cloud puso a disposición algunos de los modelos previamente entrenados de Google para uso general y los puso en API, lo que ayuda a democratizar la IA y el AA para todos.

Si eres desarrollador y puedes llamar a una API, puedes usar el aprendizaje automático. Cloud Vision es solo uno de los servicios de API que puede usar para analizar sus datos. Obtén más información sobre los otros aquí. Tu código ahora debería coincidir con el contenido del repositorio en step3-vision/analyze_gsimg.py.

En este momento, pudo archivar datos corporativos y analizarlos, pero lo que carece de un resumen de este trabajo. Organicemos todos los resultados en un único informe que pueda entregarle a su jefe. ¿Qué aspectos no se pueden administrar en una hoja de cálculo?

No se necesitan importaciones adicionales para la API de Hojas de cálculo de Google, y la única información nueva que se necesita es el ID de archivo de una hoja de cálculo existente que ya tiene formato y esperando una nueva fila de datos, por lo que la constante SHEET. Le recomendamos que cree una hoja de cálculo nueva que sea similar a la que se muestra a continuación:

ca435d8aafd72ff4.png

La URL de esa hoja de cálculo se verá de la siguiente manera: https://docs.google.com/spreadsheets/d/FILE_ID/edit. Toma ese FILE_ID y asígnalo como una cita a SHEET.

También usamos una pequeña función llamada k_ize(), que convierte bytes en kilobytes, que la define como lambda de Python, ya que es una línea simple de 1 línea. Ambos están integrados con las otras constantes que se ven de la siguiente manera:

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

Al igual que con los pasos anteriores, necesitamos otro alcance de permisos: esta vez la lectura y escritura para la API de Hojas de cálculo. SCOPES ya tiene los 4 que necesitas:

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

Ahora, cree un extremo de servicio en Hojas de cálculo de Google cerca de los otros para que se vea de la siguiente manera:

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

La funcionalidad de sheet_append_row() es sencilla: tome una fila de datos y el ID de una hoja de cálculo y, luego, agregue esa fila a esa hoja:

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

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

La llamada a spreadsheets().values().append() requiere el ID de archivo de Hojas de cálculo, el rango de celdas, los datos que deben ingresarse y los datos en sí. El ID del archivo es sencillo. El rango de celdas se proporciona en notación A1. Un rango de "Sheet1" significa toda la hoja (esto indica a la API que agregue la fila después de todos los datos de la hoja de cálculo). Hay un par de opciones sobre cómo se deben agregar los datos a la hoja, "RAW" (ingresa la string de datos de manera literal) o "USER_ENTERED" (escribe los datos como si un usuario lo ingresó en su teclado con la aplicación de Hojas de cálculo de Google y que mantiene las funciones de formato de celdas).

Si la llamada se realiza correctamente, el valor de retorno no tiene nada realmente útil, por lo que decidimos obtener la cantidad de celdas actualizadas mediante la solicitud de la API. A continuación, se muestra el código que llama a esa función:

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

La hoja de cálculo de Google tiene columnas que representan datos como cualquier "subdirectorio" superior, la ubicación del archivo archivado en Cloud Storage (depósito + nombre de archivo), el tipo de MIME del archivo, el tamaño del archivo (originalmente en bytes, pero convertido a kilobytes conk_ize() ) y la string de etiquetas de Cloud Vision. Además, ten en cuenta que la ubicación archivada es un hipervínculo para que tu administrador pueda hacer clic para confirmar que se creó una copia de seguridad de forma segura.

Agregar el bloque de código anterior justo después de mostrar los resultados de Cloud Vision, la parte principal que impulsa la app ahora está completa, aunque estructuramente un poco complejo:

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)

Si borras storage.json por última vez y vuelves a ejecutar la aplicación actualizada, el resultado debería ser similar al siguiente, lo que indica la adición de análisis de Cloud Vision:

$ python3 analyze_gsimg.py

    . . .

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

La línea adicional de resultado, aunque es útil, se ve mejor si se mira en una Hoja de cálculo de Google con la última línea (fila 7 del siguiente ejemplo) agregada al conjunto de datos existente que se agregó antes:

a7f821fa497e6bbe.png

Resumen

En los primeros 3 pasos de este instructivo, te conectaste con las API de G Suite y GCP para mover datos y analizarlos, lo que representa el 80% de todo el trabajo. Sin embargo, al final del día, nada de esto significa que si no puedes realizar la gestión de todo lo que logras. A fin de visualizar mejor los resultados, resumirá todos los resultados en un informe generado que hable los volúmenes.

Para mejorar aún más la utilidad del análisis, además de escribir los resultados en una hoja de cálculo, una posible mejora sería indexar las 5 etiquetas principales para cada imagen, de modo que se pueda crear una base de datos interna, de modo que los empleados autorizados puedan realizar consultas de imágenes mediante la búsqueda. pero dejamos eso así como un ejercicio para los lectores.

Por el momento, nuestros resultados están en una hoja de cálculo, y la administración es accesible. El código de tu app en esta etapa debe coincidir con el contenido del repositorio en step4-sheets/analyze_gsimg.py. El último paso es limpiar el código y convertirlo en un script útil.

(Opcional) La aplicación funciona de manera óptima. ¿Podemos mejorarlo? Sí, en especial la aplicación principal que parece un desastre. Vamos a colocarlo en su propia función y determinarla para la entrada del usuario en lugar de constantes fijas. Haremos eso con el módulo argparse. Además, iniciemos una pestaña del navegador web para mostrar la hoja de cálculo una vez que haya escrito la fila de datos en ella. Esto se puede hacer con el módulo webbrowser. Comprobamos estas importaciones con las otras para que las principales importaciones se vean así:

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

Para poder usar este código en otras aplicaciones, necesitamos la capacidad de suprimir la salida, por lo que agregaremos una marca DEBUG para que eso suceda. Agreguemos esta línea al final de la sección de constantes cerca de la parte superior:

DEBUG = False

Ahora, acerca del cuerpo principal. Durante la compilación de esta muestra, deberías haber comenzado a sentir “incómodo” cuando nuestro código agregue otro nivel de anidamiento con cada servicio agregado. Si no lo hizo así, no está solo, ya que esto agrega complejidad a el código, como se describe en esta entrada de blog de prueba de Google.

Siguiendo esta práctica recomendada, reorganizamos la parte principal de la app en una función y return en cada "punto de interrupción" en lugar de anidar (mostrar None si cualquiera de los pasos falla y True si todo funciona correctamente):

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

Es más fluido y limpio, y no se deja atrás la cadena de if-else recurrente, junto con la reducción de la complejidad del código, como se describió anteriormente. Lo último del rompecabezas es crear un controlador principal "real" para la personalización del usuario y minimizar los resultados (a menos que lo desees):

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)

Si todos los pasos tienen éxito, la secuencia de comandos inicia un navegador web en la hoja de cálculo especificada en la que se agregó la nueva fila de datos.

Resumen

No es necesario borrar storage.json, ya que no se produjeron cambios de alcance. Volver a ejecutar la aplicación actualizada muestra una nueva ventana del navegador abierta a la Hoja de cálculo modificada, menos líneas de resultados y emitir una opción -h muestra a los usuarios sus opciones, incluido -v para restablecer las líneas de salida ahora presionadas. antes:

$ 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

Las otras opciones permiten que los usuarios elijan diferentes nombres de archivos de Drive, el "subdirectorio" de Cloud Storage y los nombres de depósitos, los "N" resultados principales de Cloud Vision y los ID de los archivos de Hojas de cálculo de la hoja de cálculo. Con estas últimas actualizaciones, la versión final de tu código ahora debería coincidir con lo que está en el repositorio en final/analyze_gsimg.py y en su totalidad:

## Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

'''
analyze_gsimg.py - analyze G Suite 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)

Haremos todo lo posible para mantener el contenido de este instructivo actualizado, pero, en algunas ocasiones, el repositorio tendrá la versión más reciente del código.

Definitivamente, hay mucho aprendizaje en este codelab y, por eso, logró sobrevivir a uno de los codelabs más extensos. Como resultado, resolvió un posible escenario empresarial con aproximadamente 130 líneas de Python, aprovechando todo Google Cloud (GCP y G Suite) y mover datos entre entonces para compilar una solución de trabajo. No dude en explorar el repositorio de código abierto para todas las versiones de esta aplicación (obtenga más información a continuación).

Limpia

  1. El uso de las API de GCP no es gratuito, mientras que las API de G Suite están cubiertas por la tarifa mensual de suscripción de G Suite o la tarifa mensual de cero como usuario de Gmail, por lo que no hay una API. se requiere limpieza o desactivación para los usuarios de G Suite. Para GCP, puedes ir al panel de Cloud Console y consultar la tarjeta de facturación para conocer los cargos estimados.
  2. En Cloud Vision, se permite un número fijo de llamadas a la API por mes de forma gratuita. Siempre y cuando permanezcas dentro de esos límites, no es necesario que cierres nada ni que debas inhabilitar o borrar tu proyecto. Puedes encontrar más información sobre la facturación y la cuota gratuita de la API de Vision en su página de precios.
  3. Algunos usuarios de Cloud Storage reciben una cantidad de almacenamiento gratuita por mes. Si las imágenes que archivas con este laboratorio de código no harán que excedas esa cuota, no tendrás que pagar ningún cargo. Puedes encontrar más información sobre la facturación de GCS y la cuota gratuita en la página de precios. Puedes ver y borrar fácilmente BLOB del navegador de Cloud Storage.
  4. Es posible que el uso de Google Drive también tenga una cuota de almacenamiento y, si lo superas (o estás cerca de él), te recomendamos que uses la herramienta que creaste en este codelab para archivar esas imágenes en el almacenamiento en la nube y así tener más espacio en Drive. Puede encontrar más información sobre el almacenamiento en Google Drive en la página de precios correspondiente para los usuarios de G Suite Basic o usuarios de Gmail/consumidor.

Aunque la mayoría de los planes de G Suite Business y Enterprise tienen almacenamiento ilimitado, es posible que las carpetas de Drive estén desordenadas o abrumadoras. La app que compilaste en este instructivo es una excelente manera de archivar archivos externos y limpiar tu Google Drive.

Versiones alternativas

Si bien final/analyze_gsimg.py es la última versión oficial en la que trabajas en este instructivo, no es el fin de la historia. Un problema con la versión final de la app es que usa las bibliotecas de autenticación anteriores que ya no están disponibles. Elegimos esta ruta de acceso porque, en el momento de este documento, las bibliotecas de autenticación más nuevas no admitían varios elementos clave: administración de almacenamiento de tokens de OAuth y seguridad de subprocesos.

Bibliotecas de autenticación actuales (más recientes)

Sin embargo, en algún momento, ya no se admitirán las bibliotecas de autenticación anteriores, por lo que te recomendamos que revises las versiones que usen las bibliotecas de autenticación más recientes (actuales) en la carpeta alt del repositorio, incluso si no son seguras para subprocesos (pero puedes compilar tu propia solución). Busca archivos que contengan *newauth* en sus nombres.

Bibliotecas cliente de productos de GCP

Google Cloud recomienda a todos los desarrolladores usar las bibliotecas cliente de productos cuando usan las API de GCP. Lamentablemente, las API que no pertenecen a GCP no tienen esas bibliotecas en este momento. El uso de bibliotecas de plataformas de nivel inferior permite un uso uniforme de las API y ofrece una mejor legibilidad. Al igual que la recomendación anterior, las versiones alternativas que usan bibliotecas cliente de productos de GCP están disponibles en la carpeta alt del repositorio para que las revises. Busca archivos que contengan *-gcp* en sus nombres.

Autorización de cuenta de servicio

Cuando se trabaja únicamente en la nube, en general, no hay datos de humanos ni personas (personal), por lo que las cuentas de servicio y la autorización de las cuentas de servicio se usan principalmente con GCP. Sin embargo, en general, los usuarios de G Suite son propiedad de los usuarios (humanos), por lo que en este instructivo se usa la autorización de cuentas de usuario. Esto no significa que no puede usar las API de G Suite con cuentas de servicio. Siempre que esas cuentas tengan el nivel de acceso adecuado, pueden utilizarse en las aplicaciones. Como en el caso anterior, las versiones alternativas que usan la autorización de la cuenta de servicio están disponibles en la carpeta alt del repositorio para que las revises. Busca archivos que contengan *-svc* en sus nombres.

Catálogo de versiones alternativas

A continuación, encontrarás todas las versiones alternativas de final/analyze_gsimg.py, cada una de las cuales tiene una o más de las propiedades anteriores. En el nombre de archivo de cada versión, busca...

  • "oldauth" para las versiones que usan las bibliotecas de autenticación anteriores (además de final/analyze_gsimg.py)
  • "newauth" para aquellos que usen las bibliotecas de autenticación actuales o más recientes
  • gcp” para quienes usan las bibliotecas cliente de productos de GCP, como google-cloud-storage, etcétera.
  • "svc" para los usuarios que usen una autenticación de cuenta de servicio ("cuenta c cuenta") en lugar de una cuenta de usuario

Estas son todas las versiones:

Nombre del archivo

Descripción

final/analyze_gsimg.py

La muestra principal. usa las bibliotecas de autenticación anteriores

alt/analyze_gsimg-newauth.py

Igual que final/analyze_gsimg.py, pero usa las bibliotecas de autenticación más recientes.

alt/analyze_gsimg-oldauth-gcp.py

Igual que final/analyze_gsimg.py, pero usa las bibliotecas cliente de GCP.

alt/analyze_gsimg-newauth-gcp.py

Igual que alt/analyze_gsimg-newauth.py, pero usa las bibliotecas cliente de GCP.

alt/analyze_gsimg-oldauth-svc.py

Igual que final/analyze_gsimg.py, pero usa subcuenta en lugar de cuenta de usuario

alt/analyze_gsimg-newauth-svc.py

Igual que alt/analyze_gsimg-newauth.py, pero usa la autenticación de cuenta regresiva por país en lugar de la cuenta de usuario.

alt/analyze_gsimg-oldauth-svc-gcp.py

Igual que alt/analyze_gsimg-oldauth-svc.py, pero usa las bibliotecas cliente de productos de GCP y iguales que alt/analyze_gsimg-oldauth-gcp.py, pero usa la autenticación de cuenta de vac en lugar de la cuenta del usuario.

alt/analyze_gsimg-newauth-svc-gcp.py

Igual que alt/analyze_gsimg-oldauth-svc-gcp.py, pero usa las bibliotecas de autenticación más recientes.

Junto con el final/analyze_gsimg.py original , tiene todas las combinaciones posibles de la solución final, independientemente del entorno de desarrollo de la API de Google, y puede elegir la que mejor se adapte a sus necesidades. Consulta también alt/README.md para obtener una explicación similar.

Estudio adicional

A continuación, se presentan algunas ideas sobre cómo puede seguir un ejercicio uno o dos pasos más. Se puede expandir el conjunto de problemas que puede solucionar la solución actual, lo que te permite realizar las siguientes mejoras:

  1. (Varias imágenes en carpetas) En lugar de procesar una imagen, supongamos que tenía imágenes en las carpetas de Google Drive.
  2. (Varias imágenes en archivos ZIP) En lugar de una carpeta de imágenes, ¿qué ocurre con los archivos ZIP que contienen archivos de imagen? Si usas Python, considera el módulo zipfile.
  3. (Analizar etiquetas de Vision) agrupa imágenes similares, por ejemplo, comienza por buscar las etiquetas más comunes, la segunda más común, etcétera.
  4. (crear gráficos) Seguimiento 3, generar gráficos con la API de Hojas de cálculo según el análisis y la categorización de la API de Vision
  5. (categorizar documentos) En lugar de analizar imágenes con la API de Cloud Vision, supongamos que tiene archivos PDF para categorizar con la API de Cloud Natural Language. Si usas tus soluciones anteriores, los PDF pueden estar en carpetas de Drive o archivos ZIP de Drive.
  6. (crear presentaciones) Use la API de Presentaciones para generar una presentación de diapositivas con el contenido del informe de Hojas de cálculo de Google. Si deseas obtener inspiración, consulta esta entrada de blog y video sobre cómo generar diapositivas a partir de datos de hojas de cálculo.
  7. (exportar como PDF) Exporte la hoja de cálculo o la presentación de diapositivas como PDF, pero esto no es una función de las API de Hojas de cálculo ni Presentaciones. Sugerencia: API de Google Drive. Crédito adicional: Combine los PDF de Hojas de cálculo y Presentaciones en un solo PDF principal con herramientas como Ghostscript (Linux, Windows) o Combine PDF Pages.action (Mac OS X).

Más información

Codelabs

General

G Suite

Google Cloud Platform (GCP)

Licencia

Este trabajo cuenta con una licencia Atribución 2.0 Genérica de Creative Commons.