Modulo 026 – Ambientes Virtuais

– Ambientes Virtuais – O que é um Ambiente Virtual?

Caso você goste de filmes/séries(SPOILER ALERT), imagine um ambiente virtual como o mundo do Show de Truman ou a cidade criada pela Wanda de WandaVision.
O que acontece nesses casos é que são criadas bolhas dentro do mundo real. Lá, as regras são outras, as condutas são outras sem a interferência do que está fora da bolha (mundo real).
O que isso significa em termos de programação e Python?
O ambiente virtual quando criado, não recebe por definição os programas instalados do seu computador(mundo externo), dentro desse ambiente, você poderá instalar outros programas, bibliotecas, até mesmo versões mais antigas do Python que só existirão dentro daquele ambiente.

Mesmo que se tenha por exemplo o Python 3.8 Instalado no seu computador, seu ambiente Virtual poderá rodar uma versão anterior.

– Navegando no Prompt de Comando


























Modulo 025 – Integração Python para Finanças

– Integração Python para Finanças

Atenção!! Este módulo não é sobre finanças ou mercado financeiro.
Nosso objetivo aqui é entender como interagir via Python com ferramentas, bases comumente utilizadas no mercado financeiro.
Essencialmente, o que veremos aqui são métodos ou bibliotecas já conhecidas aplicadas a essa realidade. Dito isso, vamos começar !
Como sempre vamos iniciar pela importação de bibliotecas que nos permitirão analisar dados de ativos financeiros.
As importações estão destacadas ao lado.

 import numpy as np 
 import pandas as pd 
 import matplotlib.pyplot as plt 
 import pandas_datareader.data as web 

Além do nosso bom e velho Pandas, vamos importar também pandas_datareader que nos permite ler dados da web (doc)

Para essa integração, usaremos o Yahoo Finance. Por isso, vai ser necessário conhecer a nomenclatura utilizada por esse site. Por exemplo, se queremos saber as cotações da IBOVESPA no Yahoo Finance iremos usar o código ^BVSP. Outro exemplo, são em casos de ações brasileiras como a ITUB4(nome original usado na Bovespa). No Yahoo Finance, utilizaremos ITUB4.SA.
Sabendo dessas informações, podemos usar nosso primeiro método do pandas_datareader:
.DataReader()
Esse método nos permite buscar os dados de cotação da web do período solicitado conforme apresentado ao lado.

 import numpy as np 
 import pandas as pd 
 import matplotlib.pyplot as plt 
 import pandas_datareader.data as web 
                                      
 cotacao_ibov = web.DataReader('^BVSP', data_source='yahoo', start='2020-1-1', end='2020-11-10')
 display(cotacao_ibov) 
_________________________________

• data_source: indica que será puxada do yahoo.
• start: início do período desejado;
• end: fim do período desejado.

Feito essa importação dos dados, podemos trata-los de acordo com nosso interesse. Para isso, usaremos as outras bibliotecas que foram importadas.
No exemplo ao lado fizemos um gráfico usando o matplotlib a partir dos dados da coluna ‘Adj Close’.

 cotacao_ibov['Adj Close'].plot(figsize=(15, 5)) 
________________________
 <AxesSubplot:xlabel='Date'> 


• Adj Close - Coluna a ser considerada para o gráfico.
• Figsize: permite ajustar o tamanho do gráfico criado.

– Retorno IBOV e Média Móvel

Tendo as informações extraídas no Yahoo Finance, podemos agora realizar diversas análises. Vamos começar por uma muito comum e bem simples. O cálculo do retorno da Bovespa para o período definido anteriormente.
Como queremos o retorno do período, vamos calcular o ganho percentual entre a cotação do último dia do período e o primeiro dia do período. O cálculo do retorno será dado por:

                   Ú𝑙𝑡𝑖𝑚𝑎 𝑐𝑜𝑡𝑎çã𝑜 𝑑𝑜 𝑝𝑒𝑟í𝑜𝑑𝑜
𝑅𝑒𝑡𝑜𝑟𝑛𝑜 = ______________________ _ 1
                   𝑃𝑟𝑖𝑚𝑒𝑖𝑟𝑎 𝑐𝑜𝑡𝑎çã𝑜 𝑑𝑜 𝑝𝑒𝑟í𝑜𝑑𝑜 
Para acessarmos a última cotação usaremos a posição [-1] da coluna [‘Adj Close’], já para a primeira cotação do período, usaremos a posição [0].

 retorno_ibov = cotacao_ibov['Adj Close'][-1] / cotacao_ibov['Adj Close'][0] - 1 
 print('Retorno de {:.2%}'.format(retorno_ibov)) 
____________________
 Retorno de -11.15% 

Calculado o retorno, vamos para outra análise muito comum pelos investidores de bolsa de valores. A Média Móvel. Para isso, usaremos o Pandas. Ao invés de definirmos uma fórmula, usaremos dois métodos já existentes dentro dessa biblioteca:
rolling().mean()
Ela nos permitirá definir as médias apenas informando o número de pontos que desejamos. Nesse caso, como cada ponto representa um dia, ao definirmos 21 no método rolling, estamos definindo 21 dias. Veja o exemplo ao lado, além do Pandas também utilizamos o Matplotlib para plotarmos no gráfico as médias móveis definidas por nós.

 #Média móvel da bolsa 
 cotacao_ibov['Adj Close'].plot(figsize=(15, 5), label='IBOV'
 cotacao_ibov['Adj Close'].rolling(21).mean().plot(label='MM21'
 cotacao_ibov['Adj Close'].rolling(34).mean().plot(label='MM34'
 plt.legend() 
 plt.show() 
_______________________

– Pegando Cotações Carteira com Python

Para esse exemplo vamos usar uma carteira de investimentos “Carteira do Lira” ( obviamente não é a real ☺ ). Nosso objetivo é criar um dataframe de todos os ativos da nossa carteira com as cotações do período indicado. Usaremos um pouco do conhecimento adquirido anteriormente nesse módulo, mas vamos precisar adicionar alguns outros elementos.
Para que o entendimento, fique mais fácil vamos dividir a explicação em X partes:
Passo 1 : Importar as bibliotecas e os dados da carteira contidos no arquivo “Carteira.xlsx”;
Passo 2 : Criar um dataframe vazio que receberá os ativos e as cotações “puxadas” do Yahoo Finance;
Passo 3 : Definir linha de código de preenchimento de apenas 1 dos ativos no Dataframe;
Passo 4: Usando o FOR, criar um código que preencha todos os ativos no dataframe criado.

Passo 1 : Importar as bibliotecas e os dados da carteira contidos no arquivo “Carteira.xlsx”;
Assim como nos exemplos anteriores deste módulo, usaremos o pandas.reader para a busca de informações no site do Yahoo Finance e o pandas para o tratamento dos dados dentro de um dataframe.
Além disso, usaremos posteriormente o numpy e matplotlib para elaboração de gráficos.
Como já vimos no módulo sobre PANDAS, para importarmos as informações de um Excel, usaremos o método .read_excel().
O exemplo ao lado, apresenta o código em Python para a conclusão do PASSO 1.

 import numpy as np 
 import pandas as pd 
 import matplotlib.pyplot as plt 
 import pandas_datareader.data as web 
             
 carteira = pd.read_excel('Carteira.xlsx'
 display(carteira) 
_____________________

Passo 2 : Criar um dataframe vazio que receberá os ativos e as cotações “puxadas” do Yahoo Finance; 
Esta é a linha menos intuitiva de todas, então vamos avaliá-la por partes. Se usarmos essencialmente o mesmo código utilizado anteriormente, conseguimos buscas as cotações, mas além disso, também obtemos uma série de informações que não nos interessa por enquanto (high, low, open, close, volume).
De todas as informações apresentadas ao lado, apenas a última coluna nos interessa e além disso, pensando que vamos ter vários ativos no nosso dataframe, será importante renomeá-lo de acordo com o nome do ativo. Nesse caso ‘BOVA11.SA’.
Vamos entender como fazer essa etapa na próxima página ☺.

 cotacoes_carteira = pd.DataFrame() 
                    
 cotacoes_carteira = web.DataReader('BOVA11.SA', data_source='yahoo', start='2020-01-01', end='2020-11-10'
    
 display(cotacoes_carteira) 
_____________________

Passo 3 : Definir linha de código de preenchimento de apenas 1 dos ativos no Dataframe;
Para facilitar a visualização desta etapa, criamos uma variável ‘extracao’ que armazenará o dataframe apresentado anteriormente.
Como vimos, queremos que no nosso dataframe cotacoes_carteira exista uma coluna com o nome do ativo [‘BOVA11.SA’] mas que apenas a coluna [‘Adj Close’] seja utilizada.
O exemplo ao lado, apresenta como realizar esta etapa.

 cotacoes_carteira = pd.DataFrame() 
                    
 cotacoes_carteira = web.DataReader('BOVA11.SA', data_source='yahoo', start='2020-01-01', end='2020-11-10'
 cotacoes_carteira = web.DataReader['BOVA11.SA'] = extracao['Adj Close'
    
 display(cotacoes_carteira) 

 A T E N Ç Ã O ! 
Por fins didáticos, dividimos essa linha em 2 etapas, mas seria possível realizar essa etapa diretamente sem a necessidade da criação da variável extracao.

Passo 4: Usando o FOR, criar um código que preencha todos os ativos no dataframe criado.
Como temos vários ativos, podemos utilizar o FOR para percorrer todos esses ativos adicionando seus dados ao nosso dataframe cotações_carteira.

 cotacoes_carteira = pd.DataFrame() 
             
 for ativo in carteira['Ativos']:
     extracao = web.DataReader('{}.SA'.format(ativo), data_source='yahoo', start='2020-01-01', end='2020-11-10'
     cotacoes_carteiraátivo] = extracao['Adj Close'
    
 display(cotacoes_carteira)

• For permite percorrer toda lista de ativos existentes no dataframe carteira.
• Ao invés de utilizar o nome do ativo, é utilizada a variável ativo que possui o nome correspondente àquela iteração.

– Tratando Problemas de importação para o Dataframe e Normalização

Assim como vimos no módulo do Pandas, é sempre importante analisarmos a qualidade dos dados antes de iniciar a análise dos dados.
Um método já conhecido por nós que nos permite ter uma visão geral do dados é o método .info() conforme apresentado ao lado.
Podemos perceber que aparentemente todos os dados foram trazidos corretamente, com exceção do ativo XPLG11. Nesse caso temos apenas 176 dados não nulos enquanto os outros ativos, 210.
Possivelmente algum problema ocorreu na própria base do Yahoo Finance. Nesse caso, não temos muito o que fazer além de tratarmos esses dados faltantes usando alguma premissa.

 cotacoes_carteira.info() 
___________________________________
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 210 entries, 2020-01-02 to 2020-11-10
Data columns (total 14 columns):
 #   Column  Non-Null Count  Dtype  
---  ------  --------------  -----  
 0   BOVA11  210 non-null    float64
 1   SMAL11  210 non-null    float64
 2   MGLU3   210 non-null    float64
 3   BBDC4   210 non-null    float64
 4   ITUB4   210 non-null    float64
 5   ENEV3   210 non-null    float64
 6   MOVI3   210 non-null    float64
 7   BPAC11  210 non-null    float64
 8   GNDI3   210 non-null    float64
 9   NTCO3   210 non-null    float64
 10  BCRI11  210 non-null    float64
 11  VILG11  210 non-null    float64
 12  KNRI11  210 non-null    float64
 13  XPLG11  176 non-null    float64
dtypes: float64(14)
memory usage: 24.6 KB

• Valores faltantes no ativo XPLG11. Era esperado 210 assim como os outros ativos.

Para o ajuste destes dados faltantes, poderíamos usar algumas premissas. Segue abaixo a listagem de algumas mais comuns :
Excluir dados faltantes;
Utilizar a média de todos ou uma dos valores;
Replicar o dado anterior existente mais próximo.
Não existe uma abordagem 100% correta, qualquer uma que venha a ser adotada será uma premissa utilizada e qual utilizar irá variar de projeto para projeto.
No nosso caso, usaremos o valor existente imediatamente anterior ao dado faltante. Ou seja, O valor da cotação do dia anterior ao do dado faltante.
Para isso, usaremos o método .ffill() que nos permite preencher os espaços vazios com os dados existentes na linha anterior.

 cotacoes_carteira = cotacoes_carteira.ffill() 
 cotacoes_carteira.info() 
____________________________
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 210 entries, 2020-01-02 to 2020-11-10
Data columns (total 14 columns):
 #   Column  Non-Null Count  Dtype  
---  ------  --------------  -----  
 0   BOVA11  210 non-null    float64
 1   SMAL11  210 non-null    float64
 2   MGLU3   210 non-null    float64
 3   BBDC4   210 non-null    float64
 4   ITUB4   210 non-null    float64
 5   ENEV3   210 non-null    float64
 6   MOVI3   210 non-null    float64
 7   BPAC11  210 non-null    float64
 8   GNDI3   210 non-null    float64
 9   NTCO3   210 non-null    float64
 10  BCRI11  210 non-null    float64
 11  VILG11  210 non-null    float64
 12  KNRI11  210 non-null    float64
 13  XPLG11  210 non-null    float64
dtypes: float64(14)
memory usage: 24.6 KB

• Apesar de não serem dados reais, a premissa nos permite igualar a quantidade de dados existentes.

Para conseguirmos analisar nossos ativos em um mesmo gráfico é interessante normalizarmos os valores.
O que isso significa? Vamos considerar o primeiro valor conhecido da nossa base de ativos como a linha de base. Todas as variações (positivas ou negativas) serão referencias a essa linha de base. Isso nos permitirá avaliar a evolução de todos os ativos em um mesmo gráfico independentemente do seus valores serem, em valores absolutos, muito distintos.
Como normalizar? Considerando nosso caso, vamos criar um novo dataframe que será:
          𝑉𝑎𝑙𝑜𝑟 𝑑𝑎 𝑐𝑜𝑡𝑎çã𝑜 𝑑𝑜 𝑑𝑖𝑎
_____________________________
𝑉𝑎𝑙𝑜𝑟 𝑑𝑎 𝑐𝑜𝑡𝑎çã𝑜 𝑑𝑜 1º 𝑑𝑖𝑎 𝑑𝑎 𝑏𝑎𝑠𝑒 𝑑𝑒 𝑑𝑎𝑑𝑜𝑠
Chamaremos esse novo dataframe de carteira_norm conforme apresentado ao lado.

 carteira_norm = cotacoes_carteira / cotacoes_carteira.iloc[0
 carteira_norm.plot(figsize=(15, 5)) 
 plt.legend(loc='upper left'
_____________________________

• Cotação do 1º dia. O iloc[0] significa que estamos pegando a primeira linha do nosso dataframe
• Os dados normalizados nos permitem ver a evolução em % dos ativos. Perceba que todos valores se iniciam com valor no eixo y = 1.
Sem a normalização a diferença entre valores absoluto dificultaria muito a análise conjunta em um único gráfico

– Criando Valor da Carteira e Puxando Ibovespa

A primeira parte é a mesma que já fizemos anteriormente. Puxar do Yahoo Finance usando o pandas.reader(definido como web nesse exemplo) para realizar a importação dos dados. Nosso objetivo é comparar a rentabilidade entre a Bovespa e nossa carteira. Já aprendemos como calcular essa rentabilidade anteriormente, mas consideramos que todos os ativos possuíam a mesma quantidade, o que dificilmente é realidade em um caso real.
Portanto, vamos precisar incorporar a quantidade dos ativos a nossa análise.
Para isso, vamos criar um novo dataframe chamado valor_investido conforme apresentado ao lado, onde a quantidade do ativo apresentada no dataframe carteira é multiplicada pelo valor da cotação do ativo no dataframe cotacoes_carteira.
Vamos entender um pouco melhor este código na próxima página

 cotacao_ibov = web.DataReader('^BVSP', data_source='yahoo', start='2020-01-01', end='2020-11-10'
 display(cotacao_ibov) 
_____________________

Vamos utilizar a mesma estrutura de for utilizada anteriormente para “preencher” nosso novo dataframe valor_investido. A parte que é menos intuitiva nesse caso é como buscar as informações do nosso dataframe carteira. Como podemos ver no extrato apresentado abaixo, a orientação do nosso dataframe é diferente. Os ativos não são colunas e sim parte dos dados que são apresentados em linhas.
Assim, usaremos o .loc para acessar os dados. A informação desejada, SEMPRE, estará na coluna Qtde, e o que nos permite chegar no valor certo da coluna e o nome do ativo. Assim, usaremos a estrutura abaixo para acessar os dados.

 valor_investido = pd.DataFrame() 
               
 for ativo in carteira['Ativos']:
     valor_investido[ativo] = cotacoes_carteira[ativo] * carteira.loc[carteira['Ativos']==ativo, 'Qtde'].values[0]
 display(valor_investido)

• carteira: nome do dataframe;
carteira[‘Ativos’]==ativo: o valor da coluna ‘Ativos’ do df carteira que for IGUAL ao valor de ativo nesta iteração do for;
• ‘Qtde’: Coluna que desejamos
• .values[0] = indica que queremos o valor do df conforme as condições dos itens anteriores.

– Comparando a Carteira com Ibovespa

Agora que temos o valor investido por carteira, vamos descobrir o valor total da carteira.
Para isso, vamos criar uma coluna de TOTAL no nosso dataframe valor_investido.
Vamos calculá-la utilizando o método .sum(). No entanto, esse método por padrão soma colunas e não linhas... Vamos precisar fornecer um argumento para especial para nosso método que nos permita somar as linhas que representarão o valor total da carteira/dia.
Esse argumento será axis=1.

 valor_investido['Total'] = valor_investido.sum(axis=1

• Criação de uma coluna [‘Total’] no dataframe valor_investido.
• axis=1 permite somar linhas ao invés de colunas (axis=0) que é a configuração padrão do método sum().

Criada nossa coluna Total, podemos replicar os conhecimentos das páginas anteriores realizando as etapas abaixo:
1) Normalizar valores para plotagem dos gráficos;
2) Plotar gráfico acrescentando as labels necessárias para identificação;
3) Utilizando a fórmula abaixo, calcular o retorno:
                  Ú𝑙𝑡𝑖𝑚𝑎 𝑐𝑜𝑡𝑎çã𝑜 𝑑𝑜 𝑝𝑒𝑟í𝑜𝑑𝑜
𝑅𝑒𝑡𝑜𝑟𝑛𝑜 =________________________ _ 1
                 𝑃𝑟𝑖𝑚𝑒𝑖𝑟𝑎 𝑐𝑜𝑡𝑎çã𝑜 𝑑𝑜 𝑝𝑒𝑟í𝑜𝑑𝑜
Após a realização das etapas acima teremos o gráfico apresentado ao lado assim como os retornos indicados na parte inferior.
Podemos perceber que os gráficos parecem relacionados e vamos aproveitar isso para aprender mais um método do PANDAS, o .corr().

 valor_investido['Total'] = valor_investido.sum(axis=1)

 valor_investido_norm = valor_investido / valor_investido.iloc[0]
 cotacao_ibov_norm = cotacao_ibov / cotacao_ibov.iloc[0]

 valor_investido_norm['Total'].plot(figsize=(15, 5), label='Carteira')
 cotacao_ibov_norm['Adj Close'].plot(label='IBOV')
 plt.legend()
 plt.show() 
_______________________________

 retorno_carteira = valor_investido['Total'][-1] /  valor_investido['Total'][0] - 1 
 retorno_ibov = cotacao_ibov['Adj Close'][-1] / cotacao_ibov['Adj  Close'][0] - 1 
 print('Retorno da Carteira: {:.2%}'.format(retorno_carteira)) 
 print('Retorno IBOV: {:.2%}'.format(retorno_ibov)) 
________________________
 Retorno da Carteira: 1.93% 
 Retorno IBOV: -11.15% 

Os valores de correlação, variam sempre entre -1 e 1. Valores próximos de 1 indicam que existe uma relação forte e diretamente proporcional, ou seja, se um índice sobe, o outro também sobe. Valores próximos de -1 indicam que existe uma relação forte mas inversamente proporcional, ou seja, se um índice sobe, o outro desce.
Na imagem ao lado apresentamos a correlação alcançada no nosso exemplo utilizando o método .corr().
Como já era esperado pela nossa análise gráfica, podemos ver que esta correlação é bastante forte e de proporcionalidade positiva.

 correlacao = valor_investido['Total'].corr(cotacao_ibov['Adj Close']) 
 print(correlacao) 
_____________________
 0.8879301020686045 

Modulo 024 – Integração Python com API e JSON

 – Integração Python com API e JSON – Python e Integrações de API

Antes de qualquer coisa... O que é uma API??
API é um conjunto de códigos que uma plataforma, um site, etc fornece para que outros códigos possam usá-los e garantir esse relacionamento de forma segura e precisa.
Nem todas plataformas, oferecem serviço de API, mas existem muitas disponíveis para uso. Veja o exemplo ao lado. Pegamos aqui a API do Youtube (link). Aqui, temos códigos já
disponibilizados pelo próprio youtube que nos auxiliam a executar esses comandos de forma segura.
Ao invés de desenvolvermos um código novo, simplesmente utilizamos a API.

Beleza, entendemos o que é uma API, vamos usar uma na prática.
Para esse exemplo, vamos usar uma API gratuita que nos fornecerá a cotação de moedas (dólar, euro, etc).
Nesse caso, não temos a necessidade de um login na API, então, podemos ir direto para a documentação da API e entender quais são as etapas a serem seguidas para conseguirmos a informação das cotações.
Conforme apresentado ao lado esses dados serão requisitados através do método GET e serão buscados através do link indicado. Essa comunicação pode ser feita em diversas “línguas” uma das mais comuns e quando estamos trabalhando com Python é a JSON.

GET Retorna todas as moedas (atualizado a cada 30 segundos)
Retorna a ultima ocorrência de todas as moedas

• GET - O QUE? - Informa que usaremos o método get para requisitar os dados da API.
• /jason - COMO? – Formatoque será utilizada na “comunicação” entre a API e seu programa. Nesse caso, no formato JSON.
• ONDE? - Endereço que vamos requisitar as informações

Vamos para o nosso código! Como já é rotina, vamos começar importando as bibliotecas serão necessárias. Quando estamos falando de APIs e Formato JSON, vamos utilizar 2 bibliotecas novas:
requests(doc) json(doc)
Primeiro vamos entender a requests. Conforme vimos na documentação da API usaremos o GET para requisitar os dados. No entanto, quando printamos o resultado armazenado na variável cotacoes temos:
<Response [200]>
Sempre que requisitamos dados temos uma resposta. Essa resposta possui um código 200 indica que a requisição foi bem sucedida.

 import requests 
 import json

 cotacoes = requests.get('https://economia.awesomeapi.com.br/json/all')
 print(cotacoes_dic)
_____________________
 <Response [200]> 

• Ao requisitarmos essa informação, temos como resposta Response [200] que significa que a requisição ocorreu corretamente.

Sabemos que a requisição está correta, agora precisamos acessar essa informação.
Para isso usaremos o JSON. Utilizando essa biblioteca poderemos acessar os dados e convertêlos em um dicionário Python.

 import requests 
 import json

 cotacoes = requests.get('https://economia.awesomeapi.com.br/json/all')
 cotacoes_dic = cotacoes.json()
 print(cotacoes_dic)
_____________________
 {'USD': {'code': 'USD', 'codein': 'BRL', 'name': 'Dólar Comercial', 'high': '5.4585', 'low': '5.3662', 'varBid': '-0.0245', 'pctChange': '-0.45', 'bid': '5.4331', 'ask': '5.4343', 'timestamp': '1605540818', 'create_date': '2020-11-16 12:33:39'}, 'USDT': {'code': 'USD', 'codein': 'BRLT', 'name': 'Dólar Turismo', 'high': '5.61', 'low': '5.5', 'varBid': '-0.035', 'pctChange': '-0.62', 'bid': '5.41', 'ask': '5.74', 'timestamp': '1605540240', 'create_date': '2020-11-16 12:24:43'}, 'CAD': {'code': 'CAD', 'codein': 'BRL', 'name': 'Dólar Canadense', 'high': '4.1729', 'low': '4.1014', 'varBid': '0.0008', 'pctChange': '0.02', 'bid': '4.1538', 'ask': '4.1557', 'timestamp': '1605540813', 'create_date': '2020-11-16 12:33:36'}, 'EUR': {'code': 'EUR', 'codein': 'BRL', 'name': 'Euro', 'high': '6.4775', 'low': '6.3551', 'varBid': '-0.0233', 'pctChange': '-0.36', 'bid': '6.4307', 'ask': '6.4342', 'timestamp': '1605540814', 'create_date': '2020-11-16 12:33:37'}, 'GBP': {'code': 'GBP', 'codein': 'BRL', 'name': 'Libra Esterlina', 'high': '7.2275', 'low': '7.0782', 'varBid': '-0.0289', 'pctChange': '-0.4', 'bid': '7.1637', 'ask': '7.169', 'timestamp': '1605540813', 'create_date': '2020-11-16 12:33:36'}, 'ARS': {'code': 'ARS', 'codein': 'BRL', 'name': 'Peso Argentino', 'high': '0.0684', 'low': '0.0673', 'varBid': '-0.0004', 'pctChange': '-0.66', 'bid': '0.0679', 'ask': '0.068', 'timestamp': '1605540818', 'create_date': '2020-11-16 12:33:39'}, 'BTC': {'code': 'BTC', 'codein': 'BRL', 'name': 'Bitcoin', 'high': '89500', 'low': '87351', 'varBid': '2138.6', 'pctChange': '2.45', 'bid': '89210', 'ask': '89496', 'timestamp': '1605540818', 'create_date': '2020-11-16 12:33:39'}, 'LTC': {'code': 'LTC', 'codein': 'BRL', 'name': 'Litecoin', 'high': '385.56', 'low': '338', 'varBid': '38.94', 'pctChange': '11.32', 'bid': '383.01', 'ask': '383.25', 'timestamp': '1605540815', 'create_date': '2020-11-16 12:33:36'}, 'JPY': {'code': 'JPY', 'codein': 'BRL', 'name': 'Iene Japonês', 'high': '0.05229', 'low': '0.05114', 'varBid': '-0.0002', 'pctChange': '-0.38', 'bid': '0.05194', 'ask': '0.05197', 'timestamp': '1605540818', 'create_date': '2020-11-16 12:33:39'}, 'CHF': {'code': 'CHF', 'codein': 'BRL', 'name': 'Franco Suíço', 'high': '5.9992', 'low': '5.8718', 'varBid': '-0.0237', 'pctChange': '-0.4', 'bid': '5.9522', 'ask': '5.9554', 'timestamp': '1605540814', 'create_date': '2020-11-16 12:33:36'}, 'AUD': {'code': 'AUD', 'codein': 'BRL', 'name': 'Dólar Australiano', 'high': '3.9888', 'low': '3.9188', 'varBid': '0.0121', 'pctChange': '0.31', 'bid': '3.9702', 'ask': '3.9718', 'timestamp': '1605540817', 'create_date': '2020-11-16 12:33:39'}, 'CNY': {'code': 'CNY', 'codein': 'BRL', 'name': 'Yuan Chinês', 'high': '0.8307', 'low': '0.8147', 'varBid': '-0.0009', 'pctChange': '-0.11', 'bid': '0.8251', 'ask': '0.8255', 'timestamp': '1605540784', 'create_date': '2020-11-16 12:33:06'}, 'ILS': {'code': 'ILS', 'codein': 'BRL', 'name': 'Novo Shekel Israelense', 'high': '1.6277', 'low': '1.5976', 'varBid': '-0.0005', 'pctChange': '-0.03', 'bid': '1.6197', 'ask': '1.6204', 'timestamp': '1605540786', 'create_date': '2020-11-16 12:33:07'}, 'ETH': {'code': 'ETH', 'codein': 'BRL', 'name': 'Ethereum', 'high': '2500', 'low': '2500', 'varBid': '0', 'pctChange': '0', 'bid': '1460.01', 'ask': '2815.86', 'timestamp': '1605484806', 'create_date': '2020-11-15 21:00:06'}, 'XRP': {'code': 'XRP', 'codein': 'BRL', 'name': 'Ripple', 'high': '1.54', 'low': '1.46', 'varBid': '0.04', 'pctChange': '2.77', 'bid': '1.53', 'ask': '1.54', 'timestamp': '1605540805', 'create_date': '2020-11-16 12:33:26'}} 

– API de Cotação de Moeda

Como vimos no exemplo anterior, o resultado da nossa requisição é um dicionário.
Se olharmos esse dicionário com um pouco mais detalhe, vamos perceber que cada moeda é uma chave deste dicionário.
Se nosso objetivo é conseguir a cotação do dólar (USD), podemos acessar nosso dicionário. Como não conhecemos essa API, antes de irmos para o código, vamos dar uma olhada em sua documentação para entendermos as nomenclaturas utilizadas pela API.

• Usando a documentação da API podemos saber o nome da moeda e qual a chave que devemos utilizar para acessar a cotação.

 print('Dólar: {}'.format(cotacoes_dic['USD']['bid'])) 
 print('Euro: {}'.format(cotacoes_dic['EUR']['bid'])) 
 print('Bitcoin: {}'.format(cotacoes_dic['BTC']['bid'])) 
_______________________
 Dólar: 5.4331
 Euro: 6.4307
 Bitcoin: 89210

• Aqui temos um dicionário dentro de um dicionário. Para o primeiro, identificamos a MOEDA(‘BTC) depois, identificamos a INFORMAÇÃO daquela moeda que queremos(‘bid’).

 A T E N Ç Ã O ! 
Nessa API específica, os valores estarão sempre sendo atualizados, portanto, o valor indicado aqui provavelmente será diferente do valor conseguido por você ☺

Vamos dizer que temos interesse em pegar não só a cotação de hoje, mas dos últimos 30 dias? Como fazer? O primeiro passo, é ler a documentação da API e tentar entender se essa API nos oferece essa opção.
Nesse caso, temos essa opção, o que facilita nosso trabalho. Caso não houvesse, teríamos que programar com os dados disponíveis. MAS como temos, vamos entender como acessar esses dados no print ao lado.

GET Retorna todas as moedas (atualizado a cada 30 segundos)

https://economia.awesomeapi.com.br/jason/daily/USD-BRL/30

• :moeda/:numero_dias - Indica que moeda deverá ser substituído pelo código da moeda; Indica que número de dias será substituído por um número inteiro (integer).
• Aqui estamos pegando os dados de conversão (‘USD–BRL’) dos últimos (’30’) dias.

 cotacoes_dolar30d = requests.get('https://economia.awesomeapi.com.br/json/daily/USD-BRL/30')
 cotacoes_dolar_dic = cotacoes_dolar30d.json()

 lista_cotacoes_dolar = [float(item['bid']) for item in  cotacoes_dolar_dic]
 print(lista_cotacoes_dolar)
________________
 [5.4393, 5.4582, 5.4588, 5.4581, 5.391, 5.4147, 5.3858, 5.3647, 5.3612, 5.525, 5.6635, 5.756, 5.7425, 5.7416, 5.7769, 5.7538, 5.7054, 5.624, 5.617, 5.6175, 5.5918, 5.6031, 5.6053, 5.6107, 5.6453, 5.6445, 5.6096, 5.5949, 5.5691, 5.5316]

• List comprehension, inserindo o valor da cotação na lista_cotações_dólar como float, por se tratarem de números.
• For percorre todo o dicionário disponibilizado pela API.

– Mais exercícios de API com Cotação de Moeda

Nosso objetivo agora será pegar as informações do BitCoin de Jan/20 a Out/20 e plotarmos um gráfico com essas informações. Como fizemos anteriormente, vamos verificar na documentação da nossa API se é possível requisitar essas informações diretamente. Como podemos ver ao lado é possível requisitar e é isso que iremos fazer.
Perceba que o link de requisição possui um número maior de parâmetros, mas todos eles estão listados abaixo na própria API
Basta substituir no link as informações conforme as orientações da API. E é isso que iremos fazer no próximo slide.

 cotacoes_btc =  requests.get('https://economia.awesomeapi.com.br/json/daily/BTC-BRL/200?start_date=20200101&end_date=20201031')
 cotacoes_btc_dic = cotacoes_btc.json()
 lista_cotacoes_btc = [float(item['bid']) for item in cotacoes_btc_dic]

• BTC-BRL: Indica a moeda desejada.
• 200: Indica a quantidade de dados que desejamos.
• 20200101: Indica que a data inicial desejada é 01/01/2020.
• List comprehension visando a criação de uma lista de cotações (lista_cotações_btc.
• 20201031: Indica que a final desejada é 31/10/2020.

As cotações são extraídas da API da mais atual para a mais antiga. Podemos “corrigir” essa informação usando o método .reverse() e ter a informação da mais antiga para a mais nova. Como apresentado abaixo:

 cotacoes_btc =  requests.get('https://economia.awesomeapi.com.br/json/daily/BTC-BRL/200?start_date=20200101&end_date=20201031')
 cotacoes_btc_dic = cotacoes_btc.json()
 lista_cotacoes_btc [float(item['bid']) for item in cotacoes_btc_dic]
 lista_cotacoes_btc.reverse()
 print(lista_cotacoes_btc)
 print(len(lista_cotacoes_btc))
____________________
 [35150.0, 37025.0, 36836.7, 37415.0, 37158.0, 36652.1, 36800.0, 38000.1, 40050.0, 41050.0, 41212.0, 41715.0, 43392.0, 43070.0, 46424.7, 46610.0, 47626.0, 47900.0, 48553.0, 48852.0, 49700.0, 52500.0, 57700.0, 52609.1, 52499.0, 49225.0, 49700.0, 51488.8, 54450.0, 56208.0, 53609.0, 54207.4, 55300.0, 55651.1, 55760.8, 54831.8, 51440.0, 51400.0, 51600.0, 49560.0, 49735.0, 47625.1, 49000.2, 51700.3, 50650.0, 51500.0, 50865.1, 53600.0, 54001.0, 49500.4, 50400.6, 48800.4, 48820.6, 49133.5, 48096.8, 48201.0, 49350.0, 47000.0, 48100.1, 47788.9, 47750.0, 48501.4, 49679.0, 49290.6, 50405.0, 49700.0, 49750.0, 49782.0, 50710.0, 49759.1, 49800.0, 49755.0, 49915.1, 49678.2, 49746.8, 49840.0, 49960.0, 49800.0, 49208.8, 48815.5, 48993.1, 48850.0, 49890.0, 49900.1, 50360.1, 49890.0, 49905.9, 49750.0, 49920.0, 50041.3, 50073.4, 49868.0, 49320.0, 49702.1, 49651.8, 49680.0, 49516.5, 49143.0, 49321.0, 49850.0, 49951.1, 50400.2, 50402.0, 55300.0, 56161.0, 57490.0, 57330.0, 58950.0, 61298.1, 58296.3, 59800.0, 59951.0, 61902.2, 63302.0, 63140.0, 63715.0, 63700.0, 65303.8, 62300.0, 63120.0, 63210.3, 63905.0, 64280.0, 64270.3, 67501.0, 66453.3, 65800.0, 66655.0, 65657.4, 66112.0, 66100.0, 66360.9, 63606.0, 64655.2, 63599.9, 63016.2, 62700.0, 63350.9, 64200.0, 64900.0, 61939.0, 55336.6, 56500.0, 54555.7, 55550.3, 55102.2, 54348.3, 55059.1, 55511.0, 55821.2, 55856.7, 55566.0, 56908.9, 57700.0, 58250.0, 57807.2, 59285.0, 59750.0, 59100.0, 57050.6, 57880.5, 57884.0, 59501.1, 59845.0, 59720.5, 59638.4, 60600.1, 60995.0, 60950.1, 60390.7, 60512.5, 60018.1, 60569.2, 60210.3, 59801.0, 60265.0, 61211.5, 61960.0, 62747.2, 62701.0, 63558.3, 63601.7, 64100.6, 65000.0, 64400.0, 64500.0, 64950.1, 66000.3, 66952.4, 71401.0, 72251.2, 72202.4, 73300.0, 73200.0, 73685.5, 77888.1, 76550.1, 77950.2, 78101.0, 79401.1]
200 

Em posse dessa lista, podemos utilizá-la na elaboração de um gráfico mostrando a evolução da cotação do bitcoin para o período solicitado.

 import matplotlib.pyplot as plt 

 plt.figure(figsize=(15, 5))
 plt.plot(lista_cotacoes_btc)
 plt.show()
___________________________

– API com Login - Envio de SMS com Python e Twilio

Vamos usar agora uma API que necessita de um cadastro anterior.
O cadastro é bem direto e pode ser feito diretamente pelo site do Twilio.
Feito o cadastro, vamos dar uma olhada na documentação da API para entendermos como vamos usá-la para enviar SMS via Python.
Lendo a API, vemos que 2 informações são necessárias e ainda não as possuímos.
Vamos então descobrir onde identifica-las no próximo slide.

 from twilio.rest import Client 

 # Your account SID from twilio.com/console
 account_sid = 'AC274236461c28f62d429961289af45b82'
 # Your auth Token from twilio.com/console
 token = "your_auth_token"

 client = Client(account_sid, token)

 message = client.messages.create(
     to="destino"
     from_="remetente",
     body="Hello from python!")

 print(message.sid)

• Precisamos encontrar o nosso account_sid.
• Precisamos encontrar o nosso token de autenticação.

Na aba Dashboard do Twilio, podemos encontrar o account SID e o Auth Token.
Por motivos de segurança censuramos parte do auth number do pobre coitado que está fazendo essa apostila. Sem a censura, já sabemos que muitos SMS serão magicamente enviados .
Em posse dessas informações, vamos para o nosso código desenvolver o código conforme indicado na documentação da API do Twilio.

 from twilio.rest import Client 

 account_sid = 'AC274236461c28f62d429961289af45b82'
 token = '6a2d1ea365d3674c749ce4cb7367d823'

 client = Client(account_sid, token)

Outra informação que precisamos coletar no site do Twilio é o número de telefone que será utilizado para envio dos SMS.
Para isso, basta clicar na opção Trial number e confirmar. O Twilio lhe dará um número como apresentado ao lado.

 from twilio.rest import Client 

 # Your account SID from twilio.com/console
 account_sid = 'AC274236461c28f62d429961289af45b82'
 # Your auth Token from twilio.com/console
 token = "your_auth_token"

 client = Client(account_sid, token)

 message = client.messages.create(
     to="+18126153399"
     from_="+5521972795556",

 from twilio.rest import Client 

 account_sid = 'AC274236461c28f62d429961289af45b82'
 token = '6a2d1ea365d3674c749ce4cb7367d823'

 client = Client(account_sid, token)

 remetente = '+18126153399'
 destino = '+5521972795556'

Por fim é só escrevermos nossa mensagem e enviar. Antes de rodar o código, verifique se a biblioteca do twilio está instalada. Caso não esteja, assim como já fizemos outras vezes, basta usar o :
pip install twilio

 from twilio.rest import Client 

 account_sid = 'AC274236461c28f62d429961289af45b82'
 token = '6a2d1ea365d3674c749ce4cb7367d823'

 client = Client(account_sid, token)

 remetente = '+18126153399'
 destino = '+5521972795556'

 message = client.messages.create(
     to=destino, 
     from_=remetente,
     body="Coe, é o Lira aqui!")

 print(message.sid)

Modulo 023 – Integração Python – Automação Web (Parte 2)

 – Pegando Informações de Elementos dentro de Elementos

Nessa aula vamos percorrer todas as imagens dos cursos que estão na página e extrair o link para onde essas imagem nos redirecionam.
Para selecionar as imagens dos cursos temos que procurar algum atributo como ID, Classe, que pareça único desse tipo de imagem e que se repita em todas as imagens. E você também deve se perguntar aonde está o link que você quer extrair. Nós sabemos que o link está em <a> que é parent de <img>. Em <a> também não tem nenhum atributo que se repita em todas as outras imagens. Então podemos analisar os parents de <a> que são <figure> e <div>. <figure> não é uma tag muito comum e se repete nas outras imagens, e
<div> possui a classe “wp-block-image” e também se repete nas outras imagens.

Estas 2 são boas opções, mas neste exemplo vamos testar com a tag <figure>. Vamos pegar todas as tags <figure> do site.

 lista_elementos = navegador.find_elements(By.TAG_NAME, "Figure"
 print(len(lista_elementos)) 
____________________
 6 

Todos os elementos com a tag <figure> são selecionados e armazenados na lista lista_elementos. Para saber se essa lista é a ideal para o nosso caso, devemos verificar se o tamanho dela é igual a quantidade de imagens nas quais estamos interessados. O tamanho é 6, então ela é perfeita. Agora precisamos extrair o link que está na tag <a> de cada imagem, além disso sabemos também que a tag <a> é child de <figure>. Para isso, primeiro temos que percorrer essa lista.

 lista_elementos = navegador.find_elements(By.TAG_NAME, "Figure") #Lista de figures 
 for elemento in lista_elementos: 
    link = elemento.find_element(By.TAG_NAME, "a").get_attribute("href) 
    print(link) 

• Usando o .find_element em um elemento, ele só irá fazer sua busca dentro do elemento, enquanto que usando o .find_element no navegador sua busca será na página inteira.
Essa linha de código pega o atributo href da tag <a> que está dentro do elemento percorrido.
• Retornou um erro, porque não foi possível extrair o link da última imagem. Não achou o elemento <a>.

Não foi encontrado o elemento <a> na imagem do powerpoint impressionador, como podemos ver abaixo. Ou seja, a imagem está sem link.
Para contornar o erro, podemos usar o try e o except.

 lista_elementos = navegador.find_elements(By.TAG_NAME, "Figure"#Lista de figures 
 for elemento in lista_elementos: 
    try
        link = elemento.find_element(By.TAG_NAME, "a").get_attribute("href) 
    print(link) 
    except
        continue 

• Usando o try e o except, ele vai tentar pegar o link, mas se alguma das imagens estiver sem link, ele vai pular e passar para o próximo.

– Preenchendo formulários com o Selenium (botões e caixas de seleção)

Nesta aula vamos começar a usar o selenium para interagir com formulários em site. Para isso, vamos pegar uma página que tem a maioria dos tipos de formulários e aprender a interagir com cada elemento.
• O arquivo “Preenchendo Formularios.ipynb” e “formulario.html” devem estar na mesma pasta.

Na parte inicial do nosso código temos os códigos abaixo para configurar o Selenium e acessar o formulário com o qual queremos interagir.

 from selenium import webdriver 
 from selenium.webdriver.chrome.service import Service 
 from webdriver_manager.chrome import ChromeDriverManager 
 from selenium.webdriver.common.by import By 
                                 
 servico = Service(ChromeDriverManager().install()) 
 navegador = webdriver.Chrome(service=servico) 

• Inicializa o nosso navegador do Selenium

 import os 
              
 caminho = os.getcwd() 
 arquivo = caminho + r"\formulario.html" 
 navegador.get(arquivo) 

Usa o caminho do arquivo que estamos utilizando (Preenchendo Formularios.ipynb) para abrir o arquivo formulario.html.
Nesta aula vamos começar a usar o selenium para interagir com formulários em site. Para isso, vamos pegar uma página que tem a maioria dos tipos de formulários e aprender a interagir com cada elemento.
Nesta primeira parte vamos interagir com o botão “clique em mim” usando o método que já vimos anteriormente .click(). Clicando em inspecionar, podemos ver que a maioria dos elementos não possui classe nem ID para selecionarmos, então vamos usar o XPATH como método de seleção para todos os elementos.

Agora vamos clicar no primeiro botão.

 navegador.find_element(By.XPATH, '/html/body/form/input[1]').click() 

Após rodar o código, ele clicou no botão e esse botão
disparou um alerta, um pop-up. Você pode interagir com esse pop-up, clicando em
OK, alguns pop-ups você também pode clicar em CANCELAR.
Por enquanto vamos clicar em OK usando o Selenium.

 navegador.find_element(By.XPATH, '/html/body/form/input[1]').click() 
 alerta = navegador.switch_to.alert 
 alerta.accept() 

• Nos dá como resposta o pop-up (alerta).
• Aceita o alerta que aparece quando clicamos no botão “Clique em mim”.
• switch_to manda o navegador alternar para um frame, ou nova aba ou alerta. Nesse caso, estamos alternando para um alerta.

Com esse código, ele clica no botão e logo depois confirma o alerta. Isso acontece tão rápido que é muito provável que quando você for no seu navegador, o alerta não esteja mais lá.

Agora vamos ver alguns botões com características diferentes das características desse primeiro botão. Alguns desses botões são o checkbox e o radiobutton. O checkbox permite selecionar vários deles ao mesmo tempo enquanto que o radio button só permite selecionar 1 opção por vez.

Esses e outros botões que veremos são diferentes porque além de clicar neles ou preencher com alguma informação, é possível também extrair informações desses botões. Para extrairmos as informações dos botões usaremos os 3 argumentos:
• .text
• .get_attribute(“value”)
• .is_selected()
Vamos ver como funciona com os checkboxes.
Vamos copiar o XPATH do nosso segundo checkbox para clicarmos nele.

 # clicar no botão 
 navegador.find_element(By.XPATH, '/html/body/form/input[2]').click() 

 # verificar o valor do botão 
 valor = navegador.find_element(By.XPATH, '/html/body/form/input[2]').is_selected() 
 print(valor) 
____________________
 True 

• Verifica se o botão está selecionado, em caso positivo retorna True, e se não estiver selecionado retorna False.

Cada vez que você clicar no botão, o estado dele mudará. Você pode fazer isso também
para o primeiro checkbox, basta copiar o XPATH dele e usar no seu código.

– Campos de Texto Personalizado e Datas

Agora vamos continuar a nossa interação com o formulário a partir de onde paramos na última aula. Vamos ver agora como funciona um campo de texto padrão. Por exemplo o campo:
Qual seu time? ___________    <input type="text"> == $0 

Vamos copiar o XPATH desse elemento e preencher com a palavra “Vasco”.

 # preencher 
 navegador.find_element(By.XPATH, '/html/body/form/input[16]').send_keys("Vasco"

Vamos extrair o valor que está dentro desse campo (input)

 valor = navegador.find_element(By.XPATH, '/html/body/form/input[16]').get_attribute("value"
 print(valor) 
________________
 Vasco 

Você pode se perguntar por que retornou o valor exato se não estou vendo o atributo “value” no código html deste elemento. Para os elementos <input>, usar .get_attribute(“value”) extrai o valor dentro deles. O input nada mais é que um elemento de um formulário que permite a entrada de dados por parte do usuário, e ele pode aparecer de diversas formas como checkbox, radio button, campo de texto, etc. Lembrando que nos botões de seleção não usamos .get_attribute(“value”), mas sim .is_selected() para saber se o botão está selecionado ou não.

Agora vamos adaptar isso para o nosso botão de seleção de cores.
Selecione o vermelho por RGB 232 33 33
Vamos copiar o XPATH e verificar qual cor foi selecionada

 # verificar qual a cor foi selecionada 
 valor = navegador.find_element(By.XPATH, '/html/body/form/input[4]').get_attribute("value"
 print(valor) 
____________________
 #894d4d 

• Código hexadecimal da cor – É o código da cor selecionada no padrão hexadecimal.

Podemos ver que para preencher este elemento devemos passar o código hexadecimal de uma cor. Vamos testar com #3145DD que é um tom de azul.

 # preencher a cor 
 navegador.find_element(By.XPATH, '/html/body/form/input[4]').send_keys('#3145DD'

Você também pode usar um conversor online de RGB para HEX. Fazendo a conversão de RGB 232 33 33 para HEX é #e82121

 # preencher a cor 
 navegador.find_element(By.XPATH, '/html/body/form/input[4]').send_keys('#E82121'

Alguns botões você precisará visualizar em que formato eles estão exibindo a informação e preencher de acordo com esse formato. Um exemplo disso é o botão de data.
Qual é o aniversario da sua cidade? dd/mm/aaaa   <input type="date"> flex == $0 

Por exemplo, vamos copiar o XPATH desse elemento e passar a data 15/02/1994 para ele.

 navegador.find_element(By.XPATH, '/html/body/form/input[6]').send_keys('15/02/1994'

O importante é você tentar identificar que tipo de formato cada input aceita. Para isso você precisa testar e depois verificar se a informação foi preenchida corretamente, caso contrário teste outro formato.

 # pegar o valor 
 valor = navegador.find_element(By.XPATH, '/html/body/form/input[6]').get_attribute("value"
 print(valor) 
___________________
 1994-02-15 

Perceba que o formato de preenchimento é dd/mm/aaaa enquanto que o formato na hora de pegar o valor do input é aaaa-mm-dd
Se passarmos o formato que obtivemos ao pegar o valor (aaaa-mm-dd) e tentarmos preencher esse input, será que funciona? Nesse caso não funciona

– Campos com Várias Informações e de Arquivos

Na última aula fizemos o preenchimento de um campo de data. E se quiséssemos preencher um campo com data e horário específico? Como faríamos?

Que dia e que horas você nasceu? dd/mm/aaaa --:--   <input type="datetime-local"> flex == $0 

O primeiro passo é você selecionar uma data e um horário, e verificar o formato em que ficaram as informações neste campo. Porque provavelmente esse é o formato que você terá que usar quando for preencher este campo. Agora vamos copiar o XPATH deste input e tentar preencher este campo.

Que dia e que horas você nasceu? 08/03/2022 21:33

 # preenchendo 
 navegador.find_element(By.XPATH, '/html/body/form/input[7]').send_keys('15/02/1994 14:15'

Que dia e que horas você nasceu? 15/02/1994 21:33  

Podemos perceber que somente a data foi modificada, o horário não foi alterado. Na verdade existem 2 informações dentro desse campo, e não apenas uma. Então teremos que preencher 2 informações. Para isso vamos usar a tecla TAB.

 # preenchendo 
 from selenium.webdriver.common.keys import Keys 
                  
 navegador.find_element(By.XPATH, '/html/body/form/input[7]').send_keys('17/10/1994', Keys.TAB, '23:50'

Que dia e que horas você nasceu? 17/10/1994 23:50 

• Permite apertar uma tecla do seu teclado em um campo específico

Para pegar o valor desse campo, teremos que fazer como na imagem abaixo.

 # pegando o valor 
 valor = navegador.find_element(By.XPATH, '/html/body/form/input[7]').get_attribute("value"
 print(valor) 
_________________________
 1994-10-17T23:50 

Agora vamos ver como funciona o campo de anexar o arquivo.
"Nenhum arquivo selecionado"   <input type="file"> == $0 

 # pegando o valor 
 valor = navegador.find_element(By.XPATH, '/html/body/form/input[8]').get_attribute("value"
 print(valor) 

• Como não tem nenhum arquivo selecionado, não printou nenhum valor.

A partir do momento que um arquivo é selecionado, o nome desse arquivo aparece do lado do botão. Vamos ver qual o valor que está armazenado nele.

 # pegando o valor 
 valor = navegador.find_element(By.XPATH, '/html/body/form/input[8]').get_attribute("value"
 print(valor) 
_________________________
 C:\fakepath\formulario.html 

Agora vamos preencher o campo de anexar arquivo.
Escolher Arquivo Calendario.pdf

 # pegando o valor 
 navegador.find_element(By.XPATH, '/html/body/form/input[8]').send_keys(r'C:\Users\Joaol\Downloads\Calendario.pdf') 

Outra forma de preencher esse campo é como no código abaixo.

 # preenchendo 
 caminho = os.getcwd() 
 arquivo = caminho + r"\formulario.html" 
               
 navegador.find_element(By.XPATH, '/html/body/form/input[8]').send_keys(arquivo) 

Escolher Arquivo formulario.html

 # pegando o valor 
 valor = navegador.find_element(By.XPATH, '/html/body/form/input[8]').get_attribute("value"
 print(valor) 
_________________________
 C:\fakepath\formulario.html 

• fakepath aparece no caminho, porque o navegador não armazena no site o caminho
do seu computador, ele só armazena o nome do arquivo.

– Exercitando em outros campos

Nesta aula vamos continuar preenchendo os campos do nosso formulário.
Selecione um mês e um ano ----- de ----   <input type="month"> flex == $0 
Selecione um mês e um ano junho de 2022 

Vamos começar preenchendo os campos que faltam! Primeiro selecionamos uma data para verificar o formato, e depois de copiar o XPATH dele, vamos tentar preencher esse campo com o mesmo formato.

 navegador.find_element(By.XPATH, '/html/body/form/input[9]').send_keys('janeiro de 1980'

Selecione um mês e um ano janeiro de 2022

Aconteceu o mesmo problema que tinha acontecido com o campo de data e hora. Ele preencheu o primeiro valor, mas não preencheu o segundo valor. Provavelmente teremos que usar a tecla TAB para modificar o segundo valor.

 navegador.find_element(By.XPATH, '/html/body/form/input[9]').send_keys('janeiro', Keys.TAB, '1980'

Selecione um mês e um ano janeiro de 1980

O valor foi preenchido corretamente. Agora vamos pegar o valor desse campo.

 # pegando o valor 
 valor = navegador.find_element(By.XPATH, '/html/body/form/input[9]').get_attribute("value"
 print(valor) 
_________________________
 1980-01 

• Perceba que o formato do valor que pegamos é (aaaa-mm)

Agora vamos ver alguns campos padrões de texto, mas com características específicas. O próximo campo só aceita números.

Só inputs numéricos aqui ______   <input type="number"> == $0 

Vamos copiar o XPATH desse elemento e depois preencher esse campo.

 navegador.find_element(By.XPATH, '/html/body/form/input[10]').send_keys("123456"

Como podemos ver, o valor foi preenchido corretamente. Um método muito útil que serve também para os outros campos é o .clear() que serve para você limpar o campo de informações que foram preenchidas anteriormente. Você pode usar esse método para garantir que um determinado campo esteja limpo antes de você inserir novas informações.

 navegador.find_element(By.XPATH, '/html/body/form/input[10]').clear() 

O próximo campo é o campo de senha.

Cuidado para não revelar sua senha! ______   <input type="password"> == $0 

Vamos copiar o XPATH desse elemento e depois preencher esse campo.

 # preencher 
 navegador.find_element(By.XPATH, '/html/body/form/input[11]').send_keys("123456"

Como podemos ver, o campo foi preenchido.
 ****** 

Agora vamos pegar o valor desse campo.

 # pego o valor 
 valor = navegador.find_element(By.XPATH, '/html/body/form/input[11]').get_attribute('value')
 print(valor) 
________________
 123456 

Podemos ver que o valor que pegamos foi o mesmo valor que preenchemos o campo.

O próximo botão é o radio button. O procedimento para usar esse botão é o mesmo de usar o checkbox.

Com Radio buttons só é possível escolher uma  opção por vez, selecione a opção do meio 〇〇〇  <input type="radioname="01"> == $0 

Vamos copiar o XPATH do terceiro botão e depois clicar nele.

 navegador.find_element(By.XPATH, '/html/body/form/input[14]').click()  ◯◯⚫

Um erro que pode acontecer quando você tentar selecionar um radio button é ele não selecionar o botão mesmo o seu código estando correto. Quando isso acontecer, reinicie o seu navegador e tente rodar o seu código novamente. Provavelmente isto irá resolver o problema. Relembrando que o método .is_selected() verifica o estado do botão, se ele está selecionado ou não. Podemos ver ao lado que somente o terceiro botão está selecionado.

#Verificando se os botões estão selecionados 
#botão 1 
 navegador.find_element(By.XPATH, '/html/body/form/input[12]').is_selected() 
_________________
 False 

#botão 2 
 navegador.find_element(By.XPATH, '/html/body/form/input[13]').is_selected() 
_________________
 False 

#botão 3 
 navegador.find_element(By.XPATH, '/html/body/form/input[14]').is_selected() 
_________________
 True 

O próximo campo é o de horas. Vamos selecionar uma hora qualquer para verificar qual o formato desse campo.
Que horas são? 23:17   <input type="time"> flex == $0 

Vamos copiar o XPATH desse campo para tentar preenchê-lo.

 navegador.find_element(By.XPATH, '/html/body/form/input[17]').send_keys('15:15'

Que horas são? 15:15

Vamos agora para o campo da semana. Vamos selecionar uma semana qualquer para verificar qual o formato do campo.

Semana? Semana 11, 2022   <input type="week"> flex == $0 

Vamos copiar o XPATH desse campo para tentar preenchê-lo.

 navegador.find_element(By.XPATH, '/html/body/form/input[18]').send_keys('Semana 17', '2005'

Podemos ver que não conseguimos preencher esse campo com esse formato. Vamos tentar outro formato.

 navegador.find_element(By.XPATH, '/html/body/form/input[18]').send_keys('17, 2005'

Só foi preenchida a semana, o ano não foi preenchido. Provavelmente precisaremos de uma tecla TAB para preencher.

 navegador.find_element(By.XPATH, '/html/body/form/input[18]').send_keys('17', keys.TAB, '2005'

Também não funcionou. Vamos testar agora sem o TAB.

 navegador.find_element(By.XPATH, '/html/body/form/input[18]').send_keys('17', '2005'

Semana? Semana 17, 2005

Agora funcionou. É muito importante você testar um formato diferente quando o formato que você estiver usando não der certo, porque isso vai te deixar mais independente, e quando você encontrar um campo diferente, você saberá avaliar uma forma de preencher esse campo.
Agora vamos ver um bloco de texto. Vamos preencher este campo para verificar o formato e vamos também copiar o XPATH dele.

Olá
Meu nome é Lira
Ta aprendendo python?

 <textarea id="story" name="story" rows="5" cols="33"></textarea> == $0 

 navegador.find_element(By.XPATH, '//*[@id="story"]').clear() 
 navegador.find_element(By.XPATH, '//*[@id="story"]').send_keys("Olá", Keys.ENTER, 'Meu nome é Lira', Keys.ENTER, 'Value, Tmj'

– Campos de Arrastar

Agora vamos ver como fazer para editar os campos de slider.

 <input type="rangemin="0max="100"> == $0 

O slider (range) pode variar de 0 a 100, como podemos ver. O primeiro passo é copiar o XPATH desse elemento para mostrar como pegar o valor desse campo.

 # pegar o valor 
 valor = navegador.find_element(By.XPATH, '/html/body/form/input[15]').get_attribute('value'
 print(valor) 
___________________
 50 

Se movermos o slider para perto do final, esse valor será muito próximo de 100. Se movermos totalmente para o final, será 100. Mas se movermos totalmente para o início, o valor será zero.

E se usarmos o método .clear() no slider, o que acontece?

 elemento = navegador.find_element(By.XPATH, '/html/body/form/input[15]'
 elemento.clear() 

 # pegar o valor 
 valor = navegador.find_element(By.XPATH, '/html/body/form/input[15]').get_attribute('value'
 print(valor) 
___________________
 50 

Quando usamos o método .clear() no slider, a posição do slider volta à posição padrão que é o meio (50). Agora teremos que mover o slider para a posição 70. Se você mexer a seta do seu teclado, o slider se move de 1 em 1. Podemos usar o método .clear() antes de mover o slider, para garantir que a posição inicial do slider seja sempre 50. E o número de vezes que precisamos pressionar a seta do teclado para mover o slider é igual a diferença entre a posição desejada e a posição inicial do slider.
Vamos fazer isso com auxílio do for.

 # preencher o valor 
 elemento = navegador.find_element(By.XPATH, '/html/body/form/input[15]'
              
 elemento.clear() #Garante que a posição inicial do slider é 50
 for i in range(70 - 50): 
     elemento.send_keys(Keys.ARROW_RIGHT) 

Nesse caso, para ir para da posição 50 para 70, precisamos pressionar a seta para a direita do teclado, por isso ARROW_RIGHT

– Campos de Lista de Valores

Nesta aula vamos aprender como trabalhar com os dropdowns (lista de valores). Essas listas são listas que a princípio não tem um valor específico, que precisa que você clique nela e escolha uma opção.

 <select> == $0 
     <option value="a">A</option> 
     <option value="b">B</option> 
     <option value="c">C</option> 
 /<select> 

No caso dessa lista, no código da página já temos as 3 opções. Porém em listas dinâmicas, as opções só irão aparecer ao clicar na lista. Vamos copiar o XPATH desse elemento para selecioná-lo. Vamos também tentar enviar um valor a esse elemento.

 # preencher o valor 
 navegador.find_element(By.XPATH, '/html/body/form/select[1]').send_keys('C'

• Podemos ver que a letra C foi selecionada.
• Mostra o valor da opção selecionada, nesse caso letra C.

 # pegando o valor 
 valor = navegador.find_element(By.XPATH, '/html/body/form/select[1]').get_attribute('value')
print(valor) 
__________
 c 

Quando a lista for uma lista de formulário, o .send_keys() vai funcionar. Mas nem toda lista é de formulário, e para esses casos você terá que clicar e selecionar a opção dentro dessa lista. Vamos ver como fazer isso.

 # clicando para selecionar 
 navegador.find_element(By.XPATH, '/html/body/form/select[1]').click() 

Quando clicamos no elemento, ele abre a lista de opções. Pode ser que você não consiga visualizar essa lista aberta, pois ao mudar de página, ela se fecha. Dado que a lista está aberta, agora você pode selecionar um dos 3 itens.

 <select> == $0 
     <option value="a">A</option> 
     <option value="b">B</option> 
     <option value="c">C</option> 
 /<select> 

Agora que a lista está aberta, para selecionar uma opção devemos copiar o XPATH da opção que queremos.

 # selecionando manualmente 
 import time 
 navegador.find_element(By.XPATH, '/html/body/form/select[1]').click()
time.sleep(0.5) #espera meio segundo 
 navegador.find_element(By.XPATH, '/html/body/form/select[1]/option[3]').click() 

O que esse código faz é clicar na lista, então a lista é aberta, espera meio segundo, e então seleciona a opção 3 (letra C).

– Usando o Select e discussão sobre erros no Selenium

Na aula passada aprendemos 2 métodos de como interagir com listas suspensas (dropdowns), usando o .send_keys() e o .click(). Nesta aula veremos como interagir com essas listas usando o Select.

 <select> == $0 
     <option value="a">A</option> 
     <option value="b">B</option> 
     <option value="c">C</option> 
 /<select> 

A lista suspensa com a qual estávamos trabalhando na aula passada e vamos trabalhar nessa aula é um elemento do tipo <select>. Nem todo elemento do tipo <select> será possível interagir através dos métodos que aprendemos até aqui. Pensando nisso, o Selenium criou uma forma específica de interagir com elementos desse tipo.
Vamos ver como selecionar a lista suspensa usando essa forma.

 from selenium.webdriver.support.select import Select 
                  
 elemento = navegador.find_element(By.TAG_NAME, 'select'
 elemento_select = Select(elemento) 

• Importa o Select.
• Usamos o .find_element para selecionar o elemento pela tag <select>, porque sabemos que só existe 1 elemento desse na página, e porque esse método é para elementos do tipo <select>.
• Aplicamos a classe Select ao elemento. E agora conseguimos interagir com o elemento_select através de métodos diferentes.

Por exemplo, vamos usar alguns desses métodos e ver o que acontece.
1) .select_by_index()

 elemento_select.select_by_index(0

O .select_by_index() seleciona o elemento pelo índice. Nesse caso, o índice zero, referente ao primeiro elemento da lista (letra A).

 elemento_select.select_by_index(1

Nesse caso, selecionamos pelo índice 1, referente ao segundo elemento da lista (letra B).

 elemento_select.select_by_index(2

Nesse caso, selecionamos pelo índice 2, referente ao terceiro elemento da lista (letra C).

Podemos também usar outras formas de seleção como .select_by_value() e .select_by_visible_text(). E é importante saber que o valor de um elemento não é necessariamente o texto que está aparecendo para você, por isso existem esses 2 métodos diferentes.

 <select> == $0 
     <option value="a">A</option> 
     <option value="b">B</option> 
     <option value="c">C</option> 
 /<select> 

Nesse caso, o texto visível está com letra maiúscula enquanto que o valor do elemento está com letra minúscula.
Por exemplo, vamos usar alguns desses métodos e ver o que acontece.

 elemento_select.select_by_value('a'

O .select_by_value() seleciona o elemento pelo valor do elemento. Nesse caso, o valor ‘a’, referente ao elemento de letra A.

 elemento_select.select_by_value('b'

Nesse caso, selecionamos o valor ‘b’, referente ao elemento de letra B.

 elemento_select.select_by_value('c'

Nesse caso, selecionamos o valor ‘c’, referente ao elemento de letra C.

3) .select_by_visible_text()

 elemento_select.select_by_visible_text('A'

O .select_by_visible_text() seleciona o elemento pelo texto visível do elemento. Nesse caso, o texto ‘A’, referente ao elemento de letra A.

 elemento_select.select_by_visible_text('B'

Nesse caso, selecionamos o texto ‘B’, referente ao elemento de letra B.

 elemento_select.select_by_visible_text('C'

Nesse caso, selecionamos o texto ‘C’, referente ao elemento de letra C.

Nós estamos trabalhando com uma lista suspensa que permite a seleção de um único item, mas algumas listas suspensas permitem a seleção de mais de um item. Para esses casos existem alguns métodos que podem ser mais interessantes, como por exemplo:

Desmarca os itens selecionados
.deselect_all()
.deselect_by_index()
.deselect_by_value()
.deselect_by_visible_text()

 print(elemento_select.is_multiple) 
___________________
 none 

• Significa que não é um elemento múltiplo.
• O método .is_multiple verifica se esse é um elemento múltiplo, ou seja, se ele permite selecionar mais de um item.

Existem outros métodos também para verificar qual item foi selecionado dentro da lista.

 # ler o elemento selecionado 
 item = elemento_select.first_selected_option 
 print(item.get_attribute('value')) 
________________________
 a 

• .first_selected_option não retorna o valor do elemento selecionado. Retorna o próprio elemento que foi selecionado.
• A partir disso, podemos extrair o atributo desse elemento independentemente de quem ele for. Nesse caso extraímos o valor dele, que é ‘a’.

 # ler o item selecionado 
 lista_itens = elemento_select.all_selected_options 
 print(lista_itens) 
_________________
 [<selenium.webdriver.remote.webelement.WebElement (session="6c558e556921e135c0548455ed72e91d", element="e7fd38b5-e430-4bca-9935-943cde605748")>] 

• Retorna uma lista com todos os elementos selecionados, mas como a nossa lista suspensa permite selecionar apenas um elemento, será retornada uma lista com apenas 1 elemento.
• Lista com apenas 1 elemento.

A diferença desse método para o método anterior é basicamente a mesma diferença entre o .find_elements() e o .find_element(). Vamos ver abaixo como pegar o valor desse elemento.

 # ler o elemento selecionado 
 lista_itens = elemento_select.all_selected_options 
 print(lista_itens[0].get_attribute("value"))
__________________
 a 

Devemos lembrar que o método .all_selected_options nos retorna uma lista, e para pegar o valor dentro da lista devemos usar o nome da lista e o índice do elemento da lista, mesmo que a lista só contenha 1 único elemento.

 # ler o elemento selecionado 
 lista_itens = elemento_select.all_selected_options 
 print(lista_itens[0].text) 
__________________
 A 

– ActionChains e Dropdowns Especiais

Nessa aula vamos trabalhar com uma forma diferente de dropdown. Esse tipo de dropdown você pode encontrar em muitos sites, que é basicamente um dropdown simulado, diferente de um dropdown de formulário. Por exemplo:

 from selenium import webdriver 
 from selenium.webdriver.chrome.service import Service 
 from webdriver_manager.chrome import ChromeDriverManager 
 from selenium.webdriver.common.by import By 
               
 servico = Service(ChromeDriverManager().install()) 
 navegador = webdriver.Chrome(service=servico) 

 import os 
                 
 caminho = os.getcwd() 
 arquivo = caminho + r"\Pagina Hashtag.html" 
 navegador.get(arquivo) 

• Menu dropdown simulado. Esse menu aparece quando deixamos o mouse sobre o
botão “OUTROS CURSOS”. É diferente do dropdown de formulário.

Nesse caso, não podemos clicar em “outros cursos” para abrir a lista, e depois clicar na lista, pois se clicarmos em “outros cursos”, ele nos redirecionará para outra página.
Se quiséssemos, por exemplo, clicar em “Curso de SQL”, teríamos que pegar o mouse, passar em cima de “OUTROS CURSOS” e depois colocar em cima de “Curso de SQL” e aí clicar. Como ele é um dropdown simulado e tem um comportamento diferente, algumas das formas que aprendemos antes não irão funcionar. Mas nessa aula veremos o ActionChains que vai facilitar demais essa tarefa.

Como faríamos para selecionar o “Curso de SQL” normalmente?

• Botão OUTROS CURSOS com link associado a ele.
• <ul> é uma lista em html.
• Dentro da lista <ul>, temos as <li> que são os itens dessa lista. O primeiro item dessa lista é o elemento “Curso de SQL”.

Como estamos interessados em selecionar o elemento “Curso de SQL”, vamos copiar o XPATH dele e vamos tentar clicar.

 navegador.find_element(By.XPATH,'//*[@id="menu-item-17042"]/a').click() 
---------------------
 ElementNotInteractableException 

• Elemento não interagível, ou seja, ele encontrou o elemento, mas alguma coisa na página está nos impedindo de interagir com este elemento.

Nós não conseguimos clicar neste elemento. Mas você tem que se perguntar qual o seu objetivo com este elemento. Se o seu objetivo é clicar neste elemento para navegar para a página do Curso de SQL, você pode copiar o link desta página. Você pode perceber também que o link é um parâmetro href deste elemento, e como já selecionamos este elemento, podemos pegar o atributo href dele e navegar até o link associado a ele.

 link = navegador.find_element(By.XPATH,'//*[@id="menu-item-17042"]/a').get_attribute('href'
 navegador.ged(link) 

Essa é uma das opções, mas nem sempre o elemento que você está tentando clicar tem o atributo href. Nesse caso, precisamos pegar o mouse e colocar ele em cima do botão “OUTROS CURSOS” para desta forma a lista aparecer e o item “Curso de SQL” se tornar um
elemento interagível ou interactable. Para fazer isso, usaremos um elemento chamado ActionChains (documentação), que simula ações do seu mouse dentro do seu navegador, sem usar o seu mouse.

 from selenium import ActionChains 
            
 menu = navegador.find_element(By.XPATH,'//*[@id="menu-item-dropdown-16313"]/a'
 item = navegador.find_element(By.XPATH,'//*[@id="menu-item-17042"]/a'
            
 # colocar o mouse encima do menu 
 ActionChains(navegador).move_to_element(menu).perform() 
            
 # clicar no item 
 item.click() 

• Seu navegador como parâmetro.
• Ação que você quer simular. Nesse caso, mover o mouse até um elemento.
• Elemento no qual a ação será realizada. Nesse caso, menu.
• .perform() realiza a ação. E vem sempre no final.

Podemos ver que funcionou e que fomos redirecionados para a página do Curso de SQL. Em algumas páginas, após o ActionChains simular a ação de mover o mouse para determinado elemento, pode ser que demore um pouco para aparecer o menu. Nesse caso, podemos usar o time.sleep() entre os comandos de colocar o mouse em cima e o de clicar no item.

– Alertas no Selenium

Nessa aula, vamos aprender a trabalhar com alertas. Embaixo do vídeo dessa aula tem o link para baixar os arquivos necessários, que nesse caso é a página alertas.html. A parte inicial do código é bem parecida com o código das aulas anteriores, com a diferença de que agora estamos abrindo a página “alertas.html”.

Importações

 from selenium import webdriver 
 from selenium.webdriver.chrome.service import Service 
 from webdriver_manager.chrome import ChromeDriverManager 
 from selenium.webdriver.common.by import By 
               
 servico = Service(ChromeDriverManager().install()) 
 navegador = webdriver.Chrome(service=servico) 

Abrindo “alertas.html” que está na mesma pasta desse código

 import os 
                 
 caminho = os.getcwd() 
 arquivo = caminho + r"\alertas.html" 
 navegador.get(arquivo) 

Rodando esse código, a página “alertas.html” será aberta. Cada botão da página aciona um alerta, conforme mostrado abaixo.

É importante destacar a diferença entre um alerta e um pop-up. Um pop-up é um elemento da página que você consegue encontrar ao inspecionar a página. Já um alerta você não consegue inspecionar porque ele não é um elemento da página, mas sim do seu navegador.
Agora vamos interagir com os alertas. Para isso, vamos precisar copiar o XPATH de cada botão para clicar em cada um deles e fazer os alertas aparecerem. E depois, vamos ver como fazer a interação para cada tipo de alerta.

 # selecionar um alerta 
 navegador.find_element(By.XPATH, '/html/body/div[1]/input').click() 

# forma simples 
 alerta = navegador.switch_to.alert 
 alerta.accept() 

• O método .switch_to permite o navegador migrar para outros elementos como alerta, por exemplo. E com isso, você poderá interagir com esses elementos.
• Tipo de elemento para o qual o navegador migrará. Nesse caso, alerta.
• Confirma o alerta, clicando em OK.

 # forma "completa" 
 from selenium.webdriver.common.alert import Alert 
                 
 alerta = Alert(navegador) 
 alerta.accept() 

• Seu navegador como parâmetro, para que a função pegue o alerta do seu navegador.
• Confirma o alerta, clicando em OK.

Como você pode ver, existem duas formas de selecionar um alerta, a forma simples e a forma “completa”. As 2 formas funcionam, e você pode usar a forma que preferir.

2) Alerta de Confirmação

 navegador.find_element(By.XPATH, '/html/body/div[2]/input').click() 
                   
 alerta = Alert(navegador) 

Lembrando que você deve selecionar o alerta a cada alerta novo que surgir na página.

 # aceitar 
 alerta.accept() 

 # cancelar 
 alerta.dismiss() 

.accept() confirma o alerta.
.dismiss() cancela o alerta.
O que vai acontecer depois disso é o site que vai determinar.

Podemos também pegar o texto de um alerta, como podemos ver abaixo. Podemos usar esse mesmo alerta de confirmação clicando no botão dele para o alerta ser aberto.

 navegador.find_element(By.XPATH, '/html/body/div[2]/input').click() 
                        
 alerta = Alert(navegador) 
 texto = alerta.text 
 print(texto) 
________________________
 Quer confirmar a emissão da NF? 

3) Alerta de Input

 navegador.find_element(By.XPATH, '/html/body/div[2]/input').click() 
                   
 alerta = Alert(navegador) 

Preenche o input do Alerta

 alerta.send_keys('123123'

Não estamos vendo a informação que enviamos para o input do alerta ser preenchida.
Isso ocorre por causa de algum bug do Selenium para o Chrome ou do Chrome para o
Selenium. E como é um bug que não atrapalha o funcionamento do código, eles tiraram
a prioridade para a resolução desse erro.
Podemos ver ao lado que a informação que preenchemos usando o .send_keys() é a
mesma que foi exibida na página.

– Trabalhando com Diferentes Abas e Janelas

Nessa aula, vamos trabalhar com novas abas. Em algumas automações que vamos fazer, quando clicarmos em um link, esse link será aberto em uma nova aba ou em uma nova janela. E vamos ver como lidar com isso. A estrutura é parecida com a que fizemos na aula de alertas.
Lembrando que usaremos a página da hashtag que fizemos download dos arquivos dessa aula. E o código das importações é o mesmo da aula anterior.

 import os 
                 
 caminho = os.getcwd() 
 arquivo = caminho + r"\Pagina Hashitag.html" 
 navegador.get(arquivo) 

Ao abrir a página da hashtag no navegador, se clicarmos em um botão de algum curso, esse link será aberto em uma nova aba. Vamos copiar o XPATH desse botão para selecionarmos esse elemento.

 navegador.find_element(By.XPATH, '/html/body/section[2]/div/div[4]/figure/a/img').click() 

Vamos tentar preencher o campo Primeiro Nome do formulário da página do Power BI que acabou de abrir. Vamos selecionar esse elemento pelo name dele.

 <input type="textname="firtsnameplaceholder="Primeiro Nomerequired data="firstname"> == $0 

 # preenchendo o formulario 
                     
 navegador.find_element(By.ID, 'firstname').send_keys("Lira"
---------------------------------
 NoSuchElementException

Como podemos ver, o elemento não foi encontrado. Isso acontece porque por padrão o Selenium não muda de aba, ele continua olhando a aba original. Para resolver isso, antes de preencher o formulário precisamos mudar para a nova aba.

 aba_original = navegador.window_handles[0
 nova_aba = navegador.window_handles[1
 navegador.switch_to.window(nova_aba) 

.window_handles - Lista que tem todas as janelas abertas dentro do navegador que o Selenium está controlando. Os primeiros índices dessa lista correspondem às primeiras janelas abertas por ordem de abertura, ou seja, a primeira janela aberta é a de índice 0 (zero), e assim sucessivamente.

Como mudamos para a nova aba, agora conseguiremos preencher o formulário da página do Power BI.

 navegador.find_element(By.ID, 'firstname').send_keys("Lira"
 navegador.find_element(By.ID, 'email').send_keys("lira@lira.com"

E se quisermos mudar de volta para a aba original e clicar no botão Excel daquela página?

 navegador.switch_to.window(aba_original) 
 navegador.find_element(By.XPATH, '/html/body/section[2]/div/div[4]/figure/a/img').click() 

Funcionou! Agora podemos ver que estamos trabalhando com 3 abas diferentes dentro da nossa estrutura.

Se você estiver na dúvida em relação à ordem das suas abas, você pode fazer o seguinte:

 # ver os titulos de todas as abas 
 for aba in navegador.window_handles: 
     navegador.switch_to.window(aba) 
     print(navegador.title) 
_____________________________________________
 Todos os cursos Hashtag Treinamentos
 Curso de Power BI Avançado, Completo e Com Certificado!
 Curso de Exel Online Avançado, Completo e Com Certificado!

Com isso, vemos que a ordem é:
1ª Aba – Todos os Cursos (Aba Original) – Índice 0 (zero) da lista
2ª Aba – Curso de Power BI – Índice 1 da lista
3ª Aba – Curso de Excel – Índice 2 da lista

E se abrirmos um botão de algum curso em uma nova janela?

Apesar de ser uma nova janela, para o Selenium não vai mudar porque ele vai enxergar da mesma forma, como uma nova aba. É uma aba que está separada, mas isso não vai fazer diferença na forma como o Selenium irá enxergá-la.

Assim, a página do Curso de SQL será a 4ª aba, com índice 3 na lista

 abas = navegador.window_handles 
 print(len(abas)) 
_________________
 4 

E se quisermos preencher o formulário na página do SQL, como faremos?

 aba_sql = navegador.window_handles[3
 navegador.switch_to.window(aba_sql) 

 navegador.find_element(By.ID, 'firstname').send_keys("LiraSQL"
 navegador.find_element(By.ID, 'email').send_keys("sql@lira.com"

 <input type="textid="firtsname" name="firtsnameplaceholder="Primeiro Nomerequired data="firstname"> == $0 

 <input type="textid="email" name="emailplaceholder="Seu melhor e-mailrequired data="email"> == $0 

E como eu faço para fechar uma aba específica?

 # fechar a aba atualmente selecionada 
 navegador.close() 

E se eu quisesse fechar todas as abas ao mesmo tempo?

 # fechar todas as abas (navegador inteiro) 
 navegador.quit() 

– Como esperar uma informação carregar na tela

Nessa aula, vamos aprender a esperar um elemento aparecer dentro da nossa página usando o Selenium. Porque pode acontecer de um site carregar, mas algumas partes ainda não terem carregado. Normalmente, essas partes são carregadas por meio do Javascript alguns segundos depois da página ter sido carregada.
Como estamos trabalhando com o Selenium, e o padrão dele é somente esperar a página carregar, iremos utilizar alguns métodos para esperar também o carregamento de outros elementos.
Os métodos são:
1. WebDriverWait + ExpectedConditions (EC)
• Esse método é nativo do Selenium e espera até determinada condição acontecer por um determinado tempo.
• Menos linhas de códigos.
• Pode acontecer alguns bugs.
2. Loop de Espera
• Criação de uma espera “manual”.
• Nunca abandona.

O exemplo que faremos é dentro do site da hashtag. Se você esperar mais ou menos 7 segundos, um pop-up será aberto, como podemos ver na imagem abaixo.

 # criar o navegador 
 from selenium import webdriver 
 from selenium.webdriver.chrome.service import Service 
 from webdriver_manager.chrome import ChromeDriverManager 
 from selenium.webdriver.common.by import By 
                       
 servico = Service(ChromeDriverManager().install()) 
 navegador = webdriver.Chrome(service=servico) 

 navegador.get("https://www.hashtagtreinamentos.com/"

Porém, esse pop-up não aparece na hora que você entra na página. E se quisermos que o nosso código em python feche esse pop-up? Então vamos na página clicar com o botão direito do mouse, selecionar inspecionar, clicar na seta e selecionar o X do pop-up.

 <i class="eicon-close"> 
     ::before == $0 
 </i> 

 navegador.get("https://www.hashtagtreinamentos.com/"
 navegador.find_element(By.CLASS_NAME, 'eicon-close').click() 

Como rodamos o código que entra no site da hashtag e o código que clica no “X” do pop-up ao mesmo tempo, não deu tempo de o pop-up aparecer, e por isso apareceu uma mensagem de erro de que o elemento que tentamos selecionar e clicar não foi encontrado.

Como resolver isso então?
• Solução 1

 import time 
                 
 navegador.get("https://www.hashtagtreinamentos.com/"
 time.sleep(15
 navegador.find_element(By.CLASS_NAME, 'eicon-close').click() 
 print("Fechou"
___________________
 Fechou 

• Espera 15 segundos após entrar no site da hashtag, e depois clica no elemento. Funciona, mas se o elemento demorar menos do que 15 segundos para aparecer, você estará atrasando a velocidade do seu código.

• Solução 2

 # EC WebDriverWait 
 from selenium.webdriver.common.by import By 
 from selenium.webdriver.support.ui import WebDriverWait 
 from selenium.webdriver.support import expected_conditions as EC 
                   
 navegador.get("https://www.hashtagtreinamentos.com/"
             
 elemento = WebDriverWait(navegador, 30).until(EC.presence_of_element_located((By.CLASS_NAME, 'eicon-close')))
 time.sleep(1) # garantia 
 elemento.click() 
 print("Fechou"
___________________
 Fechou 

• A condição é a que o elemento que estamos procurando, apareça na página. E então, passamos para o EC (Expected Conditions) uma tupla com o método de seleção, que é pelo nome da classe.
• O time.sleep(1) espera 1 segundo antes de clicar para dar tempo de o elemento carregar por completo na página.
• O WebDriverWait possui 2 parâmetros: o seu navegador e o tempo máximo para a espera do elemento. Depois é passado o método .until(), que literalmente significa até. Ou seja, o navegador vai esperar no máximo 30 segundos até que uma condição aconteça.

• Solução 3

 # loop 
 navegador.get("https://www.hashtagtreinamentos.com/"
            
 while len(navegador.find_elements(By.CLASS_NAME, 'eicon-close')) == 0
     time.sleep(1

 time.sleep(1) # garantia 
 navegador.find_element(By.CLASS_NAME, 'eicon-close').click() 

 print("Fechou"
___________________
 Fechou 

• Como vimos nas aulas anteriores, o .find_elements() nos dá como resposta, uma lista de elementos. O while ficará testando se o tamanho da lista é igual a zero, ou seja, se o nosso elemento não apareceu. Se o elemento ainda não tiver aparecido, espera 1 segundo.
• Depois que o elemento tiver aparecido na página, espera 1 segundo para dar tempo de o elemento ser completamente carregado.

Esses foram os 3 métodos para esperar um elemento carregar na página.

– Printscreen com Selenium

Nessa aula, vamos aprender como tirar um print da sua tela com o Selenium. Existem 2 formas de print:
• Print da tela inteira
• Print de uma parte da tela
O print de uma parte da tela é na verdade um print da tela inteira, que depois é cortado em um tamanho menor, de acordo com as posições dos elementos que você quer tirar o print.
Lembrando que utilizaremos o mesmo código de importação que verifica a versão do ChromeDriver e abre o nosso navegador, e o mesmo código que abre a página da hashtag.

 from selenium import webdriver 
 from selenium.webdriver.chrome.service import Service 
 from webdriver_manager.chrome import ChromeDriverManager 
 from selenium.webdriver.common.by import By 
               
 servico = Service(ChromeDriverManager().install()) 
 navegador = webdriver.Chrome(service=servico) 

• Importações e configuração do navegador

 import os 
                 
 caminho = os.getcwd() 
 arquivo = caminho + r"\Pagina Hashtag.html" 
 navegador.get(arquivo) 

• Abrindo página da hashtag no navegador

O print sempre vai ser do que está aparecendo no seu navegador. Por exemplo, se você rolar a barra de rolagem para baixo, o seu print será diferente. Se você maximizar o seu navegador, o seu print também será diferente do anterior.
A forma de tirar o print é:

 navegador.save_screenshot("print.png"
__________________
 True 

print.png - Nome do arquivo, com a extensão de imagem. Nesse caso, será salvo como arquivo png. Se você quiser salvar como arquivo jpg, é só escrever: nome_do_arquivo.jpg.
Esse arquivo será salvo na mesma pasta do seu código. Caso você queira salvar em um
local diferente, é só passar o caminho completo do local junto ao nome do arquivo.

Para tirar print de uma parte da sua tela, como falado anteriormente, vamos cortar a imagem. Para isso, vamos precisar usar uma ferramenta de edição de imagem: OpenCV ou Pillow. Nessa aula iremos utilizar o Pillow.

 from PIL import Image 
                                  
 imagem = Image.open("print.png"
                                  
 imagem = imagem.crop() 
                                  
 imagem.save("print_pedaco.png"

• Importa Image da biblioteca PIL (Pillow).
• Abre o print que tiramos do navegador e armazena na variável imagem.
• Método .crop() que corta a imagem de acordo com os parâmetros passados. Nesse caso, o print será cortado e salvo na variável imagem.
• Salva a imagem no mesmo local do seu código com o nome “print_pedaço.png”.

Como faremos esse corte? E quais são os parâmetros do método .crop()? Para cortar uma imagem usando o .crop(), temos que passar uma tupla como parâmetro. Essa tupla deverá conter a posição de 2 pontos, que veremos na próxima página (círculos laranjas).

Podemos ver o ponto (0, 0) na imagem e ver que conforme avançamos para a direita, o nosso valor de x cresce, e conforme avançamos para baixo, o nosso valor de y cresce. Os círculos laranjas são os pontos que devemos passar para o método .crop() como parâmetro.
Assim fica .crop((x_inicial, y_inicial, x_final, y_final)). E para descobrir o valor do x_final e do y_final, faremos:

x_final = x_inicial + largura
y_final = y_inicial + altura

Vamos escolher um elemento no navegador para que possamos tirar um print desse elemento. Por exemplo, se quisermos tirar um print da barra de navegação? Vamos clicar com o botão direito do mouse, e selecionar inspecionar. Depois vamos clicar nos três pontinhos da direita, e em Dock side, selecionar a 3ª opção.
Pronto, modificamos a posição da barra porque assim fica mais fácil de visualizarmos o elemento que queremos.

 <header id="header" role="banner" class> == $0 

Vamos selecionar o elemento pelo seu ID e pegar a sua posição. Essa posição se refere ao (x_inicial, y_inicial), então sabemos que o x_inicial desse elemento é 0 (zero) e o y_inicial desse elemento também é 0 (zero).

 elemento = navegador,find_element(By.ID, 'header'
 posicao = elemento.location 
 print(posicao) 
____________________
 {'x': 0, 'y': 0} 

Isso faz sentido, já que podemos ver que o nosso elemento está começando no ponto (0, 0), que está indicado pelo círculo preto. Vamos pegar também o tamanho desse elemento.

 elemento = navegador,find_element(By.ID, 'header'
 tamanho = elemento.size 
 print(tamanho) 
____________________
 {'height': 146, 'width': 1019} 

Então temos 2 dicionários, o dicionário posição (com chaves x e y) e o dicionário tamanho (com chaves height e width).

Agora vamos descobrir quais são os valores que teremos que passar para o .crop() como parâmetro e como ficará a imagem cortada.

 from PIL import Image 
                                  
 imagem = Image.open("print.png"
                    
 elemento = navegador,find_element(By.ID, 'header'
 posicao = elemento.location 
 tamanho = elemento.size 
             
 x_inicial = posicao["x"
 y_inicial = posicao["y"
 x_final = x_inicial + tamanho["width"
 y_final = y_inicial + tamanho["height"
          
 imagem = imagem.crop((x_inicial, y_inicial, x_final, y_final)) 
 imagem.save("print_pedaco.png"

x_final = x_inicial + largura
y_final = y_inicial + altura
Tupla (x_inicial, y_incial, x_final, y_final)

Pronto! Vamos verificar como ficou o print e o print do pedaço.

Podemos ver na página anterior que o print do pedaço não ficou totalmente certo, pois cortou algumas partes da barra de navegação. Isso pode acontecer com você também, caso a escala do seu monitor esteja diferente de 100%.

Como essa é uma alteração de cálculo que faz tudo que está aparecendo na minha tela ficar com 125% de tamanho, os valores que “printamos” de tamanho e posição não condizem com o que está aparecendo na minha tela. Para resolver isso, existem 2 formas:
Colocar o valor da escala em 100% ou multiplicar os valores de tamanho e posição pelo valor da escala, que no meu caso é 125% (1.25).
Então multiplicaremos a escala (1.25, no meu caso) pelos valores: x_inicial, y_inicial, altura e largura, que foram os valores que pegamos do elemento. Fazendo essa alteração, o código fica:

 from PIL import Image 
                                  
 imagem = Image.open("print.png"
                    
 elemento = navegador,find_element(By.ID, 'header'
 posicao = elemento.location 
 tamanho = elemento.size 
             
 x_inicial = posicao["x"]*1.25 
 y_inicial = posicao["y"]*1.25 
 x_final = x_inicial + tamanho["width"]*1.25 
 y_final = y_inicial + tamanho["height"]*1.25 
          
 imagem = imagem.crop((x_inicial, y_inicial, x_final, y_final)) 
 imagem.save("print_pedaco.png"

Agora vamos verificar os prints novamente, após as alterações.

Podemos verificar que agora deu certo! Inclusive na imagem abaixo do print do pedaço, mostra a seleção do elemento ao clicar em inspecionar, e essa seleção mostra exatamente que o print do pedaço da tela está correto.

– Gerenciando a tela do Navegador

Agora nessa aula, vamos aprender a gerenciar a tela do nosso navegador: maximizar, minimizar e rodar o navegador de forma oculta (que chamamos de modo headless). O código padrão inicial de importações e abrir a página da hashtag é o mesmo.
Quando abrimos o nosso navegador, podemos perceber que ele nunca está maximizado. Como podemos maximizá-lo através do código? Para maximizar o navegador é só rodar o código abaixo:

 navegador.maximize_window() 

E como faço para minimizar o navegador?

 navegador.minimize_window() 

Lembrando que o minimizar não é clicar no botão de minimizar, mas sim o navegador voltar ao tamanho original de quando o abrimos. Mas caso você queira que o seu navegador rode de forma oculta, então você gostaria de utilizar o modo headless.

O que é o modo headless? O significado literal é “sem cabeça”, mas é um modo no qual o seu navegador executa o seu código de forma escondida, sem abrir o seu navegador. Para utilizar o modo headless, precisamos fazer algumas configurações.

 options = webdriver.ChromeOptions() 
 options.add_argument('--headless'
 novo_nav = webdriver.Chrome(service=servico, options=options) 
                         
 novo_nav.get("https://hashtagtreinamentos.com"
 print(novo_nav.title) 
__________________ 
 Hashtag Treinamentos | Torne-se uma referência em qualquer empresa 

• O .ChromeOptions() é uma classe no Selenium que permite manipular várias propriedades do ChromeDriver.
• Adiciona um argumento de linha de comando, que nesse caso é o ‘--headless’ (que deixa o seu navegador escondido). Esse argumento é aplicado no seu navegador.
• O argumento de palavra-chave options recebe a variável options, que indicará como o navegador será aberto.

Perceba que ele imprimiu o título do site da hashtag, mas não abriu nenhum navegador
Você pode pesquisar no google os argumentos que você pode adicionar além de “--headless”. Por exemplo, você pode pesquisar:
“selenium python como abrir o navegador com extensões desabilitadas”, e provavelmente você achará o “--disable-extensions”

 D I C A 
Construa todas as suas automações sem o modo headless. Porque você poderá ver o que está funcionando no seu código e o que não está, e com isso você poderá fazer os ajustes necessários. Depois disso, você poderá colocar o modo headless. Isso porque alguns sites se comportam de forma diferente no modo headless, e isso poderá impactar o funcionamento do seu código.

– Carregando um navegador com Cookies e Logins

Agora vamos ver como resolver um problema para quem quer automatizar envio de mensagens no WhatsApp ou algum serviço que você já tenha que estar logado para utilizá-lo. Para isso, precisaremos criar um perfil do Google Chrome por meio do nosso código. Assim que este perfil for criado, você poderá utilizá-lo para fazer login nas plataformas que você quiser, pois uma vez que você esteja logado nessas plataformas através desse perfil, você não precisará logar novamente nessas plataformas.
Para configurar o navegador, precisaremos do .ChromeOptions() que vimos na aula passada, que nos permite adicionar argumentos que serão aplicados no nosso navegador.

 from selenium import webdriver 
 from selenium.webdriver.chrome.service import Service 
 from webdriver_manager.chrome import ChromeDriverManager 
 from selenium.webdriver.common.by import By 
               
 servico = Service(ChromeDriverManager().install())
 options = webdriver.ChromeOptions()
 options.add_argument(r"user-data-dir=C:\Users\Felipe\AppData\Local\Google\Chrome\User Data\Defalt")
 navegador = webdriver.Chrome(service=servico, options=options) 

O argumento “user-data-dir” diz qual perfil do Chrome ele irá carregar junto ao caminho do local onde está armazenado este perfil. No meu caso, o caminho é o que está na imagem. Para saber o caminho do seu perfil é só digitar no Chrome sem aspas “chrome://version”, e na página que abrir você vai copiar o caminho que está ao lado de “Caminho de perfil”.

Vamos entrar agora no local que copiamos na página anterior.
• Repare que na pasta User Data, temos a pasta Default, e se você tiver outros perfis do Chrome já configurados, você verá pastas com um nome padrão, por exemplo “Profile1”, “Profile2”, “Profile3”, dependendo de quantos perfis já configurados você possuir.

Na pasta Default, temos todas as informações desse usuário como Contas, Cache, Preenchimento Automático, etc.

No caminho que copiamos no nosso código, nós temos o caminho da pasta User Data, mas esse caminho estava entrando dentro da pasta Default. Não queremos entrar na pasta Default, e no lugar de “Default” vamos escrever “Profile Selenium”. O “Profile Selenium” é um perfil que ainda não existe. Quando rodarmos esse código pela primeira vez, esse perfil será criado.

 from selenium import webdriver 
 from selenium.webdriver.chrome.service import Service 
 from webdriver_manager.chrome import ChromeDriverManager 
 from selenium.webdriver.common.by import By 
               
 servico = Service(ChromeDriverManager().install())
 options = webdriver.ChromeOptions()
 options.add_argument(r"user-data-dir=C:\Users\Felipe\AppData\Local\Google\Chrome\User Data\Profile Selenium")
 navegador = webdriver.Chrome(service=servico, options=options) 

 navegador.get("https://web.whatsapp.com"

• Podemos ver que agora o perfil “Profile Selenium” foi criado, e dentro do “Profile Selenium” estarão todas as informações que esse perfil for armazenando. Agora você terá que fazer login no seu WhatsApp, nas plataformas e ferramentas que você quiser.

Vamos executar todo o código, inclusive o código para ir para a página do WhatsApp. Vamos fazer login na nossa conta de WhatsApp também.
Pronto! Agora que conectamos à nossa conta de WhatsApp, vamos fechar o navegador e executar a primeira parte do nosso código novamente.

 from selenium import webdriver 
 from selenium.webdriver.chrome.service import Service 
 from webdriver_manager.chrome import ChromeDriverManager 
 from selenium.webdriver.common.by import By 
               
 servico = Service(ChromeDriverManager().install())
 options = webdriver.ChromeOptions()
 options.add_argument(r"user-data-dir=C:\Users\Felipe\AppData\Local\Google\Chrome\User Data\Profile Selenium")
 navegador = webdriver.Chrome(service=servico, options=options) 

• Podemos ver que o WhatsApp já está no nosso histórico de navegação

Vamos fechar o nosso navegador novamente. Agora vamos executar o nosso código mais uma vez, mas dessa vez vamos executar o código todo.

 from selenium import webdriver 
 from selenium.webdriver.chrome.service import Service 
 from webdriver_manager.chrome import ChromeDriverManager 
 from selenium.webdriver.common.by import By 
               
 servico = Service(ChromeDriverManager().install())
 options = webdriver.ChromeOptions()
 options.add_argument(r"user-data-dir=C:\Users\Felipe\AppData\Local\Google\Chrome\User Data\Profile Selenium")
 navegador = webdriver.Chrome(service=servico, options=options) 

 navegador.get("https://web.whatsapp.com"

Pronto! Nosso navegador conectou à nossa conta de WhatsApp, sem que precisássemos fazer o login novamente. A partir de agora nosso login ao WhatsApp está automatizado.
Quando carregamos um perfil, o nosso navegador demora um pouco mais para responder os primeiros comandos, porque todas as informações do perfil estão sendo carregadas e isso faz com que o navegador fique um pouco mais “pesado”, portanto não se preocupe
porque isso é normal.

– Executando Scripts em Javascript pelo Selenium (Scroll na tela)

Agora vamos aprender a usar o Selenium para executar comandos em Javascript dentro do nosso navegador. Mas por quê? Porque a estrutura de um site é feita em HTML e CSS, e a parte dinâmica dos sites é feita normalmente em Javascript. Rodar scripts em Javascript dentro do Selenium é importante porque nos permite fazer muito mais coisas. Por exemplo, suponhamos que a Hashtag pesquise “python” dentro do youtube e apareça como resultado uma lista de vídeos, e a Hashtag queira fazer propaganda em todos os vídeos de python do youtube. Quando arrastamos para baixo a barra de rolagem, percebemos que os vídeos que aparecem na lista não são carregados todos de uma vez, são carregados aos poucos conforme vamos descendo a barra de rolagem.
Se a Hashtag precisar pegar 50 vídeos, teremos que dar um scroll na página primeiro, depois esperar os vídeos serem carregados e aí sim, pegar o link dos vídeos. Então, nesse exemplo executaremos script para fazer exatamente isso.

 from selenium import webdriver 
 from selenium.webdriver.chrome.service import Service 
 from webdriver_manager.chrome import ChromeDriverManager 
 from selenium.webdriver.common.by import By 
 from selenium.webdriver.common.keys import Keys 
 import time

 servico = Service(ChromeDriverManager().install())
 navegador = webdriver.Chrome(service=servico)

 navegador.get("https://www.youtube.com")
 time.sleep(2)

Agora, vamos pesquisar “python” dentro do youtube. Para isso, vamos inspecionar a barra de busca do youtube, e vamos tentar selecionála e mandar a palavra “python” e a tecla Enter para fazer a busca.

 lista_inputs = navegador.find_elements(By.TAG_NAME, 'input'
 for elemento in lista_inputs: 
     if elemento.get_attribute("id") == "search"
         elemento.send_keys("python"
         elemento.send_keys("keys.ENTER") 
         break 
 time.sleep(5) 

Nesse código, estamos selecionando todos os elementos que possuem a tag input (mesma tag da barra de pesquisa) e os armazenando em uma lista. Percorremos os elementos dessa lista, testando se algum deles possui o atributo “id” igual a search. Em caso afirmativo, ele manda a palavra “python” para esse elemento, envia a tecla Enter, e depois sai do loop.

Agora, vamos extrair o link dos vídeos

• Podemos ver que o link que está dentro do elemento da imagem <img> é o endereço da imagem, e não o endereço do vídeo que estamos procurando. Quando isso acontecer, devemos procurar algum elemento próximo que tenha o atributo href.

Podemos ver que no elemento que achamos, seu id é “thumbnail”. Geralmente, o atributo id é único, mas nesse caso, todos os outros vídeos também possuem id igual a “thumbnail”. Então, em vez de pegarmos apenas um elemento, vamos pegar uma lista de elementos que possuem o mesmo id.

 lista_videos = navegador.find_elements(By.ID, 'thumbnail'
 for video in lista_videos: 
     print(video.get_attribute("href")) 

Podemos ver que na página anterior, o nosso código “printou” vários links. E se quisermos pegar muito mais links? Para isso, antes de executar o código que pega os links dos vídeos, vamos ter que dar scroll na página. E como fazer para dar scroll na página?

Para dar scroll na página, teremos que executar um comando em Javascript. E para isso, devemos fazer: navegador.execute_script(“”). E dentro dos parênteses e entre aspas devemos passar o comando em Javascript que queremos executar.

Agora, vamos clicar em inspecionar na página e clicar em Console.

 >window.skroll(0, 500) 

Esse comando em Javascript, window.scroll(x, y); Dá scroll na página para a posição que passarmos dentro dos parênteses. Onde X se refere à posição do scroll horizontal e
Y se refere à posição do scroll vertical. Nesse caso, o nosso comando dá scroll vertical para a posição 500.

E o que fazer para a nossa página sempre ficar arrastando para baixo? Teremos que colocar o nosso comando dentro de um loop e atualizarmos a posição que passaremos como parâmetro dentro do comando em Javascript.

 #dar scroll na tela
 import time
                  
 for i in range(15):
     qtde_scroll = i * 4000
     navegador.execute_script(f'window.scroll(0, {qtde_scroll})')
     time.sleep(2)
                 
 lista_videos = navegador.find_elements(By.ID, 'thumbnail')
               
 for video in lista_videos:
     print(video.get_attribute("href"))

• O time.sleep(2) é muito importante, porque espera o carregamento dos vídeos na página antes de dar o próximo scroll. Dessa forma, conseguimos pegar muito mais vídeos.

– Trabalhando com iFrames

Nessa aula, vamos trabalhar com IFrames dentro do Selenium. Um IFrame nada mais é que uma página dentro de outra página. É quando você quer pegar uma informação e colocar dentro da página, e essa informação está vindo de outra página.
Por que falar de IFrames? Porque às vezes você fará tudo certo no Selenium, mas de jeito nenhum seu código funcionará, porque o elemento não será encontrado. Se isso acontecer, talvez esse elemento esteja dentro de um IFrame.

Nesse nosso caso, o link que acessamos é um painel com jogos do dia, onde podemos ver uma tabela, que é um relatório do Power BI. O que queremos é acessar as informações dessa tabela. E se quisermos acessar “Pontos por Jogo Mandante” da 1ª linha da tabela, cujo valor é 2,20, como faremos?

Abaixo está o nosso código com as importações e configura configurações para acessar o site com o Selenium.

 from selenium import webdriver 
 from selenium.webdriver.chrome.service import Service 
 from webdriver_manager.chrome import ChromeDriverManager 
 from selenium.webdriver.common.by import By 
 from selenium.webdriver.common.keys import Keys 
 import time

 servico = Service(ChromeDriverManager().install())
 navegador = webdriver.Chrome(service=servico)

 link = "https://pbdatatrader.com.br/jogosdodia"

 navegador.get(link)
 time.sleep(7)

Como faríamos normalmente para selecionar o elemento no qual estamos interessados? Iríamos clicar em inspecionar a página, com a seta selecionaríamos o elemento, e copiaríamos o XPATH dele.

Agora, vamos tentar selecioná-lo pelo XPATH.

 texto = navegador.find_element(By.XPATH, '''//*[@id="pvExplorationHost"]/div/div/exploration/div/explore-canvas/div/div[2]/div/div[2]/div[2]/visual-container-repeat/visual-container[19]/transform/div/div[2]/div/visual-modern/div/div/div[2]/div[1]/div[4]/div/div[1]/div[8]''').text
 print(texto)
-----------------------
 NoSuchElementException

A mensagem de erro diz que o elemento não existe. Mas como? Se inspecionarmos o relatório do Power BI e clicarmos no elemento que estamos interessados, e depois subirmos buscando entender a hierarquia dos elementos na página, descobriremos que esse elemento está dentro de 2 IFrames.

O Selenium não consegue ler dentro de um IFrame, precisamos avisar ao Selenium para parar de olhar para a página principal e olhar para o IFrame. Já no nosso caso, teremos que falar para ele para olhar para o IFrame de fora, e depois olhar para o IFrame de dentro, e aí sim tentar selecionar o nosso elemento.

Como explicado na página anterior, entraremos nos 2 IFrames. Vamos selecionar o IFrame pelo nome da tag <iframe>. Importante lembrar que quando você entra em um IFrame, você não consegue mais pegar informações da página principal, a não ser que você volte para a página principal novamente.

 iframe = navegador.find_element(By.TAG_NAME, 'iframe')
 navegador.switch_to.frame(iframe)
         
 iframe = navegador.find_element(By.TAG_NAME, 'iframe')
 navegador.switch_to.frame(iframe)

 valor_xpath = '//*[@id="pvExplorationHost"]/div/div/exploration/div/explore-canvas/div/div[2]/div/div[2]/div[2]/visual-container-repeat/visual-container[19]/transform/div/div[2]/div/visual-modern/div/div/div[2]/div[1]/div[4]/div/div[1]/div[8]'
 texto = navegador.find_element(By.XPATH, valor_xpath).text
 print(texto)

Pronto! Agora conseguimos obter a informação do elemento que estávamos interessados. E se quisermos voltar à página principal?

 navegador.switch_to.defalt_content() 

Com esse código, você voltará à página principal! Com isso, você conseguirá selecionar os elementos da página principal novamente.