Olhe para o céu! Aprenda sobre visualização de dados com o WhatsApp, Google Maps, Python, Twilio e Clarifai

July 15, 2020
Escrito por
Diane Phan
Twilion
Revisado por
Sam Agnew
Twilion

Olhe para o céu! Aprenda sobre visualização de dados

Você se lembra do Second Sky de 2019, quando Porter Robinson e sua equipe montaram um enorme quadro para os participantes desenharem e assinarem? Devido à COVID-19, seu festival de música fez a transição para o mundo virtual. Inspirado pela sua nova canção, "Look at the Sky", que estreou no final do seu cenário de céu secreto, eu construí este divertido quadro digital para visualizar onde os fãs estão no mundo e como todos nós ainda estamos conectados sob o mesmo céu.

Ao concluir este tutorial, você criará uma página da web de visualização de dados após aplicar o reconhecimento de imagem nas fotos do WhatsApp.

 

gif do projeto 'olhe para o céu!' enviando uma mensagem do WhatsApp
gif do projeto 'olhe para o céu!' visualizando dados no mapa

Neste artigo, abordaremos como você pode acessar as visualizações de dados de seu aplicativo do Python que facilmente compartilham e identificam conteúdo de mídia em um sandbox privado do WhatsApp usando a API da Twilio para WhatsAppAPI da Clarifai e o Flask.

Requisitos do tutorial

Para criar este projeto, você precisará ter os seguintes itens prontos para uso:

  • Python 3.6 ou superior. Se o seu sistema operacional não fornece um interpretador de Python, acesse python.org para fazer download de um instalador.
  • ngrok, um utilitário útil para conectar a versão de desenvolvimento de nosso aplicativo do Python em execução no seu sistema a um URL público ao qual a Twilio pode se conectar. Ele é necessário para a versão de desenvolvimento do aplicativo porque provavelmente o computador está atrás de um roteador ou firewall, o que faz com que não possa ser acessado diretamente na Internet. Você também pode optar por automatizar o ngrok neste artigo.
  • Uma conta da Clarifai. Inscreva-se em uma conta gratuita para gerar uma chave API.
  • Uma conta da Twilio gratuita ou paga. Se você é novo na Twilio, obtenha uma conta gratuita agora mesmo! (Se você se inscrever por meio deste link, a Twilio oferecerá um crédito de US$ 10 ao fazer o upgrade.)
  • Uma conta do Gmail para gerar uma chave API de JavaScript do Google Maps. A documentação no Google vai orientar você na criação de um projeto para a chave API e, em seguida, restringir e habilitar a API de JavaScript do Maps.  

Configuração

Começaremos criando um diretório para armazenar nossos arquivos do projeto. Dentro do terminal de sua preferência, digite:

$ mkdir sky-map
$ cd sky-map

Como instalaremos alguns pacotes Python nesse projeto, crie um ambiente virtual.

Se estiver usando um sistema Unix ou MacOS, abra um terminal e digite os seguintes comandos:

$ python -m venv venv
$ source venv/bin/activate
(venv) $ pip install flask twilio clarifai flask-googlemaps reverse_geocoder python-dotenv pyngrok

OBSERVAÇÃO: dependendo da sua versão ativa do Python, talvez seja necessário especificar python3.

Se estiver em um computador com Windows, digite os seguintes comandos em uma janela de prompt:

$ python -m venv venv
$ source venv\bin\activate
(venv) $ pip install flask twilio clarifai flask-googlemaps reverse_geocoder python-dotenv pyngrok

Se está curioso para saber mais sobre os pacotes, você pode verificá-los aqui:

  • A estrutura do Flask, para criar o aplicativo da web que receberá as notificações de mensagens da Twilio.
  • O pacote python-twilio, para enviar mensagens pelo serviço da Twilio.
  • biblioteca Python da Clarifai, para interagir com a API da Clarifai para reconhecimento de imagem.
  • A biblioteca reverse_geocoder, para recuperar dados de localização das coordenadas.
  • O wrapper pyngrok para o ngrok  

Configurar o sandbox da Twilio para WhatsApp

Faça login no dashboard da Twilio para visualizar seu Programmable SMS (SMS programável). Procure "WhatsApp" na barra lateral. Clique nele para saber como configurar o sandbox.

O sandbox é fornecido pela Twilio. No entanto, quando concluir seu aplicativo, poderá solicitar acesso de produção para o número de telefone da Twilio.

Sandbox da Twilio para WhatsApp

Use seu smartphone para enviar uma mensagem de WhatsApp da frase para seu número de WhatsApp atribuído. Se for bem-sucedido, você receberá uma mensagem, conforme mostrado abaixo.

Mensagem de confirmação da sandbox da Twilio

Você deve compartilhar essas instruções com qualquer outra pessoa que queira participar do sandbox do WhatsApp para compartilhar imagens.

Autenticar nos serviços da Twilio e da Clarifai

Em seguida, precisamos armazenar com segurança algumas credenciais importantes que serão usadas para a autenticação nos serviços da Twilio e da Clarifai.

Para as variáveis TWILIO_ACCOUNT_SID e TWILIO_AUTH_TOKEN, você pode obter os valores que se aplicam à sua conta da Twilio no Console da Twilio:

Credenciais da conta da Twilio

Precisaremos criar um arquivo .env para armazenar com segurança algumas credenciais importantes que serão usadas para a autenticação no serviço da Twilio.

É assim que o arquivo .env deve se parecer:  

TWILIO_ACCOUNT_SID=<your account SID>
TWILIO_AUTH_TOKEN=<your auth token>

Enquanto isso, vamos gerar a API key (chave API) da Clarifai para a parte de reconhecimento de imagem do nosso projeto. Para usar a API da Clarifai, você precisa criar uma conta e um aplicativo.

export CLARIFAI_API_KEY=<"your Clarifai API Key">

Se você for um usuário do Windows, substitua export por set para a API key (chave API) da Clarifai.

Receber e responder mensagens com a Twilio

O objetivo deste aplicativo é permitir que amigos e familiares enviem mensagens de texto ao seu número do WhatsApp com uma imagem do céu e que apareça em nossa página de visualização do Google Maps.

Depois de enviar uma mensagem de texto com a frase gerada no console da Twilio para WhatsApp, os usuários devem habilitar seus serviços de localização do WhatsApp para que possam enviar sua localização atual antes de prosseguir com o envio de uma imagem. O desenvolvedor pode acessar a visualização do Google Maps acessando localhost:5000 ou seu URL exclusivo do ngrok. Os pontos no mapa são gerados dos dados recuperados de cada usuário que envia mensagens de texto para o número do WhatsApp.

Desenvolver as funções

 API da Twilio para programmable SMS  usa um webhook (retorno de chamada da Web) para permitir que dados em tempo real sejam entregues a outros aplicativos. Isto é especialmente importante porque permite que vejamos constantemente os status de nossos amigos.

Abra o arquivo app.py que você criou e coloque o seguinte código acima das linhas do ngrok:

import os
from dotenv import load_dotenv
from flask import Flask, request, render_template
from twilio.twiml.messaging_response import MessagingResponse
from pprint import pprint   # makes payload look nicer to read
from twilio.rest import Client
from flask_googlemaps import GoogleMaps
from flask_googlemaps import Map

load_dotenv()

app = Flask(__name__)
GoogleMaps(app, key="<YOUR GOOGLE MAPS API KEY>")
client = Client()

sky_pics = {}
markers = []

def respond(message):
    response = MessagingResponse()
    response.message(message)
    return str(response)

@app.route('/webhook', methods=['POST'])
def reply():
    sender = request.form.get('From')
    media_msg = request.form.get('NumMedia')    # 1 if its a picture 
    message_latitude = request.values.get('Latitude')
    message_longitude = request.values.get('Longitude')
    # check if the user already sent in a pic. if they send something new, then update it
    if media_msg == '1' and sender in sky_pics:
        pic_url = request.form.get('MediaUrl0')  # URL of the person's media
        relevant_tags = get_tags(pic_url)
        print("The tags for your picture are : ", relevant_tags)
        if 'sky' or 'weather' in relevant_tags and sky_pics.get(sender)[4] is None:
            sky_pics.get(sender)[4] = pic_url
            return respond(f'Thanks for sending in a picture.')
        if 'sky' or 'weather' in relevant_tags and sky_pics.get(sender)[4] is not None:
            # replace the picture URL in sky_pics dictionary
            sky_pics.get(sender)[4] = pic_url
            return respond(f'Your picture has been updated.')
        else:
            return respond(f'Please send in a picture of the sky.')
    elif message_latitude is not None and message_longitude is not None:
        location = get_location(message_latitude, message_longitude)
        sky_pics[sender] = [None] * 5
        sky_pics.get(sender)[0] = message_latitude
        sky_pics.get(sender)[1] = message_longitude
        sky_pics.get(sender)[2] = location[0]
        sky_pics.get(sender)[3] = location[1]
        return respond(f'Your location has been set to : {location}')
    else:
        return respond(f'Please send your current location, then send a picture of the sky.')

No código acima, uma instância GoogleMaps é definida. Para ver a visualização do Google Maps no navegador da Web, acesse o console do Google Cloud Platform para criar um projeto e gerar uma API key (chave API). Antes de prosseguir, restrinja sua chave API clicando no nome do projeto, neste caso, API key 1.

Página de restrição de chave da API do Google Cloud Platform

A captura de tela acima mostra as opções para restringir sua chave API a um dos muitos serviços do Google. Clique na opção Restrict key (Restringir chave) para ver um menu suspenso e localizar Maps Javascript API (API JavaScript do Maps). Se a API Maps JavaScript (API JavaScript do Maps) não estiver na lista suspensa, será necessário ativar a API primeiro.

Google Cloud Platform - Página de habilitação da API Maps Javascript

Clique em salvar quando terminar.

Depois de concluir as etapas acima, localize a página do projeto para ver uma página semelhante a esta:

Google Cloud Platform - Lista de chaves de API no projeto

Insira sua Chave na linha GoogleMaps(app, key="<YOUR GOOGLE MAPS API KEY>") para que você possa usar os serviços do Google para gerar o mapa e testá-lo localmente.

Volte ao código em app.py. Observe que existem funções chamadas get_tags() e get_location() que ainda não foram definidas. Falaremos sobre essas funções mais adiante no artigo, bem como a estrutura de dados sky_pics que contém as informações do remetente, como as coordenadas de localização e os dados de imagem.

Configurar um servidor do Flask de desenvolvimento

Agora que você salvou o código acima em seu arquivo, teremos que realizar os testes iniciando um servidor do Flask de desenvolvimento. Digite a seguinte linha em seu terminal:

export FLASK_APP=app.py
export FLASK_ENV=development

Lembre-se de que, se você for um usuário do Windows, precisará substituir export por set para as variáveis de ambiente.

Essas linhas são convenientes porque sempre que você salvar o arquivo de origem, o servidor será recarregado e refletirá as alterações.

Então, digite flask.run em seu terminal para iniciar a estrutura do Flask.

saída de texto do aplicativo do flask no terminal após a execução de &#x27;execução do flask&#x27;

A captura de tela acima mostra a aparência do seu console depois de executar o comando flask run. O serviço está sendo executado de modo privado na porta 5000 do computador e aguarda as conexões de entrada. Você também perceberá que o modo de depuração está ativo e que o servidor do Flask foi reiniciado para refletir minhas alterações.

Enquanto o Flask estiver sendo executado em uma janela do terminal, abra uma segunda aba ou janela do terminal. Inicie o ngrok com o seguinte comando:

$ ngrok http 5000

Ótimo! Você habilitou seu serviço do Flask publicamente pela Internet!

ngrok é uma excelente ferramenta, pois permite criar um domínio público temporário que redireciona as solicitações HTTP para a nossa porta local 5000.

Se não for possível instalar o ngrok em todo o sistema, tente localizar o arquivo ngrok executável manualmente para chamá-lo em seu terminal usando caminho completo dele. Por exemplo, meu arquivo do ngrok estava em meu desktop, então eu digitaria:

$ /Users/diane/Desktop/ngrok http 5000

Exemplo de execução ngrok afunilando seu aplicativo na porta 5000

Seu terminal do ngrok agora terá a aparência da imagem acima. Como você pode ver, há URLs na seção "Forwarding" (Encaminhamento). Eles são URLs públicos usados pelo ngrok para redirecionar as solicitações para nosso servidor do Flask.

Configurar um webhook com a Twilio

Copie o URL do ngrok que usamos anteriormente (neste caso, https://ad7e4814affe.ngrok.io/) e volte para o Console da Twilio, onde diremos à Twilio para enviar notificações de mensagens recebidas para esse URL.  

No console da Twilio, clique em (...) na barra lateral esquerda para encontrar o dashboard Programmable SMS. Procure "WhatsApp" na barra lateral. Clique nele para desbloquear a opção "Sandbox" em "Learn" (Aprender), que vimos anteriormente neste artigo.

Cole o URL copiado da sessão do ngrok no campo "WHEN A MESSAGE COMES IN" (QUANDO UMA MENSAGEM FOR RECEBIDA) e inclua /webhook, pois esse é o nosso endpoint. Este é o meu exemplo de referência:

Sandbox da Twilio para WhatsApp com webhook no campo de texto

O URL do ngrok é "https://ad7e4814affe.ngrok.io/webhook" 

Antes de clicar no botão "Save" (Salvar), certifique-se de que o método de solicitação esteja definido como HTTP POST.

Chegou a hora de realizar os testes! Faça login no WhatsApp e envie uma mensagem de texto para o sandbox da Twilio.

Exemplo de texto do bot do projeto &#x27;olhe para o céu!&#x27;

Parece que funcionou! Agora é hora de enviar uma imagem do céu.

Como deixar o app mais eficiente

No arquivo app.pysky_pics foi declarado como um dicionário Python para o projeto. Essa variável global é uma estrutura de dados que nos permite ter uma chave exclusiva representando o número de telefone da pessoa. Cada chave terá suas próprias informações que podem ser atualizadas. O dicionário também é um objeto retornável que lista de forma conveniente todas as chaves (número de telefone do remetente) e seus valores (as coordenadas, o local e uma imagem).

Com a ajuda do Geocoder, Clarifai e Google Maps, podemos criar um aplicativo mais eficiente para ver nossos dados de uma forma criativa e divertida.

Criar marcadores no mapa com a API do Geocoder

Quando o usuário ativa os serviços de localização e envia mensagens de texto com localização atual dele, as coordenadas Longitude e Latitude ficam disponíveis no payload de mensagens do WhatsApp da Twilio. Trabalhar com o ngrok permite visualizar todas as solicitações recebidas no seu webhook localmente, o que facilita a visualização dos dados do emissor do texto. Aqui está uma captura de tela das solicitações recebidas geradas pelo ngrok:

exemplo de página http:4040 do ngrok mostrando as coordenadas de longitude e a latitude do texto

Essas coordenadas são usadas para traçar os marcadores de localização na API do Google Maps, mas você pode usar a API Reverse Geocoder para acompanhar os locais onde os usuários estão e confirmar a localização deles.

Crie um arquivo no diretório raiz chamado geocoder.py e copie o código a seguir:

import reverse_geocoder as rg
def get_location(message_latitude, message_longitude):
    coordinates = (message_latitude, message_longitude)
    results = rg.search(coordinates) # default mode = 2
    state = results[0]['admin1']
    country = results[0]['cc']
    location = [state, country]
    return location

Depois de importar o código, salve-o e volte para app.py. Você precisa importar a função do novo arquivo Python para o arquivo principal que é executado via Flask. Adicione esta linha na parte superior do arquivo, juntamente com os outros pacotes importados para este aplicativo.

from geocoder import get_location

Ótimo! Agora que temos dados de localização, precisamos coletar as imagens.

Identificar o céu com a Clarifai

Este projeto é uma oportunidade divertida de testar a API da Clarifai e ver como ela funciona em relação às entradas do usuário. Nesta seção, você entenderá por que as APIs de reconhecimento de imagem são importantes, especialmente ao criar um projeto que apresenta aos usuários não confiáveis a capacidade de carregar qualquer foto que desejarem. Aqui, você vai querer ter certeza de que os usuários só enviam imagens do céu em vez de algo mais, como um meme.

Dito isso, vamos criar um novo arquivo do Python. Eu criei o image_classifer.py para armazenar o código que usa a API da Clarifai. Copie o seguinte código no arquivo que você acabou de criar:

from clarifai.rest import ClarifaiApp
from pprint import pprint   #makes payload look nicer to read
app = ClarifaiApp()

def get_tags(image_url):
    response_data = app.tag_urls([image_url])
    sky_tags = {}   #dictionary data structure for faster lookup time 
    for concept in response_data['outputs'][0]['data']['concepts']:
        sky_tags[concept['name']] = 1
    return sky_tags

Depois de importar o código, salve-o e volte para app.py. Você precisará importar a função do novo arquivo do Python para app.py. Adicione esta linha na parte superior do arquivo, juntamente com os outros pacotes importados para este aplicativo.

from image_classifier import get_tags

Se ainda não tiver feito isso, defina a API key (chave API) da Clarifai com o seguinte comando:

export CLARIFAI_API_KEY=<"your Clarifai API Key">

Se você for um usuário do Windows, substitua export por set para a API key (chave API) da Clarifai.

Aqui está um exemplo do que acontecerá quando testarmos todo o aplicativo mais tarde. O usuário enviará uma mensagem com uma imagem do céu. Se o aplicativo confirmar que a imagem é, de fato, um céu, o WhatsApp responderá com uma mensagem "Thanks for sending in a picture" (Obrigado por enviar uma imagem), como visto abaixo:

captura de tela de uma conversa do whatsapp sobre uma imagem de céu e uma mensagem de agradecimento

A linha print("The tags for your picture are : ", relevant_tags) do app.py permite visualizar as tags geradas pela API da Clarifai a partir da imagem que foi enviada. Confira as tags da foto acima:

The tags for your picture are :  {'tree': 1, 'sky': 1, 'nature': 1, 'no person': 1, 'leaf': 1, 'blue sky': 1, 'sun': 1, 'fall': 1, 'landscape': 1, 'light': 1, 'bright': 1, 'wood': 1, 'fair weather': 1, 'summer': 1, 'park': 1, 'grass': 1, 'outdoors': 1, 'moon': 1, 'countryside': 1, 'rural': 1}

Parece que a API da Clarifai está funcionando e o app pode dizer para você enviar uma imagem de um céu real.

Visualizar dados no Google Maps

Chegou a hora de criar o nosso belo mapa de dados. Se você ainda não criou uma API key (chave API) do Google Maps, reserve um tempo para gerar uma chave e habilitar o Google Maps para JavaScript.

Existem diferentes métodos de implementação de HTML em um aplicativo do Flask, mas achei que a solução a seguir fosse suficiente para a visualização.

Cole o seguinte código entre a definição do webhook e as linhas do ngrok no arquivo app.py:

@app.route("/")
def mapview():
    for entry in sky_pics:
        if sky_pics.get(entry)[4] is None:
            url_entry_pic = 'https://s3-external-1.amazonaws.com/media.twiliocdn.com/ACa2dea70cb125daf20c4ac433be77eda4/d7a07ccac2cf9321e82559c82beff7ed'       # random filler pic
            sky_pics.get(entry)[4] = url_entry_pic
        markers.append({
            'icon': 'http://maps.google.com/mapfiles/ms/icons/green-dot.png',
            'lat': sky_pics.get(entry)[0], 
            'lng': sky_pics.get(entry)[1],
            'infobox': '<div id="bodyContent">' +
                '<img src="' + sky_pics.get(entry)[4] + '" alt = "sky" style="width:175px;height:220px;"></img>' + '</div>' 
        })
    mymap = Map(
        identifier="sndmap",
        style=(
            "height:100%;"
            "width:100%;"
            "top:0;"
            "position:absolute;"
            "z-index:200;"
            "zoom: -9999999;"
        ),
        # these coordinates re-center the map
        lat=37.805355,
        lng=-122.322618,
        markers = markers,
    )
    return render_template('index.html', mymap=mymap)

Como pode ver, há uma mistura de HTML e Python para gerar os pontos de referência no mapa. A matriz markers foi criada para conter os elementos HTML, como a identificação representada por icon e infobox, que são gerados no site do Google Maps. O infobox é uma janela pop-up que exibe a imagem do céu enviada pela pessoa com as coordenadas fornecidas, para que você possa brincar com o HTML lá e descobrir o que deseja ver na sua visualização.

Ao criar a matriz markers, o dicionário sky_pics é iterado e identifica todos os usuários que não puderam enviar uma imagem. Você pode escolher sua própria maneira de lidar com os dados incompletos. Eu usei uma imagem de preenchimento aleatória de um céu para que o mapa ainda possa ser preenchido com pontos de dados em vez de criar um erro fora dos limites para os dados ausentes.

Um objeto de mapa JavaScript chamado mymap também foi criado no código acima. Ele será chamado em outro arquivo. No diretório raiz, crie uma pasta chamada templates (modelos) e dentro desse arquivo, crie index.html.

<!DOCTYPE html>
    <html>
    <head>
            {{"decoupled-map"|googlemap_js(37.4419, -122.1419, markers=[(37.4419, -122.1419)])}}
            {{mymap.js}}
    </head>
    <body>
        <body style='margin: 0'></body>
        <div style="width: 100%; height: 100%" id="mapContainer"></div>
        <h1>Look at the sky!</h1>
        <h2> I'm still here. </h2>
        {{mymap.html}}
    </body>
</html>

Este arquivo HTML é processado em app.py quando você acessa seu URL do ngrok. Com a ajuda de flask-googlemaps, que importamos no arquivo app.py, podemos usar funções e modelos globais no ambiente Jinja para visualizar o Mapa em nosso navegador da web. Confira a publicação de Miguel Grinberg se estiver interessado em saber mais sobre os modelos e o ambiente Jinja para apps Python.

Personalize os parâmetros map() em app.py e os cabeçalhos HTML para que sua visualização na Web pareça mais atraente.

Executar o app de visualização de dados do WhatsApp

É hora de concluir tudo e ter certeza de que seu programa está funcionando da maneira que deseja para que você possa compartilhar o projeto com amigos e familiares. Se você quiser um exemplo, veja meu código no GitHub.

Certifique-se de que tenha uma guia executando flask e uma guia executando ngrok. Se você o fechou por algum motivo, inicie-o novamente agora com os seguintes comandos em suas respectivas guias.

(venv) $ flask run

E na segunda guia:

$ ngrok http 5000

Além disso, certifique-se de que o URL do webhook do ngrok esteja atualizado dentro do sandbox da Twilio para WhatsApp. Sempre que reiniciar o ngrok, o URL mudará. Então, será necessário substituir o URL. Lembre-se de adicionar /webhook no final do URL de encaminhamento do ngrok.

É hora de compartilhar fotografias do céu de sua própria casa. Não se esqueça de dizer aos amigos o seu número de WhatsApp para que eles possam enviar mensagens de texto, registrar a localização deles no sandbox e enviar imagens incríveis do céu. Depois de pelo menos uma pessoa ter enviado o local e a imagem a você, visite o URL do ngrok para ver os dados.

Captura de tela do Google Maps com uma identificação e imagem de um céu nesse local

Conclusão: criar um app de visualização de dados do WhatsApp

Parabéns por criar seu primeiro aplicativo de visualização de dados do WhatsApp! Você deve estar impressionado com as fotos do céu que foram compartilhadas com seu aplicativo. Este tutorial simples do Google Maps e WhatsApp mostra como criar uma visualização de dados das imagens e dos locais de amigos e familiares em todo o mundo. Eles podem até mesmo atualizar a localização deles com uma imagem do pôr do sol no final do dia com a ajuda da Twilio, Python, Clarifai e Flask.

Espero que este artigo tenha sido divertido e ensinado você sobre essas APIs, mas que também o tenha lembrado de aproveitar o mundo ao seu redor. É divertido escapar de mundos, mas não se esqueça de apreciar a beleza à sua volta. Podemos começar admirando as cores do céu e percebendo que compartilhamos o mesmo céu, independentemente da distância. Como Porter Robinson mencionou, tudo o que precisamos já está aqui.

O que há de novo nos apps de visualização de dados?

As APIs são muito divertidas de usar, não acha? Se está procurando maneiras de expandir este projeto, tente o seguinte:

Avise-me se estiver trabalhando em qualquer projeto ou se vir algo adorável no céu!

Este artigo foi traduzido do original "Look at the Sky! Learn Data Visualization with WhatsApp, Google Maps". Enquanto melhoramos nossos processos de tradução, adoraríamos receber seus comentários em help@twilio.com - contribuições valiosas podem render brindes da Twilio.