domingo, 3 de abril de 2022

Criando seu próprio Kubernetes Cluster com Kind

Índice

 

Introdução

Com a crescente migração das empresas para o ambiente cloud, a necessidade de utilização de containers se tornou cada vez maior. Sistemas com arquiteturas mais complexas se tornam mais facies de manter e integrar através de ferramentas de contêineres como Docker. Contêineres trazem simplicidade quando pensamos em unidades, mas o que acontece quando temos que gerenciar o ciclo de vida de vários contêineres ao mesmo tempo? Nesse caso, precisamos de um orquestrador de contêineres e há diversas opções (AWS EKS, Open Shift, Nomad, Docker Swarm), porém vamos falar do mais popular de todos, Kubernetes.

Kubernetes

O Kubernetes é uma plataforma para gerenciamento de cargas de trabalho e serviços distribuídos em contêineres, que facilita tanto a configuração declarativa quanto a automação.

Para publicar um contêiner no kubernetes podemos utilizar a ferramenta kubectl que é a ferramenta oficial de linha de comando. Você pode encontrar mais detalhes neste link.

kubectl apply -f ./aplicacao.yaml

Os recursos que queremos publicar no kubernetes podem ser descritos em arquivos YAML como no exemplo abaixo

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

Não vamos aprofundar muito no kubernetes pois não é o objetivo deste artigo.

Como testar arquivos do kubernetes?

Uma parte importante do ciclo de desenvolvimento são os testes. É muito importante que a gente consiga testar inclusive os arquivos que descrevem os recursos que vamos publicar no kuberntes.

O que é o Kind?

kind é uma ferramenta para executar clusters locais do Kubernetes usando “nós” em contêiner do Docker.

Isso significa que podemos iniciar um cluster kubernetes no docker instalado na máquina e assim conseguir testar nossos arquivos.

Como Funciona?

De maneira simples, o kind cria um container docker que irá representar o cluster kubernetes.



Mostrando na prática

Instalando o kind

Há diversas formas de instalar o kind e os detalhes podem ser vistos aqui.

Exemplo utilizando o brew para instalar no MAC:

brew install kind

Criando cluster

A forma mais simples é indo direto no comando create

kind create cluster

Também é possível criar a partir de um arquivo de configuração:

kind: Cluster
apiVersion: kind.x-k8s.io/v1
name: cluster-kind
kind create cluster --config cluster.yaml

Obtendo informações do cluster

O comando abaixo lista os clusteres que foram criados.

kind get clusters

O comando abaixo detalha um cluster específico

kubectl cluster-info --context cluster-kind

Deletando o cluster

Para deletar o cluster é tão simples quanto cirar:

kind delete cluster --name cluster-kind

Configurando ingress controller

Esse exemplo mostra como criar um Ingress Controller que será responsável por estabelecer uma conexão entre o ambiente local o cluster kubernetes.

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: cluster-kind
nodes:
- role: control-plane
  kubeadmConfigPatches:
  - |
    kind: InitConfiguration
    nodeRegistration:
      kubeletExtraArgs:
        node-labels: "ingress-ready=true"    
  extraPortMappings:
  - containerPort: 80
    hostPort: 80
    protocol: TCP
  - containerPort: 443
    hostPort: 443
    protocol: TCP

Agora basta criar o cluster

kind create cluster --config cluster.yaml

Publicando recursos no kubernetes local

Os comandos abaixo dependem da instalação do kubectl e como não é escopo detalhar o kubernetes, vou coloca-los apenas para fins de exemplo.

kind: Pod
apiVersion: v1
metadata:
  name: kind-app
  labels:
    app: kind-app
spec:
  containers:
  - name: kind-app
    image: hashicorp/http-echo:0.2.3
    args:
    - "-text=Hello World! This is a Kubernetes with kind App"
---
kind: Service
apiVersion: v1
metadata:
  name: kind-service
spec:
  selector:
    app: kind-app
  ports:
  # Default port used by the image
  - port: 5678
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: kind-ingress
spec:
  rules:
  - http:
      paths:
      - pathType: Prefix
        path: "/kind"
        backend:
          service:
            name: kind-service
            port:
              number: 5678
---
kubectl apply -f kind-app.yml

Agora é só acessar o link http://localhost:5678/kind para ver o resultado

Outros recursos

Para aplicar outros recursos como config-map, secrets, deployments, cron-job, etc basta seguir a mesma ideia.

Conclusão

Isso foi uma introdução bem superficial ao kind, apenas para sentir o gostinho. Há muito mais para explorar. O mais importante é entender que o kind permite a realização de testes locais de todos os artefatos antes mesmo de executa-los no ambiente real.

Referência

terça-feira, 1 de março de 2022

Google Docs API - Criando e atualizando planilhas.

Índice



 

Introdução

Esse artigo vai te ensinar a criar uma planilha no google sheets usando a linguagem python com as libs gspread e a lib oficial do google google-api-python-client.

Vamos usar o CSV gerado no post Selenium com Python para criar uma planilha no Google Drive.

Para isso, será necessário criar um projeto no google cloud, configurar o acesso a API do Google Sheets e configurar uma credencial de acesso para o nosso programa, que será feito em python.

Criando um App no Google

O primeiro passo é criar um Projeto no Google Cloud clicando aqui. Para criar um projeto, no canto superior esquerdo, clique em → IAM & Admin → Create a Project, como mostra a figura:



Dê um nome para seu projeto e aperte em Create:



Em seguida, precisamos configurar o nosso projeto para permitir que ele acesse a API do Google Sheets. Para isso acesso o menu → API & Services → Library



No campo de pesquisa, digite "sheets" e aperte "enter" para pesquisar a API que queremos.


Selecione a API "Google Sheets API”:


Aperte no botão “enable”



Agora temos que repetir esse último passo mas desta vez para a API do Google Drive. Acesse novamente o menu → API & Services → Library e pesquise:


Selecione a API "Google Drive API”:


Aperte no botão "enable”


Gerando Credenciais de acesso.

Agora que temos tudo pronto, precisamos gerar as credencias para que a nossa aplicação possa se autenticar na nossa conta e com isso criar a manipular as planilhas.

O Google permite dois tipos de autenticação:

  • User authentication: Esse tipo de autenticação irá solicitar ao usuário que autentique com sua conta google sempre que o programa for executado. É um modelo OAutho2
  • App authentication: Nesse tipo de autenticação o usuário com a conta google permite que o programa se autentique em seu nome utilizando credenciais pré configuradas.

Não é escopo desse posto aprofundar no mecanismo de autenticação do Google. Se quiser se aprofundar mais, clique aqui e acesse a documentação oficial.

Para criar a credencial de acesso, acesse o menu → API & Services → Credentials


Na tela que abrir, aperte no botão "+ CREATE CREDENTIALS” e em seguida "OAuth Client ID”:


Na tela que abrir, aperte no botão abaixo para configurar um tela de consentimento, que será exibida para o usuário consentir que o nosso programa terá acesso a sua planilha:


Agora você tem duas opções:

  • Internal: Disponível apenas para usuários do Google Workspace que é a versão para empresa das ferramentas do Google.
  • External: É a opção para o público em geral.

Nesse post, vou seguir com a opção external, mas caso você possua conta no Google Workspace, pode selecionar a primeira opção.

Aperte no botão "create”.


Na tela que aparecer, preencha as informações obrigatórias e aperte "Save And Continue”


Essa é a parte mais importante, que é configurar os escopos da nossa credencial. Em outras palavras, aqui vamos definir quais permissões nosso programa irá precisar para executar seu trabalho. Essas opções serão apresentadas para o usuário dizer se permite ou não que a nossa aplicação tenha esses acessos.

Aperte no botão ADD OR REMOVE SCOPES



Você pode pesquisar ou adicionar manualmente os escopos necessários. Como a pesquisa não é muito boa, vamos fazer manualmente. Vá até a opção "Manually add Scopes" e adicione os seguintes escopos:


Quando finalizar, aperte no botão "update" e em seguida no botão "Save and continue".

O próximo passo é necessário por que o Google entende que você que o seu programa será disponibilizado para o público em geral e por tanto precisa passar pela avaliação técnica de uma equipe da Google. Isso serve para google garantir que não é um programa de fraude e nem nada do tipo.

Enquanto seu programa não é autorizado pela equipe técnica do google, você pode cadastrar alguns usuários de teste que terão acesso imediato ao programa.

Para configurar quais usuários de teste terão acesso a esse credencial aperte no botão "+ add users” e adicione o seu usuário, depois aperte no botão "save and continue”.


Agora volte na tela abaixo para finalmente criar a credencial:


Preencha os campos e aperte no botão "create":


Na próxima tela, faça download do json que contem as credenciais e guarde pois vamos utilizar no código:


Pronto, sua credencial está criado e devidamente configurado.

Uffa! vamos ao código!

Bibliotecas Python

Para o nosso exemplo, vamos utilizar 4 bibliotecas:

As 3 primeiras bibliotecas são as bibliotecas oficiais da google, com elas é possível realizar todas as operações que precisamos (copiar, criar, editar e excluir documentos), porém essas libs tem uma estrutura verbosa e difícil de utilizar, então vamos utiliza-las apenas para gerenciar nossas credencias e token.

Para realizar as operações nas planilhas, vamos utilizar uma biblioteca bem simples mas ao mesmo tempo muito completa chamada gspread. Essa biblioteca é uma interface de comunicação com a API do Google Sheets, abstraindo toda sua complexidade e verbosidade, tornando nosso desenvolvimento mais rápido e fácil. Com ela é possível realizar diversas operações como:

  • abrir planilhas por título, chave e url.
  • ler, escrever e formatar um conjunto de celulas
  • compartilhar a planilha com outros usuários
  • fazer atualizações em lote
  • Diversas outras operações.

Para saber mais sobre como utilizar a biblioteca, basta clicar aqui e ler a documentação no github.

Codificando nosso exemplo

Vamos relembrar o nosso exemplo: vamos criar uma planilha no Google Drive que servirá de template e nela vamos criar duas abas: Gráficos e Ações.

A aba "Ações" servirá para carregar o nosso arquivo CSV com os dados. A aba "Gráficos" irá apresentar um gráfico de pizza com o preço das ações da primeira aba.

Nosso programa irá copiar essa template e criar uma nova planilha onde vamos fazer o upload do CSV. Dessa forma, podemos criar várias planilhas com dados e gráficos diferentes.

Passo 1 - Criar a Template

Vamos criar uma planilha em branco para servir de template. Vá até seu google drive crie um diretório, em seguida clique com o botão direito e crie uma planilha. Dê o nome de Template e crie duas abas chamadas de Gráficos e Ações.





Copie e cole (command+shift+v no MAC e ctrl+shit+v no windows) o conteúdo abaixo na célula A1 da aba Ações

ativo	valor_atual	min	max	yield	valorizacao
MGLU3	6,33	5,74	26,22	0,20%	-3,06%
LREN3	26,2	21,69	43,95	1,60%	-1,76%
BBAS3	32,23	26,49	35,24	7,00%	-0,19%
ITSA4	10,27	8,79	11,1	4,70%	1,99%

Agora na aba Gráficos, vá no menu Insert → Charts e crie um gráfico de pizza com as seguintes configurações:


Passo 2 - Autenticar e gerar o token.

Para manipular uma planilha, precisamos criar um cliente do gspread e para isso precisamos autenticar na api do google utilizando a credencial que baixamos nos passos anteriores.

import gspread
from gspread.spreadsheet import Spreadsheet
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow

CREDENTIALS_FILE=f'<CAMINHO PARA A CREDENCIAL BAIXADA>/credentials.json'
TOKEN_FILE=f'<CAMINHO ONDE O TOKEN SERA GERADO>/acesso/token.json'

SCOPES = [
    'https://www.googleapis.com/auth/drive',
    'https://www.googleapis.com/auth/drive.readonly',
    'https://www.googleapis.com/auth/spreadsheets',
    'https://www.googleapis.com/auth/spreadsheets.readonly'
]

def get_credentials():
    credentials = None
    if os.path.exists(TOKEN_FILE):
        credentials = Credentials.from_authorized_user_file(TOKEN_FILE, SCOPES)
    if not credentials or not credentials.valid:
        if credentials and credentials.expired and credentials.refresh_token:
            credentials.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(CREDENTIALS_FILE, SCOPES)
            credentials = flow.run_local_server(port=0)
        with open(TOKEN_FILE, 'w') as token:
            token.write(credentials.to_json())
    return credentials

def main():
    client = gspread.authorize(get_credentials())

if __name__ == '__main__':
    main()

Ao executar o código acima, um browser irá se abrir para confirmar o acesso solicitado pelos escopos. Basta confirmar e fechar o browser que o arquivo token.json será criado. Esse arquivo irá conter o token de acesso que precisamos para comunicar com a api do google. O token tem prazo de validade e precisará ser renovado quando o tempo expirar.

Passo 3 - Criar uma nova planilha a partir da template

Para realizar um cópia da template para uma planilha final, vamos primeiro verificar se essa planilha já existe e caso exista ela será removida.

TEMPLATE_FOLDER_ID = f'1WPriGQaE5cScXL8UK16FD-NCJoKUcls4'
TEMPLATE_ID = f'1b05snBcvehGex_jsN1mgtBYm7jOJZQKkuLIHJ9E4RV8'

planilha_nova = 'Versão nova'    
print(f"Verificando se planilha {planilha_nova} existe")
try:
    sh = client.open(planilha_nova, TEMPLATE_FOLDER_ID)
    print(f"Panilha {planilha_nova} já existe e será removida")
    client.del_spreadsheet(sh.id)
except:
    print(f"Panilha {planilha_nova} ainda não existe")

print(f"Copiando a template para: {planilha_nova}")
client.copy(TEMPLATE_ID, title=planilha_nova, copy_permissions=True)

A variável TEMPLATE_FOLDER_ID é o identificador único do diretório que criamos e pode ser obtido direto da URL do diretório:


A variável TEMPLATE_ID também pode ser obtida da mesma maneira:


Não se esqueça de substituir pelos valores correspondentes do diretório e planilhas que você gerou no seu google drive.

Passo 4 - Upload do CSV

Por último, vamos fazer upload do arquivo CSV para a a aba "Ações” na planilha que acabou de ser gerada

CSV_FILE = f'<CAMINHO DO CSV>/acoes.csv'

print(f"Atualizando CSV: {CSV_FILE}")
spreadsheet: Spreadsheet = client.open(planilha_nova)

with open(CSV_FILE, 'r') as file:
    spreadsheet.values_update(
        'Ações',
        params={'valueInputOption': 'USER_ENTERED'},
        body={'values': list(csv.reader(file))}
    )

Passo 5 - Formatando celula (opcional)

Caso seja necessário, podemos formatar células e colunas da planilha:

print(f"Formatando Cabecalho")
aba_acoes = spreadsheet.get_worksheet(1)
aba_acoes.format('A1:F1', {
    'horizontalAlignment': 'CENTER',
    'textFormat': {'bold': True}
    })

No nosso caso toda formatação que estiver na template será mantida na cópia mas está ai o exemplo caso seja necessário fazer alguma formatação customizada.

Dicas

Caso seu google sheets esteja configurado com o separador decimal "." você deve configurar para usar a ",”. Vá no menu File → Settings e configure o Locale para Brasil.





Conclusão

Esse foi um artigo bem extenso devido a configuração do aplicativo no google mas espero que possa ser útil para você.

O código fonte completo pode ser encontrado aqui.

Referências

sábado, 5 de fevereiro de 2022

Selenium com Python

Índice



Introdução

Selenium automates browsers. That's it! What you do with that power is entirely up to you. Primarily it is for automating web applications for testing purposes, but is certainly not limited to just that. Boring web-based administration tasks can (and should) also be automated as well.

Essa frase foi retirada diretamente do site oficial do Selenium. Traduzindo, o Selenium começou como um framework para testes funcionais de aplicações web, porém com o passar do tempo foi amplamente utilizado para automatizar tarefas como acessar e coletar informações de páginas web.

Neste artigo, vamos abordar esse aspecto de automação e webscraping em um exemplo prático, onde vamos buscar informações sobre ações no site Fundamentus e montar um arquivo CSV que possa ser importado em qualquer lugar (banco de dados, Google Sheets, etc.)



Arquitetura

Para começar precisamos entender como funciona a arquitetura do selenium que está dividida em três partes.

  • Cliente: é uma biblioteca específica para uma determinada linguagem feita para interagir com o selenium
  • Driver: é o agente que irá permitir a interação entre o cliente e o browser de fato
  • Browser: é o ambiente onde a página será renderizada e executada.







Instalações

Neste exemplo, vamos utilizar a linguagem python, então precisamos baixar duas coisas, a biblioteca oficial do selenium para python e o driver correspondente ao browser que estamos utilizando.

A instalação da biblioteca é bem simples:

pip install selenium

(ou você pode usar o poetry)

A instalação do driver pode ser um pouco complicada pois a versão dele deve ser idêntica a versão do browser instalado na máquina, então para facilitar, é possível utilizar a imagem docker do selenium.

version: '3.8'

services:
    selenium-chrome:
        image: selenium/standalone-chrome:latest
        hostname: selenium-chrome
        networks:
            - selenium-network
        privileged: true
        shm_size: 2g
        ports:
            - "4444:4444"
            - "7900:7900"
        healthcheck:
            test: ["CMD", "curl", "-f", "http://localhost:7900"]
            interval: 10s
            timeout: 10s
            retries: 5
    app:
        build: ./
        volumes:
            - /Users/geraldoferraz/repositorios/blog/selenium-with-python:/tmp/
        networks:
            - selenium-network
        depends_on:
            selenium-chrome:
                condition: service_healthy

networks:
    selenium-network:
      driver:  bridge



Site Fundamentus

Agora que temos tudo que precisamos, vamos analisar a página do Fundamentus e entender onde estão as informações que queremos coletar. Vamos acessar a página de análise da ação da Magazine Luiza (MGLU3). Para isso, acesse este link e você verá uma página semelhante a essa:




Inspect do Chrome

A forma mais fácil de localizar um elemento é utilizando o XPATH. Vamos utilizar a ferramenta de inspeção do browser para recuperar o xpath das informações de “Cotação”, “Min 52 sem”, “Max 52 sem”, “Div. Yield” e a Oscilação “Dia”.

  • Encontre a informação desejada, clique com o botão direito do mouse e selecione a opção “inspect”


  • Na ferramenta de inspeção que se abriu, no item selecionado, clique com o botão direito do mouse e selecione a opção “Copy”→ “Copy full xpath”



Hands-on

Agora que sabemos como chegar no nosso elemento, vamos ver o código necessário para realizar a coleta.

Primeiro, a partir do driver, precisamos construir o objeto que irá representar o browser.

from selenium import webdriver
from selenium.webdriver.chrome.service import Service

def main():
    option = webdriver.ChromeOptions()

    s = Service('/Users/geraldoferraz/Downloads/chromedriver')
    navegador = webdriver.Chrome(service=s, options=option)

    #para trabalhar dentro do docker
    #navegador = webdriver.Remote('http://selenium-chrome:4444/wd/hub', options=option)

if __name__ == '__main__':
    main()

Segundo, precisamos carregar a página desejada e utilizar o XPATH que obtivemos no passo anterior para encontrar as informações que queremos.

navegador.get("<https://fundamentus.com.br/detalhes.php?papel=MGLU3>")

try:
    xpath_valor_atual = '/html/body/div[1]/div[2]/table[1]/tbody/tr[1]/td[4]/span'        
    valor_atual = navegador.find_element(By.XPATH, xpath_valor_atual).text
    print(f'valor atual={valor_atual}')
finally:
    navegador.close()

A lib do selenium possui diversas formas de encontrar elementos na página sendo o XPATH o mais preciso:

  • By.ID
  • By.XPATH
  • By.NAME
  • By.TAG_NAME
  • By.CLASS_NAME
  • By.CSS_SELECTOR

Você deve escolher a melhor forma de acordo com a sua lógica. Para o nosso exemplo, o XPATH será suficiente.

No exemplo a seguir, vamos ver como pegar todas as informações que precisamos de um conjunto de ações:

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By

def main():
    option = webdriver.ChromeOptions()
    s = Service('/Users/geraldoferraz/Downloads/chromedriver')
    navegador = webdriver.Chrome(service=s, options=option)

    #para trabalhar dentro do docker
    #navegador = webdriver.Remote('http://selenium-chrome:4444/wd/hub', options=option)

    acoes = ['MGLU3', 'LREN3', 'BBAS3', 'ITSA4']

    try:
        for acao in acoes:
            navegador.get(f"https://fundamentus.com.br/detalhes.php?papel={acao}")
            xpath_valor_atual = '/html/body/div[1]/div[2]/table[1]/tbody/tr[1]/td[4]/span'
            xpath_min = '/html/body/div[1]/div[2]/table[1]/tbody/tr[3]/td[4]/span'
            xpath_max = '/html/body/div[1]/div[2]/table[1]/tbody/tr[4]/td[4]/span'
            xpath_yield = '/html/body/div[1]/div[2]/table[3]/tbody/tr[9]/td[4]/span'
            xpath_valorizacao = '/html/body/div[1]/div[2]/table[3]/tbody/tr[2]/td[2]/span/font'

            valor_atual = navegador.find_element(By.XPATH, xpath_valor_atual).text
            min = navegador.find_element(By.XPATH, xpath_min).text
            max = navegador.find_element(By.XPATH, xpath_max).text
            _yield = navegador.find_element(By.XPATH, xpath_yield).text
            valorizacao = navegador.find_element(By.XPATH, xpath_valorizacao).text

            print(f'valor atual={valor_atual}, min={min}, max={max}, min={_yield}, min={valorizacao} ')
    finally:
        navegador.close()

if __name__ == '__main__':
    main()

A parte mais simples é gerar o CSV

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
import csv

def main():
    option = webdriver.ChromeOptions()
    utilize esse formato para trabalhar localmente
    s = Service('/Users/geraldoferraz/Downloads/chromedriver')
    navegador = webdriver.Chrome(service=s, options=option)

    #para trabalhar dentro do docker
    #navegador = webdriver.Remote('http://selenium-chrome:4444/wd/hub', options=option)

    acoes = ['MGLU3', 'LREN3', 'BBAS3', 'ITSA4']

    try:
        with open('acoes.csv', 'w', newline='') as csvfile:
            cabecalho = ['valor_atual', 'min', 'max', 'yield', 'valorizacao']
            writer = csv.DictWriter(csvfile, delimiter=',', fieldnames=cabecalho)
            writer.writeheader()

            for acao in acoes:
                navegador.get(f"https://fundamentus.com.br/detalhes.php?papel={acao}")
                xpath_valor_atual = '/html/body/div[1]/div[2]/table[1]/tbody/tr[1]/td[4]/span'
                xpath_min = '/html/body/div[1]/div[2]/table[1]/tbody/tr[3]/td[4]/span'
                xpath_max = '/html/body/div[1]/div[2]/table[1]/tbody/tr[4]/td[4]/span'
                xpath_yield = '/html/body/div[1]/div[2]/table[3]/tbody/tr[9]/td[4]/span'
                xpath_valorizacao = '/html/body/div[1]/div[2]/table[3]/tbody/tr[2]/td[2]/span/font'

                valor_atual = navegador.find_element(By.XPATH, xpath_valor_atual).text
                min = navegador.find_element(By.XPATH, xpath_min).text
                max = navegador.find_element(By.XPATH, xpath_max).text
                _yield = navegador.find_element(By.XPATH, xpath_yield).text
                valorizacao = navegador.find_element(By.XPATH, xpath_valorizacao).text

                writer.writerow({'valor_atual': valor_atual, 'min': min, 'max': max, 
                'yield': _yield, 'valorizacao': valorizacao})
    finally:
        navegador.close()

if __name__ == '__main__':
    main()



Atenção!

  • Ao executar o programa, você deve ter notado que um browser se abriu. Para o desenvolvimento, pode ser interessante acompanhar visualmente tudo o que está acontecendo, assim podemos pegar alguma falha na nossa lógica, porém em um ambiente de produção, provavelmente não teremos um ambiente visual para que um browser seja aberto, então é interessante adicionar a configuração abaixo na construção do browser.
option.add_argument('headless')
  • Algumas vezes, o site pode ter algum tipo de proteção contra robôs, que podem prejudicar a performance do site, então, precisamos ficar atentos a isso, caso contrário pode ser que o nosso robô não funcione. Não é o escopo desse artigo mostrar como contornar esse cenário, mas saiba que é possível, basta realizar uma pesquisa rápida no google.
  • Para trabalhar dentro do docker, basta descomentar a linha abaixo e executar o docker-compose.yml
navegador = webdriver.Remote('http://selenium-chrome:4444/wd/hub', options=option)



Conclusão

O selenium é uma ferramenta extremamente versátil que permite automatizar diversas tarefas. A criatividade é o limite.

Github do projeto



Referências