<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Lucas Cruz</title>
    <description>The latest articles on DEV Community by Lucas Cruz (@olucascruz).</description>
    <link>https://dev.to/olucascruz</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1176312%2F755ad178-566e-4b93-b0c8-13a591d55ef4.jpeg</url>
      <title>DEV Community: Lucas Cruz</title>
      <link>https://dev.to/olucascruz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/olucascruz"/>
    <language>en</language>
    <item>
      <title>Primeiros Passos com Databricks para Data Warehousing</title>
      <dc:creator>Lucas Cruz</dc:creator>
      <pubDate>Thu, 18 Sep 2025 18:53:19 +0000</pubDate>
      <link>https://dev.to/olucascruz/primeiros-passos-com-databricks-para-data-warehousing-4li7</link>
      <guid>https://dev.to/olucascruz/primeiros-passos-com-databricks-para-data-warehousing-4li7</guid>
      <description>&lt;p&gt;Anotações do curso de databricks provido pela por databricks academy - &lt;/p&gt;

&lt;p&gt;Databricks é uma plataforma de dados unificada e inteligente, que implementa o conceito de Lakehouse. A plataforma unifica o armazenamento de dados tanto brutos quanto estruturados, permite a transformação desses dados, com notebooks (que aceitam linguagens como python, scala e R) ou SQL.A plataforma também permite a criação de rotinas de dados e dashboards. Por fim ela tem diversos pontos que usam IA para execução de ações com dados.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sumário
&lt;/h2&gt;

&lt;p&gt;Ingestão de dados&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Componentes centrais da plataforma
-- Lakeflow
-- Databricks SQL
-- Mosaic AI
-Funcionalidades e para quem são destinadas
-Data warehousing
-- Explicação de 'nó de computação'
-- Arquitetura de medallion&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Ingestão de dados
&lt;/h2&gt;

&lt;p&gt;Formas de criar/ inserir dados no databricks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create table: Usando SQL &lt;/li&gt;
&lt;li&gt;Upload UI: Subir os dados pela interface&lt;/li&gt;
&lt;li&gt;Copy into: Usando a função de COPY do SQL&lt;/li&gt;
&lt;li&gt;Autoloader: Um processo de carregar dados de forma automatica de alguma fonte.&lt;/li&gt;
&lt;li&gt;Streaming tables: tabelas atualizadas em tempo real&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Componentes centrais
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Componentes centrais da plataforma: Lakeflow, Databricks SQL, AI/BI, Mosaic AI&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Lakeflow
&lt;/h2&gt;

&lt;p&gt;O Lakeflow tem três componentes principais: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;lakeflow connect que conecta com várias fontes de dados. &lt;/li&gt;
&lt;li&gt;Lakeflow DLT - (DLT, que significa Delta Live Tables, é uma funcionalidade do Databricks que simplifica a criação e o gerenciamento de pipelines de dados.)&lt;/li&gt;
&lt;li&gt;Lakeflow Jobs: Job = tarefa automatizada e agendada&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  O Databricks SQL
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Ferramenta para análise exploratória. &lt;/li&gt;
&lt;li&gt;O Databricks SQL, junto com os Dashboards, centraliza consultas e visualizações. A plataforma infunde essas ferramentas com IA através de recursos como o Databricks Assistant e o Genie&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  O Mosaic AI
&lt;/h2&gt;

&lt;p&gt;É uma ferramenta que oferece suporte end-to-end para IA tradicional e generativa.&lt;/p&gt;

&lt;h2&gt;
  
  
  Funcionalidades
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi2cnrpitfknsjb7yqpl1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi2cnrpitfknsjb7yqpl1.png" alt=" " width="800" height="364"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para equipe de dados o databricks fornece -&lt;br&gt;
Notebooks&lt;br&gt;
Editor SQL&lt;br&gt;
Assistente de IA para geração de código&lt;br&gt;
Metadados - Com descrição gerada por IA&lt;br&gt;
Sistema de busca de arquivos&lt;/p&gt;

&lt;p&gt;Para equipe de negocios&lt;/p&gt;

&lt;p&gt;IA/BI Dashboard - Espaço para geração de dashboards com ferramenta de IA&lt;br&gt;
IA/BI Genie - Espaço de chat conversasional com acesso a informação dos dados, pode-se "perguntar diretamente para os dados"&lt;/p&gt;

&lt;h2&gt;
  
  
  Data Warehousing
&lt;/h2&gt;

&lt;p&gt;Solução centralizada para Relatórios, Análises e insights&lt;/p&gt;

&lt;p&gt;SQL warehouses no databricks é um recurso computacional escalável e otimizado para executar SQL queries, análise de dados, criação de visualizações de dados.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fypt6eqfqfqm1lc1en5n5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fypt6eqfqfqm1lc1en5n5.png" alt=" " width="800" height="641"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cluster size:&lt;br&gt;
Refere-se ao poder computacional alocado ao SQL warehouse&lt;/p&gt;

&lt;p&gt;Expresso em "tamanhos de camiseta", como Pequeno (Small), Médio (Medium), Grande (Large) e Extra Grande (X-Large).&lt;/p&gt;

&lt;p&gt;Cada tamanho define o número de nós de computação e a capacidade para &lt;br&gt;
processamento paralelo.&lt;/p&gt;

&lt;p&gt;Scaling:&lt;br&gt;
Garante que o SQL Warehouse aloque recursos de forma adaptativa e dinâmica. &lt;br&gt;
Permitindo configurar o mínimo de clusters e o máximo&lt;br&gt;
Os benefícios são que um custo eficiente - Onde só se paga pelo que se usa&lt;br&gt;
E uma performance otimizada prevenindo gargalos.&lt;/p&gt;

&lt;p&gt;Um cluster é formado por um conjunto de nós de computação.&lt;/p&gt;

&lt;p&gt;Explicação sobre 'nó de computação'/'worker'&lt;/p&gt;

&lt;p&gt;Cada nó de computação é uma instância de servidor na nuvem&lt;br&gt;
Um ‘nó de computação’ é uma máquina virtual (VM) que possui um conjunto de recursos dedicados como CPU, Memória RAM, armazenamento, e em alguns casos GPU&lt;/p&gt;

&lt;p&gt;O gasto computacional é calculado com DBU - Databricks Unit&lt;/p&gt;

&lt;h2&gt;
  
  
  Arquitetura de Medallion
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;É recomendado que com databricks se use a arquitetura de Medallion&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3c0dapjlw1vwhcjp48uv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3c0dapjlw1vwhcjp48uv.png" alt=" " width="800" height="312"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Existem três camadas:&lt;/p&gt;

&lt;p&gt;Bronze - Dados brutos, sem tratamento, aqui temos uma cópia exata dos dados de origem.&lt;/p&gt;

&lt;p&gt;Prata - Dados tratados, limpos e organizados&lt;/p&gt;

&lt;p&gt;Ouro - Dados prontos para uso, em aplicativos, dashboard e etc. Preparados para a area de negócios já agrupados.&lt;/p&gt;

&lt;p&gt;A arquitetura de medallion pode ser considerada um padrão de projeto de dados.&lt;/p&gt;




&lt;p&gt;Para acessar o curso completo: &lt;a href="https://customer-academy.databricks.com/learn/courses/3603/get-started-with-databricks-for-data-warehousing?hash=42b6834df6bded2a210c444fa1982f59f1ec9831&amp;amp;generated_by=1192585" rel="noopener noreferrer"&gt;https://customer-academy.databricks.com/learn/courses/3603/get-started-with-databricks-for-data-warehousing?hash=42b6834df6bded2a210c444fa1982f59f1ec9831&amp;amp;generated_by=1192585&lt;/a&gt;&lt;/p&gt;

</description>
      <category>databricks</category>
      <category>cloud</category>
      <category>data</category>
      <category>learning</category>
    </item>
    <item>
      <title>Fundamentos arquitetura de soluções de Automação</title>
      <dc:creator>Lucas Cruz</dc:creator>
      <pubDate>Thu, 11 Sep 2025 15:38:27 +0000</pubDate>
      <link>https://dev.to/olucascruz/fundamentos-arquitetura-de-solucoes-de-automacao-39pe</link>
      <guid>https://dev.to/olucascruz/fundamentos-arquitetura-de-solucoes-de-automacao-39pe</guid>
      <description>&lt;p&gt;Nos meus estudos sobre arquitetura de soluções eu coletei algumas informações e aqui compartilho.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sumário:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Descrição da função&lt;/li&gt;
&lt;li&gt;Responsabilidades do arquiteto de soluções em cada etapa de um desenvolvimento de automação.&lt;/li&gt;
&lt;li&gt;Princípios de design da solução&lt;/li&gt;
&lt;li&gt;Referências &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Arquiteto de soluções
&lt;/h2&gt;

&lt;p&gt;Responsável por projetar a solução e garantir que seu desenvolvimento seja feito seguindo boas práticas&lt;/p&gt;

&lt;p&gt;Responsabilidade em cada etapa do processo de desenvolvimento da solução:&lt;/p&gt;

&lt;h3&gt;
  
  
  1 Início:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Avaliação da Declaração de Trabalho&lt;/li&gt;
&lt;li&gt;Exame do ambiente e infraestrutura existente&lt;/li&gt;
&lt;li&gt;Elaborar o rastreador de acesso de aplicativos junto com o gerente de projeto

&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2 Caso de Negócios e Validação Técnica:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Criar um Plano de Acesso de Aplicativo detalhado&lt;/li&gt;
&lt;li&gt;Estimativa de esforço do ponto de vista do desenvolvimento&lt;/li&gt;
&lt;li&gt;Auxiliar o Analista de Negócios na validação técnica de casos de uso selecionados: Identificando Dependências técnicas e Complexidades

&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3 Análise de Processos:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Contribuir e Revisar o PDD, que é um pré-requisito importante para o estágio de Design da Solução.&lt;/li&gt;
&lt;li&gt;Estimar as licenças necessárias para o desenvolvimento.&lt;/li&gt;
&lt;li&gt;Projetar o estado futuro da solução ("To-Be"). Ele fornece detalhes sobre o que está dentro e fora do escopo, desafios, gerenciamento de exceções, dados de entrada e saída.

&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4 Design da Solução
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Na etapa de Design da Solução, a equipe de implementação se concentra na criação do Documento de Design de Solução (SDD)&lt;/li&gt;
&lt;li&gt;Projetar e documentar a arquitetura de solução&lt;/li&gt;
&lt;li&gt;Criar o Plano de Testes Técnicos (TTP)&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  4.1 Documento de design de solução - SDD
&lt;/h4&gt;

&lt;p&gt;Documento formal que descreve os detalhes do projeto de solução.&lt;/p&gt;

&lt;p&gt;Deve conter: Visão geral do processo, Arquitetura da solução e diagramas de fluxo de processo integração com aplicativos e tecnologias, tratamento de erros e gerenciamento de exceções, e considerações sobre desempenho e escalabilidade.&lt;/p&gt;

&lt;p&gt;Objetivo: Roteiro de desenvolvimento, manutenção e melhorias, colaboração e trabalho em equipe e transferência de conhecimento.&lt;/p&gt;





&lt;h3&gt;
  
  
  5 Desenvolvimento e teste
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Orientar desenvolvimento&lt;/li&gt;
&lt;li&gt;Garantir altos padrões técnicos e a excelência geral da solução&lt;/li&gt;
&lt;li&gt;Realizar regularmente revisões de código para corrigir e melhorar o desempenho do processo.

&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  6 Teste de aceitação de usuário e hipercuidado
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Realizar revisões finais do código, de acordo com as mudanças necessárias durante o UAT.&lt;/li&gt;
&lt;li&gt;Documentar os resultados e registrar em log todos os bugs identificados durante os testes&lt;/li&gt;
&lt;li&gt;Hipercuidado é um período limitado imediatamente após a implantação de uma solução automatizada em produção, marcado pela atenção especial dada a cada processo executado&lt;/li&gt;
&lt;/ul&gt;





&lt;h2&gt;
  
  
  Princípios de design da solução.
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Evitar complexidade desnecessária
&lt;/li&gt;
&lt;li&gt;Escalabilidade&lt;/li&gt;
&lt;li&gt;Manutenibilidade
&lt;/li&gt;
&lt;li&gt;Modularidade&lt;/li&gt;
&lt;li&gt;Legibilidade
&lt;/li&gt;
&lt;li&gt;Confiabilidade&lt;/li&gt;
&lt;li&gt;Extensibilidade&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>arquiteturadesolucoes</category>
      <category>solutionarchitecture</category>
      <category>documentation</category>
    </item>
    <item>
      <title>RPA - Robotic Process Automation</title>
      <dc:creator>Lucas Cruz</dc:creator>
      <pubDate>Thu, 21 Aug 2025 21:09:33 +0000</pubDate>
      <link>https://dev.to/olucascruz/rpa-robotic-process-automation-b5d</link>
      <guid>https://dev.to/olucascruz/rpa-robotic-process-automation-b5d</guid>
      <description>&lt;h2&gt;
  
  
  O que é RPA?
&lt;/h2&gt;

&lt;p&gt;Um rpa - Processo de Automação Robótica - é um tipo de software feito para automatizar processos digitais&lt;/p&gt;

&lt;p&gt;Os processos mais indicados para serem automatizados:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;repetitivos&lt;/li&gt;
&lt;li&gt;De alto volume &lt;/li&gt;
&lt;li&gt;Que não exigem julgamento humano ou análise complexa.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tarefas comuns executadas por RPA:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;extrair dados&lt;/li&gt;
&lt;li&gt;preencher formulários&lt;/li&gt;
&lt;li&gt;mover arquivos&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Quais os tipos de RPA
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;RPA assistido:&lt;/strong&gt;&lt;br&gt;
Um rpa que é executado e acompanhado por uma pessoa, o rpa é executado na maquina que a pessoa usa.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RPA não assistido:&lt;/strong&gt;&lt;br&gt;
Um rpa que executa sem nenhuma interferência humana. Geralmente é executado em uma maquina dedicada.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quais os ganhos com RPA
&lt;/h2&gt;

&lt;p&gt;Reduz o tempo gasto em atividades de baixa complexidade que consomem muito tempo&lt;/p&gt;

&lt;p&gt;Arquitetura comum de soluções com RPA:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Desenvolvimento (Dev Studio): onde os processos são desenhados e testados&lt;/li&gt;
&lt;li&gt;Runner (Robô/Agent): executa os processos no ambiente de produção&lt;/li&gt;
&lt;li&gt;Orquestrador (Orchestrator): gerencia múltiplos robôs, agendamentos e monitoramento&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ferramentas para desenvolvimento de RPA:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Botcity &lt;/li&gt;
&lt;li&gt;UIPath&lt;/li&gt;
&lt;li&gt;Anywhere&lt;/li&gt;
&lt;li&gt;Blue Prism&lt;/li&gt;
&lt;li&gt;Power Automate (Microsoft)&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>rpa</category>
    </item>
    <item>
      <title>Crie seu primeiro RPA com BotCity</title>
      <dc:creator>Lucas Cruz</dc:creator>
      <pubDate>Mon, 17 Mar 2025 08:15:22 +0000</pubDate>
      <link>https://dev.to/olucascruz/crie-seu-primeiro-rpa-com-botcity-4490</link>
      <guid>https://dev.to/olucascruz/crie-seu-primeiro-rpa-com-botcity-4490</guid>
      <description>&lt;h2&gt;
  
  
  Vídeo da execução da automação
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/gHbbEOqn9dM"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Repositório no GitHub: &lt;a href="https://github.com/olucascruz/oficina_rpa" rel="noopener noreferrer"&gt;https://github.com/olucascruz/oficina_rpa&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;Hoje, nesta oficina, vamos colocar a mão na massa e construir juntos um RPA! Nosso projeto será uma automação web e desktop, onde veremos, na prática, como essa tecnologia pode facilitar tarefas repetitivas.&lt;/p&gt;

&lt;p&gt;O processo que vamos desenvolver consiste em:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Acessar o Google News.&lt;/li&gt;
&lt;li&gt;Pesquisar um tema específico.&lt;/li&gt;
&lt;li&gt;Obter os títulos das notícias.&lt;/li&gt;
&lt;li&gt;Abrir o &lt;a href="https://pt-br.libreoffice.org/descubra/impress/" rel="noopener noreferrer"&gt;&lt;strong&gt;Impress&lt;/strong&gt;&lt;/a&gt; (na oficina presencial, utilizamos o PowerPoint).&lt;/li&gt;
&lt;li&gt;Criar uma apresentação com esses títulos.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Meu nome é Lucas Cruz, sou desenvolvedor de RPAs e faço parte do projeto DX Academy. Atualmente, curso Sistemas de Informação e, nos últimos dois anos, desenvolvi diversos RPAs para automatizar processos e otimizar fluxos de trabalho.&lt;/p&gt;

&lt;p&gt;A oficina foi conduzida por mim, com a colaboração do &lt;a href="https://www.linkedin.com/in/henrique-franklin-22945a11a/" rel="noopener noreferrer"&gt;Henrique Franklin&lt;/a&gt;, que abordou conceitos fundamentais de RPA e mapeamento de processos. Todo o material utilizado, incluindo as apresentações, está disponível no &lt;a href="https://github.com/olucascruz/oficina_rpa" rel="noopener noreferrer"&gt;repositório&lt;/a&gt; do projeto.&lt;/p&gt;

&lt;p&gt;O que é RPA?&lt;/p&gt;

&lt;p&gt;RPA (Robotic Process Automation) é a tecnologia que usa 'robôs' para automatizar tarefas manuais e repetitivas. Com ela, é possível aumentar a produtividade, reduzir erros e liberar tempo para atividades estratégicas. Vamos ver como isso funciona na prática!&lt;/p&gt;

&lt;h2&gt;
  
  
  Parte Técnica
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Criando o &lt;a href="https://docs.python.org/pt-br/3.13/library/venv.html" rel="noopener noreferrer"&gt;Ambiente Virtual&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Para começar, criem um ambiente virtual com o seguinte comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; venv venv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ativem o ambiente virtual:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;venv/Scripts/Activate.ps1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Instalando Dependências
&lt;/h3&gt;

&lt;p&gt;Instale o &lt;a href="https://www.cookiecutter.io/article-post/what-is-cookiecutter-highlight" rel="noopener noreferrer"&gt;Cookiecutter&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;cookiecutter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Em seguida, use o template da BotCity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; cookiecutter https://sdk.botcity.dev/templates/python/v2.zip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Selecione a opção "ambos" (both) e dê um nome ao seu projeto.&lt;br&gt;
Defina o &lt;strong&gt;Project ID&lt;/strong&gt;, por exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rpa
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora que baixamos o template da BotCity, vou explicar um pouco sobre os arquivos gerados. Entre eles, temos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Arquivos necessários para gerar a build.&lt;/li&gt;
&lt;li&gt;O arquivo &lt;code&gt;.botproject&lt;/code&gt;, que permite abrir o projeto na IDE da BotCity.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Contextualização
&lt;/h2&gt;

&lt;p&gt;Na indústria, uma atividade muito comum é baixar dados de um sistema e enviá-los por e-mail. Esse processo, quando feito manualmente, pode ser repetitivo e propenso a erros, tornando a automação uma solução eficiente.&lt;/p&gt;

&lt;p&gt;Um aspecto importante das automações web é que devem ser executadas no mesmo navegador em que foram desenvolvidas. Isso ocorre porque páginas da web podem ter comportamentos distintos em diferentes navegadores, o que pode comprometer a estabilidade da automação. Embora esse problema nem sempre aconteça, é um risco que deve ser considerado.&lt;/p&gt;

&lt;h3&gt;
  
  
  Instalando Dependências do Projeto
&lt;/h3&gt;

&lt;p&gt;Acesse a pasta do projeto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;rpa
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instale os pacotes necessários:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Escolhendo um &lt;a href="https://www.selenium.dev/pt-br/documentation/webdriver/" rel="noopener noreferrer"&gt;WebDriver&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Para iniciarmos, precisamos de um WebDriver, que permite ao nosso RPA interagir com o navegador. A escolha do driver depende do navegador que será utilizado na automação.&lt;/p&gt;

&lt;p&gt;Aqui, utilizaremos o &lt;strong&gt;Geckodriver&lt;/strong&gt;, que é o WebDriver do Firefox. Pode ser baixado em:&lt;br&gt;
&lt;a href="https://github.com/mozilla/geckodriver/releases" rel="noopener noreferrer"&gt;https://github.com/mozilla/geckodriver/releases&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Outra alternativa é usar o &lt;strong&gt;WebDriver Manager&lt;/strong&gt;:&lt;br&gt;
&lt;a href="https://pypi.org/project/webdriver-manager/" rel="noopener noreferrer"&gt;https://pypi.org/project/webdriver-manager/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Atenção:&lt;/strong&gt; O &lt;a href="https://pypi.org/project/webdriver-manager/" rel="noopener noreferrer"&gt;webdriver-manager&lt;/a&gt; pode facilitar a configuração inicial, mas também introduz uma dependência de terceiros. Isso pode gerar falhas na obtenção do WebDriver e comprometer a execução da automação. Portanto, avalie bem a melhor abordagem para o seu projeto.&lt;/p&gt;
&lt;h2&gt;
  
  
  Implementação
&lt;/h2&gt;

&lt;p&gt;No processo manual, abriríamos o navegador, acessaríamos o Google e, então, buscaríamos pelo Google News. No entanto, ao automatizar esse fluxo, podemos otimizar o processo acessando diretamente a página desejada, tornando a automação mais eficiente.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;webbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;então para maximizar usamos &lt;/p&gt;

&lt;p&gt;webbot.maximize_window()&lt;/p&gt;

&lt;h3&gt;
  
  
  Localizando Elementos Web
&lt;/h3&gt;

&lt;p&gt;Para interagir com os elementos da página, utilizamos as ferramentas de desenvolvedor do navegador para inspecioná-los e obter seus seletores. O &lt;a href="https://escoladedados.org/tutoriais/xpath-para-raspagem-de-dados-em-html/#:~:text=O%20XPath%20%C3%A9%20uma%20linguagem,HTML%20(HyperText%20Markup%20Language)." rel="noopener noreferrer"&gt;&lt;strong&gt;XPath&lt;/strong&gt;&lt;/a&gt; é um dos métodos mais utilizados para encontrar elementos.&lt;/p&gt;

&lt;p&gt;Capturamos o elemento de input de pesquisa com:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;webbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;xpath&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;By&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;XPATH&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Depois, podemos escrever no input com:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;webbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;texto&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ou alternativamente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;webbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;webbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;paste&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;texto&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para enviar a pesquisa:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;webbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No código do projeto fica assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;input_el&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;webbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/html/body/div[4]/header/div[2]/div[2]/div[2]/form/div[1]/div/div/div/div/div[1]/input[2]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;By&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;XPATH&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;input_el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;search_text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;webbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para capturar os títulos da pesquisa, usamos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;title_text1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;webbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;xpath&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;By&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;XPATH&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se quisermos validar se o elemento foi encontrado corretamente, podemos imprimir o resultado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title_text1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se não for o elemento correto, o retorno pode ser &lt;code&gt;NoneType&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Para capturar os 5 e guardar esses titulos em uma lista podemos fazer da seguinte maneira&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;list_text_news&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

&lt;span class="n"&gt;webbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;news1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;webbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/html/body/c-wiz/div/main/div[2]/c-wiz/c-wiz[1]/c-wiz/article/div[1]/div[2]/div/a&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;By&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;XPATH&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;

&lt;span class="n"&gt;news2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;webbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/html/body/c-wiz/div/main/div[2]/c-wiz/c-wiz[2]/c-wiz/div/div[1]/c-wiz/article/div[1]/div[2]/div/a&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;By&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;XPATH&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;

&lt;span class="n"&gt;news3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;webbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/html/body/c-wiz/div/main/div[2]/c-wiz/c-wiz[2]/c-wiz/div/div[2]/c-wiz/article/div[1]/div[2]/div/a&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;By&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;XPATH&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;

&lt;span class="n"&gt;news4&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;webbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/html/body/c-wiz/div/main/div[2]/c-wiz/c-wiz[2]/c-wiz/div/div[3]/c-wiz/article/div[1]/div[2]/div/a&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;By&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;XPATH&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;

&lt;span class="n"&gt;news5&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;webbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/html/body/c-wiz/div/main/div[2]/c-wiz/c-wiz[3]/c-wiz/article/div[1]/div[2]/div/a&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;By&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;XPATH&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;

&lt;span class="n"&gt;webbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stop_browser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;list_text_news&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;news1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;list_text_news&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;news2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;list_text_news&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;news3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;list_text_news&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;news4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;list_text_news&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;news5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Uma boa prática no desenvolvimento de software é sempre manter o código desacoplado. Como essa parte da automação é responsável apenas por capturar noticias do google news podemos organizá-la em uma função específica:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_titles_news&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;webbot&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;WebBot&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;search_text&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="n"&gt;webbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;browse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://news.google.com/home?hl=pt-BR&amp;amp;gl=BR&amp;amp;ceid=BR:pt-419&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;webbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;maximize_window&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;input_el&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;webbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/html/body/div[4]/header/div[2]/div[2]/div[2]/form/div[1]/div/div/div/div/div[1]/input[2]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;By&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;XPATH&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;input_el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;search_text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;webbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;list_text_news&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="n"&gt;webbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;news1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;webbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/html/body/c-wiz/div/main/div[2]/c-wiz/c-wiz[1]/c-wiz/article/div[1]/div[2]/div/a&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;By&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;XPATH&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;

    &lt;span class="n"&gt;news2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;webbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/html/body/c-wiz/div/main/div[2]/c-wiz/c-wiz[2]/c-wiz/div/div[1]/c-wiz/article/div[1]/div[2]/div/a&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;By&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;XPATH&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;

    &lt;span class="n"&gt;news3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;webbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/html/body/c-wiz/div/main/div[2]/c-wiz/c-wiz[2]/c-wiz/div/div[2]/c-wiz/article/div[1]/div[2]/div/a&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;By&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;XPATH&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;

    &lt;span class="n"&gt;news4&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;webbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/html/body/c-wiz/div/main/div[2]/c-wiz/c-wiz[2]/c-wiz/div/div[3]/c-wiz/article/div[1]/div[2]/div/a&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;By&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;XPATH&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;

    &lt;span class="n"&gt;news5&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;webbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/html/body/c-wiz/div/main/div[2]/c-wiz/c-wiz[3]/c-wiz/article/div[1]/div[2]/div/a&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;By&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;XPATH&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;

    &lt;span class="n"&gt;webbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stop_browser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;list_text_news&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;news1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;list_text_news&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;news2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;list_text_news&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;news3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;list_text_news&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;news4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;list_text_news&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;news5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;



    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;list_text_news&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Aprofundando
&lt;/h3&gt;

&lt;p&gt;A página do Google News apresenta uma peculiaridade: seu conteúdo não é fixo. Além da lista de notícias, também são exibidas caixas com notícias de uma mesma fonte. Esses dois tipos de elementos não estão localizados em posições fixas, o que torna a busca pelos textos mais desafiadora.&lt;/p&gt;

&lt;p&gt;Usar o método mencionado anteriormente não garante que a automação funcione de forma consistente. Quando isso acontece, precisamos buscar alternativas.&lt;/p&gt;

&lt;p&gt;Uma opção seria buscar os textos usando seletores diferentes do XPath. Uma forma comum de resolver esse problema é buscar todos os elementos com uma determinada classe, utilizando o método:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;webbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_elements&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;nome_da_classe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;By&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CLASS_NAME&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Note que essa função retorna uma lista de múltiplos elementos)&lt;br&gt;
No entanto, neste caso específico, esse método não funciona.&lt;/p&gt;

&lt;p&gt;Uma forma de contornar esse problema é buscar todos os conteúdos de texto dentro das tags e, em seguida, filtrar para obter apenas as notícias. O código ficaria assim:&lt;/p&gt;

&lt;p&gt;desta forma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;text_in_page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;webbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;page_source&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;get_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; | &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;list_text_in_page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text_in_page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; | &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;list_text_contains_search_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;search_text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;notícias sobre&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;list_text_in_page&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aqui usamos um filtro que remove textos que contém "notícias sobre", pois os blocos com notícias de uma mesma fonte tem esse título.&lt;/p&gt;

&lt;p&gt;Dessa maneira, nossa solução fica menos propensa a erros.&lt;/p&gt;

&lt;p&gt;Ao desenvolver RPAs sempre nos deparamos com problemas que exigem soluções diferentes. A abordagem mostrada anteriormente é a forma mais geral para se buscar um elemento da página e obter seu texto. Nesta seção é mostrado uma solução melhor adaptada para esse site em específico e para está automação.&lt;/p&gt;

&lt;p&gt;IMPORTANTE: A primeira solução foi criada na primeira vez que automatizei esse site, sem conhecer completamente seu comportamento, o que a tornava propensa a erros. Para evitar esses problemas, é fundamental realizar testes. Durante o desenvolvimento de uma automação, é comum deixá-la executando periodicamente em um período de testes, o que nos permite identificar erros, casos especiais e outros problemas. Ao corrigir essas questões, nossa solução se torna mais robusta.&lt;/p&gt;

&lt;p&gt;Por fim a função fica assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_titles_news&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;webbot&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;WebBot&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;search_text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="n"&gt;webbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;browse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://news.google.com/home?hl=pt-BR&amp;amp;gl=BR&amp;amp;ceid=BR:pt-419&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;webbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;maximize_window&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;input_el&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;webbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/html/body/div[4]/header/div[2]/div[2]/div[2]/form/div[1]/div/div/div/div/div[1]/input[2]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;By&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;XPATH&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;input_el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;search_text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;webbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;webbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;text_in_page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;webbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;page_source&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;get_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; | &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;list_text_in_page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text_in_page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; | &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;list_text_contains_search_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;search_text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;notícias sobre&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;list_text_in_page&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="n"&gt;webbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stop_browser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;list_text_contains_search_text&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Automação Desktop
&lt;/h2&gt;

&lt;p&gt;Agora que temos os títulos, vamos abrir o &lt;strong&gt;Impress&lt;/strong&gt; para criar uma apresentação.&lt;/p&gt;

&lt;p&gt;Uma maneira simples de abrir um programa no Windows via automação é:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Pressionar a tecla &lt;strong&gt;Windows&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Pesquisar o nome do programa.&lt;/li&gt;
&lt;li&gt;Pressionar &lt;strong&gt;Enter&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Interação com Interface Gráfica
&lt;/h3&gt;

&lt;p&gt;Para interagir com elementos visuais, utilizamos imagens de referência. Essas imagens podem ser capturadas manualmente ou pelo &lt;a href="https://documentation.botcity.dev/pt/studio/" rel="noopener noreferrer"&gt;&lt;strong&gt;BotCity Studio&lt;/strong&gt;&lt;/a&gt; que também gera o código para interagir com a imagem.&lt;/p&gt;

&lt;h4&gt;
  
  
  Vantagens do BotCity Studio:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Gera automaticamente o código para interagir com as imagens.&lt;/li&gt;
&lt;li&gt;Facilita o uso de "click relativo", onde o usuário pode selecionar visualmente o local em que deseja clicar em relação à imagem identificada.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Para encontrar um elemento na interface, usamos o seguinte código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;desktop_bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;nome_da_imagem&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As imagens devem estar na pasta &lt;strong&gt;resources&lt;/strong&gt;, que já vem configurada no template.&lt;/p&gt;

&lt;p&gt;O código gerado pelo BotCity Studio para encontrar e clicar em um elemento é o seguinte:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;desktop_bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;nome_da_imagem&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;not_found&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;nome_da_imagem&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;desktop_bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se o elemento for opcional (como um popup de atualização), podemos evitar erros verificando sua existência antes de tentar clicar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;desktop_bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;nome_da_imagem&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;desktop_bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Se o item não for encontrado, a função de clique não será executada, evitando falhas na automação.
&lt;/h2&gt;

&lt;p&gt;Podemos dividir a parte de criação da apresentação em uma função separada para manter o código mais organizado. O código final para a função de criação da apresentação seria:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_pptx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;desktop_bot&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;DesktopBot&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;search_text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;titles&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;desktop_bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;type_windows&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;desktop_bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;paste&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;LibreOffice Impress&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;desktop_bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;desktop_bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fechar_btn&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;desktop_bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;desktop_bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title_field&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;not_found&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text_field&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    
    &lt;span class="n"&gt;desktop_bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;desktop_bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;paste&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Principais notícias sobre: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;search_text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;desktop_bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text_field&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;not_found&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text_field&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    
    &lt;span class="n"&gt;desktop_bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;titles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;desktop_bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;paste&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;desktop_bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;desktop_bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;backspace&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;desktop_bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;control_a&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# decrease font size
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;desktop_bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;control_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;desktop_bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;formatte_bt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;not_found&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;formatte_bt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="n"&gt;desktop_bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;desktop_bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;list_bt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;desktop_bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;desktop_bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;unordered_list_bt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;desktop_bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;desktop_bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;control_s&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;desktop_bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;desktop_bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;kb_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;novo_file&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;desktop_bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;desktop_bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Close app
&lt;/span&gt;    &lt;span class="n"&gt;desktop_bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;control_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;q&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Dicas para automação desktop
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Use imagens &lt;strong&gt;únicas&lt;/strong&gt;. Se um botão contém um ícone e um texto, prefira capturar a imagem com o texto para evitar confusões.&lt;/li&gt;
&lt;li&gt;Prefira usar os atalhos do programa, se disponíveis, em vez de depender de visão computacional, pois isso tende a ser menos propenso a erros.&lt;/li&gt;
&lt;li&gt;Use sabiamente o comando de espera, especialmente se o programa depender de algum processamento demorado.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;IMPORTANTE: Imagens capturadas em determinadas telas não serão reconhecidas em telas com resoluções diferentes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Estrutura do projeto
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqwyz6xfxir22nscczyyi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqwyz6xfxir22nscczyyi.png" alt="Print da estrutura do projeto" width="263" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No final, a estrutura do projeto fica assim, com a pasta app contendo as funções tanto de acesso ao site quanto de uso do PowerPoint. Para automações mais complexas, em que vários sistemas estão envolvidos, podemos criar subpastas específicas para cada funcionalidade dentro da pasta app.&lt;/p&gt;

&lt;p&gt;Embora não tenha sido usado neste projeto, em sistemas mais robustos, é comum criar uma pasta utils que contém funções utilitárias que são usadas em várias partes do projeto.&lt;/p&gt;




&lt;p&gt;Com isso, finalizamos a construção do nosso RPA! Espero que esta oficina tenha sido útil para vocês e que consigam aplicar esses conhecimentos em novos projetos. Boa automação!&lt;/p&gt;

&lt;p&gt;PS: Se você gostou desse texto, recomendo também o meu primeiro artigo sobre automação, onde compartilho o passo a passo para automatizar um editor de imagens GIMP. Confira aqui: &lt;a href="https://www.linkedin.com/pulse/automatizando-editor-de-imagens-gimp-com-lucas-cruz-/?trackingId=AE1ajJRISMqf7C0pSSWUNw%3D%3D" rel="noopener noreferrer"&gt;Automatizando editor de imagens GIMP com Python/Botcity&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rpa</category>
      <category>botcity</category>
      <category>automation</category>
      <category>python</category>
    </item>
    <item>
      <title>Como normalizar banco de dados?</title>
      <dc:creator>Lucas Cruz</dc:creator>
      <pubDate>Tue, 02 Apr 2024 21:21:08 +0000</pubDate>
      <link>https://dev.to/olucascruz/como-normalizar-banco-de-dados-33dh</link>
      <guid>https://dev.to/olucascruz/como-normalizar-banco-de-dados-33dh</guid>
      <description>&lt;p&gt;Ao fim desse artigo você saberá como normalizar um banco de dados uma habilidade essencial para qualquer um que deseje desenvolver softwares com persistência de dados &lt;/p&gt;

&lt;h2&gt;
  
  
  O que é normalização?
&lt;/h2&gt;

&lt;p&gt;A normalização é um processo para organizar e estruturar um banco de dados relacional para eliminar redundâncias e anomalias.&lt;br&gt;
As formas normais são 1FN: Atomicidade de dados, 2FN: Eliminação de dependências parciais, 3FN: Eliminação de dependências transitivas. Cada uma das formas normais depende da anterior ou seja é preciso está na 1FN para ir para a 2FN.&lt;/p&gt;

&lt;h2&gt;
  
  
  1FN: Atomicidade de dados
&lt;/h2&gt;

&lt;p&gt;As colunas devem ser &lt;strong&gt;atômicas&lt;/strong&gt; ou seja indivisíveis, por exemplo, se o endereço for um dado que vai ser salvo, seguindo a 1º forma normal cada parte do endereço deve ser uma coluna: &lt;/p&gt;

&lt;p&gt;| número da casa | bairro | rua | cidade |&lt;/p&gt;

&lt;p&gt;e não apenas &lt;/p&gt;

&lt;p&gt;|endereço|&lt;/p&gt;

&lt;p&gt;E também caso tenha muita um valor se repita varias vezes deve-se registrá-lo em outra tabela.&lt;/p&gt;

&lt;p&gt;Por exemplo pode se haver tabelas para: Bairro, Rua e Cidade&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bairro&lt;/strong&gt;&lt;br&gt;
| id | nome do bairro |&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rua&lt;/strong&gt;&lt;br&gt;
| id | nome da rua |&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cidade&lt;/strong&gt;&lt;br&gt;
| id | nome da cidade |&lt;/p&gt;

&lt;p&gt;Assim na tabela endereço as colunas só referenciam o id ao invés de repetir o valor varias vezes.&lt;/p&gt;

&lt;h2&gt;
  
  
  2NF: Eliminação de Dependências Parciais
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Primeiro precisa-se seguir a 1NF.&lt;/em&gt;&lt;br&gt;
Os atributos da tabela devem depender de uma chave primaria completa não de forma parcial em caso de chaves conjuntas.&lt;/p&gt;

&lt;p&gt;Se for uma tabela pedido:&lt;/p&gt;

&lt;p&gt;|id do pedido | id do cliente | nome do cliente | Hora da entrega|&lt;/p&gt;

&lt;p&gt;Deve-se analisar qual é a chave primária, agora verificar se algum   atributo não chave está dependendo de outra chave, se estiver deve ser movido para outra tabela, nesse caso o nome do cliente ficando assim:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tabela pedido&lt;/strong&gt;:&lt;br&gt;
| id do pedido | id do cliente | Hora da entrega |&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tabela cliente&lt;/strong&gt;:&lt;br&gt;
| id do cliente | nome do cliente |&lt;/p&gt;

&lt;h2&gt;
  
  
  3NF: Remoção de Dependências Transitivas
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Deve atender o 2NF.&lt;/em&gt;&lt;br&gt;
Os atributos só podem depender do id e de nenhuma outra coluna.&lt;br&gt;
Por exemplo se você uma tabela produto:&lt;/p&gt;

&lt;p&gt;Tabela produto&lt;/p&gt;

&lt;p&gt;| id do produto | nome do produto | categoria do produto | preço |&lt;/p&gt;

&lt;p&gt;Como a coluna de categoria do produto depende da coluna nome do produto ele deve ser movido para outra tabela e referenciado nessa:&lt;/p&gt;

&lt;p&gt;Tabela categorias&lt;/p&gt;

&lt;p&gt;| id da categoria | nome da categoria |&lt;/p&gt;

&lt;p&gt;Isso promove maior organização dos dados e ajuda a evitar anomalias na modificação, inserção e exclusão de dados.&lt;/p&gt;

&lt;p&gt;Referências:&lt;br&gt;
 &lt;a href="https://pt.wikipedia.org/wiki/Normaliza%C3%A7%C3%A3o_de_dados"&gt;https://pt.wikipedia.org/wiki/Normaliza%C3%A7%C3%A3o_de_dados&lt;/a&gt;&lt;br&gt;
 &lt;a href="https://dev.to/ikauematos/conceitos-principais-sobre-normalizacao-1hpl"&gt;https://dev.to/ikauematos/conceitos-principais-sobre-normalizacao-1hpl&lt;/a&gt;&lt;/p&gt;

</description>
      <category>database</category>
      <category>braziliandevs</category>
      <category>mysql</category>
      <category>sql</category>
    </item>
    <item>
      <title>Fetch API: One Byte Explainer</title>
      <dc:creator>Lucas Cruz</dc:creator>
      <pubDate>Fri, 29 Mar 2024 20:35:03 +0000</pubDate>
      <link>https://dev.to/olucascruz/fetch-api-one-byte-explainer-53pn</link>
      <guid>https://dev.to/olucascruz/fetch-api-one-byte-explainer-53pn</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for DEV Challenge v24.03.20, One Byte Explainer: Browser API or Feature.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Explainer
&lt;/h2&gt;

&lt;p&gt;The fetch API allows simplified access to HTTP protocol methods, enabling client-server communication. The fetch API can be called with just one argument (path) to use the GET method, but it also supports other methods like POST, PUT, DELETE.&lt;/p&gt;

&lt;h2&gt;
  
  
  Additional Context
&lt;/h2&gt;

&lt;p&gt;For more information you can visit the: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API"&gt;https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API&lt;/a&gt;&lt;/p&gt;

</description>
      <category>frontendchallenge</category>
      <category>devchallenge</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Glam Up My Markup: Camp Activities with stars (particles)</title>
      <dc:creator>Lucas Cruz</dc:creator>
      <pubDate>Fri, 29 Mar 2024 17:10:22 +0000</pubDate>
      <link>https://dev.to/olucascruz/glam-up-my-markup-camp-activities-with-stars-particles-42fc</link>
      <guid>https://dev.to/olucascruz/glam-up-my-markup-camp-activities-with-stars-particles-42fc</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for DEV Challenge v24.03.20, Glam Up My Markup: Camp Activities&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I build a interface with three principal colors, black, white and purple. The forms is purple, the blackground is black because I like dark theme, and starts white. Next to form there stars - Small circles white that move it-&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;github: &lt;a href="https://github.com/olucascruz/frontendChallengeDevTo"&gt;https://github.com/olucascruz/frontendChallengeDevTo&lt;/a&gt;&lt;br&gt;
&lt;iframe height="600" src="https://codepen.io/frenib/embed/mdgBeQw?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Journey
&lt;/h2&gt;

&lt;p&gt;Firstly, I selected a color palette consisting of purple, black, and white. While the form serves as the main element of the interface, I decided to add a new element for me: particles, commonly used in game development. With a basic knowledge of how to implement them, I began by creating a div to store the particles, assigning it the class 'particles', and then created additional divs to represent the particles themselves, with the class 'particle'. Initially, I attempted to position the particles randomly using the 'position: absolute' property and random margins, but soon realized that this did not produce the desired effect. After some research, I discovered that setting the position of the particles as 'position: relative' would allow me to move them using the 'top' and 'left' properties without the need for margins, resulting in the desired behavior.&lt;/p&gt;

&lt;p&gt;The generation of random positions was implemented using JavaScript. Additionally, I created two CSS animations: one to simulate the glow of the particles and another for their movement. I noticed that when the particles glowed and moved simultaneously, the effect seemed strange. To correct this, I adjusted the speed of the animation for each particle individually, using JavaScript for this purpose.&lt;/p&gt;

&lt;p&gt;Subsequently, I made the interface responsive. To achieve this, I used media queries to center the form when the screen was smaller and to send the particles behind the form. This configuration required that the div with the class 'particles' and the section containing the form had the 'position: absolute' property, allowing them to occupy the same space without issues.&lt;/p&gt;

&lt;p&gt;Finally, in the form, I used a purple color with a gradient, and if you hover the mouse over it, there is a white shadow around it. The button also has this behavior, with the addition that it also changes color, and when clicked, the form disappears, and a message appears.&lt;/p&gt;

&lt;p&gt;LICENSE CODE: MIT&lt;/p&gt;

</description>
      <category>frontendchallenge</category>
      <category>devchallenge</category>
      <category>css</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Propriedades ACID de uma transação em banco de dados.</title>
      <dc:creator>Lucas Cruz</dc:creator>
      <pubDate>Mon, 25 Mar 2024 01:55:26 +0000</pubDate>
      <link>https://dev.to/olucascruz/propriedades-acid-de-uma-transacao-em-banco-de-dados-i3m</link>
      <guid>https://dev.to/olucascruz/propriedades-acid-de-uma-transacao-em-banco-de-dados-i3m</guid>
      <description>&lt;p&gt;Talvez você já tenha escutado sobre propriedades ACID de transações em banco de dados em algum lugar mas não entenda completamente sobre o que se trata, então esse artigo veio para esclarecer suas dúvidas.&lt;/p&gt;

&lt;p&gt;O que são: As transações ACID são um conjunto de propriedades de um &lt;strong&gt;banco de dados relacionais&lt;/strong&gt; que garante que as operações sejam executadas de forma segura e confiável.&lt;/p&gt;

&lt;p&gt;Bem vamos ao significado das letras:&lt;br&gt;
A = Atomicidade&lt;br&gt;
C = Consistência&lt;br&gt;
I = Isolamento&lt;br&gt;
D = Durabilidade&lt;/p&gt;

&lt;p&gt;Antes de seguimos para a explicação de cada propriedade acho importante dar um passo trás e explicar o que são transações e operações.&lt;/p&gt;

&lt;h2&gt;
  
  
  Operações
&lt;/h2&gt;

&lt;p&gt;Ação específica realizada em um banco de dados, como &lt;strong&gt;SELECT&lt;/strong&gt;, &lt;strong&gt;INSERT&lt;/strong&gt;, &lt;strong&gt;UPDADE&lt;/strong&gt;, &lt;strong&gt;DELETE&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Transações
&lt;/h2&gt;

&lt;p&gt;São unidades lógicas de trabalho que são composta por uma ou mais operações.&lt;/p&gt;

&lt;h2&gt;
  
  
  Atomicidade
&lt;/h2&gt;

&lt;p&gt;Garante uma transação seja tratada como uma &lt;strong&gt;unidade indivisível&lt;/strong&gt; todas as operações de uma transação sejam concluídas com sucesso, para que ela seja aplicada ao banco de dados.&lt;/p&gt;

&lt;p&gt;Se durante a transação alguma operação falhar toda a transação será desfeita (rollback).&lt;br&gt;
Se todas as operações derem certo então a transação é salva no banco de dados (commit).&lt;/p&gt;

&lt;h3&gt;
  
  
  Caso: Transação Bancária
&lt;/h3&gt;

&lt;p&gt;Digamos que temos a conta A e a conta B.&lt;br&gt;
A conta A faz um depósito na conta B, ou seja uma operação de UPDATE na conta A e na conta B, se uma dessas operações falharem, ambas devem ser desconsideradas. &lt;/p&gt;

&lt;h2&gt;
  
  
  Consistência
&lt;/h2&gt;

&lt;p&gt;Garante que cada transação siga todas as &lt;strong&gt;regras e restrições&lt;/strong&gt; definidas durante a criação do banco de dados sejam obedecidas. Como tipo de dado, relacionamentos por chave estrangeira entre outras devem ser seguidos para que a transação seja executada com sucesso&lt;/p&gt;

&lt;h2&gt;
  
  
  Isolamento
&lt;/h2&gt;

&lt;p&gt;Garante que cada transação seja &lt;strong&gt;executada isoladamente&lt;/strong&gt;, nenhuma transação pode interferir no funcionamento de outra.&lt;/p&gt;

&lt;h2&gt;
  
  
  Durabilidade
&lt;/h2&gt;

&lt;p&gt;Garante que uma vez que a alteração é salva, &lt;strong&gt;ela permanece&lt;/strong&gt; no banco de dados e só pode ser alterada por outra transação.&lt;/p&gt;

&lt;p&gt;Referências&lt;br&gt;
&lt;a href="https://www.oracle.com/database/what-is-database/"&gt;https://www.oracle.com/database/what-is-database/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pt.wikipedia.org/wiki/Transa%C3%A7%C3%A3o_(banco_de_dados)"&gt;https://pt.wikipedia.org/wiki/Transa%C3%A7%C3%A3o_(banco_de_dados)&lt;/a&gt;&lt;/p&gt;

</description>
      <category>database</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Tipos em Python</title>
      <dc:creator>Lucas Cruz</dc:creator>
      <pubDate>Thu, 21 Mar 2024 06:08:46 +0000</pubDate>
      <link>https://dev.to/olucascruz/tipos-em-python-3jfl</link>
      <guid>https://dev.to/olucascruz/tipos-em-python-3jfl</guid>
      <description>&lt;p&gt;Estou fazendo um bootcamp com foco em python pela DIO e decidi compartilhar um pouco do conteúdo que estou aprendendo/revendo (como eu já programo em python a um tempo muitas coisas são revisitas).&lt;/p&gt;

&lt;h3&gt;
  
  
  Tipos de dados
&lt;/h3&gt;

&lt;p&gt;Os tipos de dados definem as características e comportamentos de um valor para o interpretador.&lt;/p&gt;

&lt;p&gt;IMPORTANTE: É importante entender que em python todas as variáveis são objetos e sendo objetos elas tem seus métodos.&lt;/p&gt;

&lt;p&gt;Python é uma linguagem de tipagem dinâmica, o que significa que você pode modificar o tipo de uma variável sem fazer cerimônia como:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;variable = 10 
variable = "now is a string"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como visto no exemplo acima nem precisa citar qual é o tipo como em outras linguagens como C# que seria algo assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int number = 10;
float floatNumber = 5.5f;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ok, voltando ao python, os seus tipos:&lt;/p&gt;

&lt;p&gt;Texto -&amp;gt; str&lt;br&gt;
Numérico -&amp;gt; int, float, complex&lt;/p&gt;

&lt;p&gt;int são os números inteiros tais como: 1, 2, 3&lt;/p&gt;

&lt;p&gt;float são números com ponto flutuante tais comos: 0.1, 0.2, 3.14159265359&lt;/p&gt;

&lt;p&gt;PERA, algo novo para mim, o que é um complex? certamente não é algo do dia a dia, a primeira coisa que fiz ao ver isso foi perguntar ao Chat GPT. Segue a conversa abaixo::&lt;/p&gt;

&lt;p&gt;Me: o que é um complex em python?&lt;/p&gt;

&lt;p&gt;ChatGPT&lt;/p&gt;

&lt;p&gt;Em Python, um complex é um tipo de dado numérico que representa um número complexo. Um número complexo é composto por uma parte real e uma parte imaginária, onde a parte imaginária é multiplicada pelo número imaginário "i", que é a raiz quadrada de -1.&lt;/p&gt;

&lt;p&gt;Em Python, os números complexos são representados pela seguinte sintaxe:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;x = &amp;lt;parte real&amp;gt; + &amp;lt;parte imaginária&amp;gt;j
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Onde  e  são números reais, e j representa a unidade imaginária. Por exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;z = 3 + 4j
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Neste exemplo, z é um número complexo com parte real 3 e parte imaginária 4. Python fornece várias funções e operações para trabalhar com números complexos, incluindo operações aritméticas, como adição, subtração, multiplicação e divisão, bem como funções específicas, como abs() para calcular o módulo (ou magnitude) de um número complexo.&lt;/p&gt;

&lt;p&gt;OK tendo a explicação de que o tipo complex permite trabalhar com números imaginários podemos seguir adiante.&lt;/p&gt;

&lt;p&gt;Sequência -&amp;gt; list, tuple, range&lt;br&gt;
Simplificando:&lt;br&gt;
 Listas = mutáveis&lt;br&gt;
 Tuplas = imutáveis&lt;br&gt;
 range = A função range do Python gera uma lista de números que geralmente são usados ​​em muitas situações para iteração, como no loop for ou em muitos outros casos.&lt;/p&gt;

&lt;p&gt;Mapa -&amp;gt; dict &lt;br&gt;
Dicionário basicamente uma tabela de chave valor&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dictionary = {1:"primeiro"} // o 1 é a chave  o "primeiro" o valor

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Coleção -&amp;gt; set, frozenset&lt;/p&gt;

&lt;p&gt;Um set é basicamente uma coleção que não permite valores duplicados, o que pode ser bastante útil.&lt;/p&gt;

&lt;p&gt;Agora o frozenset eu realmente não uso no dia dia - após uma pesquisa descobrir que é um set só que imutável (como o nome meio que já diz)&lt;/p&gt;

&lt;p&gt;Booleano -&amp;gt; bool&lt;br&gt;
Pode assumir os valores os valores True (verdadeiro) ou False (falso)&lt;/p&gt;

&lt;p&gt;Binários - bytes, bytearray, memoryview&lt;/p&gt;

&lt;p&gt;O tipo bytes em Python representa uma sequência imutável de bytes. Ele é usado para armazenar dados binários, como imagens, arquivos de áudio, ou qualquer outro tipo de dados que não sejam de texto.&lt;/p&gt;

&lt;p&gt;O tipo bytearray é semelhante ao tipo bytes, mas é mutável, o que significa que seu conteúdo pode ser alterado após a criação.&lt;/p&gt;

&lt;p&gt;O tipo memoryview em Python permite acessar o conteúdo de objetos de bytes (ou outros objetos de buffer) sem fazer cópias desnecessárias na memória.&lt;br&gt;
Ele fornece uma interface de baixo nível para acessar os dados armazenados em um objeto de buffer, como um objeto bytes ou bytearray, sem a necessidade de converter o objeto inteiro em outro tipo de dados.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>braziliandevs</category>
      <category>python</category>
    </item>
    <item>
      <title>Cadê meus zeros? Sobre tipos em banco de dados.</title>
      <dc:creator>Lucas Cruz</dc:creator>
      <pubDate>Fri, 15 Mar 2024 21:25:00 +0000</pubDate>
      <link>https://dev.to/olucascruz/cade-meus-zeros-sobre-tipos-em-banco-de-dados-1o8l</link>
      <guid>https://dev.to/olucascruz/cade-meus-zeros-sobre-tipos-em-banco-de-dados-1o8l</guid>
      <description>&lt;p&gt;Estava eu codando, mais um dia comum, quando de repente acontece um erro.&lt;/p&gt;

&lt;p&gt;O valor que deveria ser salvo aparece na interface diferente do valor que eu digitei, nesse momento apertei ctrl+c para parar a execução do código, e rodei ele outra vez com npx expo start.&lt;/p&gt;

&lt;p&gt;O banco de dados recarregou e ali estava outra vez o valor errado, eu estava testando a inserção de um código e como teste usei "0000000000" porém o que aparecia na lista era apenas 0.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuehnavs1sekkfj3rsem7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuehnavs1sekkfj3rsem7.png" alt="Meme algo de errado não está certo" width="447" height="332"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Depois de reiniciar a segunda coisa que pensei foi que em algum lugar do código deve está convertendo para inteiro (Sim, eu estava usando &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Type_Conversion" rel="noopener noreferrer"&gt;JavaScript&lt;/a&gt;), mas ao analisar o código parecia tudo ok.&lt;/p&gt;

&lt;p&gt;Até lembrar do tipo que estava usando no banco de dados, os Ids eram do tipo inteiro. Então tudo fez sentido! Não posso salvar dados que tenham zeros a esquerda dessa forma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tx.executeSql(
'CREATE TABLE IF NOT EXISTS Machine (id INTEGER PRIMARY KEY, is_available INTEGER)',
[], 
()=&amp;gt;{console.log("successful create Machine")}, 
()=&amp;gt;{console.error("error: create Machine")})

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para resolver essa questão bastava modificar o tipo para texto.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tx.executeSql(
'CREATE TABLE IF NOT EXISTS Machine (id TEXT PRIMARY KEY, is_available INTEGER)',
[], 
()=&amp;gt;{console.log("successful create Machine")}, 
()=&amp;gt;{console.error("error: create Machine")})

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora sim o app consegue adicionar itens com zeros a esquerda:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3u77ubjc7fw07axzbyy5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3u77ubjc7fw07axzbyy5.png" alt="Interface com o item 000000000 adicionado" width="257" height="565"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Concluindo
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;É sempre importante verificar os tipos de dados que está usando no banco de dados, para não ocorrer erros como este e perder seus zeros ou pior.&lt;/li&gt;
&lt;li&gt;Apesar parecer intuitivo usar um tipo numérico como inteiro prefira usar texto quando o número que for usar não for usado para cálculos ou seja que não precisem necessariamente ser um número.&lt;/li&gt;
&lt;li&gt;Façam testes.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>braziliandevs</category>
      <category>bancodedados</category>
      <category>testing</category>
    </item>
    <item>
      <title>Substituindo ternários por switch-case em React-Native</title>
      <dc:creator>Lucas Cruz</dc:creator>
      <pubDate>Thu, 14 Mar 2024 19:29:28 +0000</pubDate>
      <link>https://dev.to/olucascruz/substituindo-ternarios-por-switch-case-em-react-native-4n2p</link>
      <guid>https://dev.to/olucascruz/substituindo-ternarios-por-switch-case-em-react-native-4n2p</guid>
      <description>&lt;p&gt;Recentemente lendo alguns posts sobre react-native encontrei uma forma de melhorar um componente. Originalmente, eu o havia implementado com ternários, mas como se tratava de múltiplos estados possíveis tornava o código difícil de entender e manter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;stateModal === "wait" ? &amp;lt;&amp;gt;...&amp;lt;/&amp;gt; 
: 
stateModal === edit ? &amp;lt;&amp;gt;...&amp;lt;/&amp;gt; 
: 
stateModal === "delete" ? &amp;lt;&amp;gt;...&amp;lt;/&amp;gt; 
:
stateModal === "finish" ? &amp;lt;&amp;gt;...&amp;lt;/&amp;gt; 
: null

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Basicamente eu tenho um componente de modal que tem alguns estados: wait, edit, delete, finish&lt;/p&gt;

&lt;p&gt;A forma que encontrei para melhorar.&lt;/p&gt;

&lt;h3&gt;
  
  
  Definindo switch-case
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const switchModalState = () =&amp;gt; {
        switch (stateModal) {
            case "wait":
                return (
                  &amp;lt;&amp;gt;...&amp;lt;/&amp;gt;
                    )    

            case "edit":
                return (
                    &amp;lt;&amp;gt;...&amp;lt;/&amp;gt;
                    )

            case "delete":
                return (
                    &amp;lt;&amp;gt;...&amp;lt;/&amp;gt;
                    )

            case "finish":
                return (
                    &amp;lt;&amp;gt;...&amp;lt;/&amp;gt;
                )

            default:
                return (
                    &amp;lt;&amp;gt;...&amp;lt;/&amp;gt;
                    )
        }


    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Chamando função para renderizar
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;return(
        &amp;lt;Modal
        visible={modalVisible}
        animationType="slide"
        transparent={true}
        onRequestClose={() =&amp;gt; setModalVisible(false)}
        &amp;gt;
            &amp;lt;View style={styles.modalContainer}&amp;gt;
                &amp;lt;View style={styles.modalContent}&amp;gt;
                    {switchModalState()}
                &amp;lt;/View&amp;gt;
            &amp;lt;/View&amp;gt;
        &amp;lt;/Modal&amp;gt;

        )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Concluindo
&lt;/h2&gt;

&lt;p&gt;Dessa forma fica mais simples para que outros desenvolvedores entendam o código e também facilita a manutenção, tornando mais fácil adicionar estados novos, ou editar um estado específico.  Investir tempo em uma estrutura bem definida para lidar com os estados do modal não apenas facilita o trabalho para mim como desenvolvedor, mas também para qualquer pessoa que precise entender ou modificar o código no futuro.&lt;/p&gt;

&lt;p&gt;Se quiser visualizar o código atualmente: &lt;a href="https://github.com/olucascruz/control_equip/blob/main/src/components/ModalEditDelete.jsx"&gt;https://github.com/olucascruz/control_equip/blob/main/src/components/ModalEditDelete.jsx&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Refs:&lt;br&gt;
&lt;a href="https://dev.to/girordo/algumas-das-melhores-praticas-que-utilizo-diariamente-41c4"&gt;https://dev.to/girordo/algumas-das-melhores-praticas-que-utilizo-diariamente-41c4&lt;/a&gt;&lt;br&gt;
&lt;a href="https://stackoverflow.com/questions/46592833/how-to-use-switch-statement-inside-a-react-component"&gt;https://stackoverflow.com/questions/46592833/how-to-use-switch-statement-inside-a-react-component&lt;/a&gt; &lt;/p&gt;

</description>
      <category>javascript</category>
      <category>reactnative</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>Criando uma interface de escolha de fases em UNITY</title>
      <dc:creator>Lucas Cruz</dc:creator>
      <pubDate>Sun, 10 Mar 2024 00:03:30 +0000</pubDate>
      <link>https://dev.to/olucascruz/criando-uma-interface-de-escolha-de-fases-em-unity-54m</link>
      <guid>https://dev.to/olucascruz/criando-uma-interface-de-escolha-de-fases-em-unity-54m</guid>
      <description>&lt;p&gt;(Texto ainda em desenvolvimento)&lt;/p&gt;

&lt;p&gt;Estou criando um jogo mobile e nele haverá várias fases. É sempre bom ter uma tela que mostra as fases disponíveis e as fases trancadas.&lt;/p&gt;

&lt;p&gt;Primeiramente, antes de ir para Unity, geralmente desenho a interface no Figma, mas sinta-se à vontade para usar qualquer outra aplicação semelhante. Então, obtive esse resultado inicial:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fapg8nivyfldu6wariuhd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fapg8nivyfldu6wariuhd.png" alt="interface de escolha de fase" width="255" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A partir dessa ideia, vamos criar essa interface em Unity e torná-la interativa.&lt;/p&gt;

&lt;p&gt;Primeiro, como no Unity não temos objetos de UI como círculos por padrão, irei criar uma imagem com o editor de imagens GIMP:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgpp9pbvrlqx03yryv9ly.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgpp9pbvrlqx03yryv9ly.png" alt="circulo basico" width="428" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Então, para trazer para o Unity, toda essa parte será feita com o objeto Canvas. Os objetos interativos para selecionar fases serão botões TextMeshPro, as barras serão raw images e o texto será um TextMeshPro padrão.&lt;/p&gt;

&lt;p&gt;A estrutura ficou da seguinte forma:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fydkpdqpsap9wizdlypai.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fydkpdqpsap9wizdlypai.png" alt="Estrutura unity" width="223" height="258"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;E a interface assim:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmk96gab215rhauysf5j9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmk96gab215rhauysf5j9.png" alt="Interface" width="168" height="275"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;interface no simulador&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5vno943k3ltl5xk6atnb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5vno943k3ltl5xk6atnb.png" alt="interface no simulador" width="125" height="243"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A partir dessa interface pronta, é hora de pensar em uma estratégia para quando o usuário apertar o botão da fase escolhida e esse botão passar informações para a cena de jogo. Também por código, mudar o estado de disponibilidade do botão, para só permitir o clique nas fases já desbloqueadas.&lt;/p&gt;




&lt;h2&gt;
  
  
  Botões
&lt;/h2&gt;

&lt;p&gt;Para fazer os botões funcionarem você pode usar dois objetos&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcbus9m5dhsjlbe6kuxn8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcbus9m5dhsjlbe6kuxn8.png" alt="Image description" width="204" height="39"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Esses objetos ficam com os scripts de mudança de tela e de definir os elementos do nível, nesse caso uso para colocar a skin do enemy.&lt;/p&gt;

&lt;p&gt;SceneHandler:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using UnityEngine;
using UnityEngine.SceneManagement;

public class SceneHandler : MonoBehaviour
{
    public void LoadScene(string nameScene)
    {
        // Carrega a cena com o nome especificado
        SceneManager.LoadScene(nameScene);
    }

    public void ResetScene()
    {
        // Obtém o nome da cena atual
        string nameCurrentScene = SceneManager.GetActiveScene().name;

        // Recarrega a cena atual pelo seu nome
        SceneManager.LoadScene(nameCurrentScene);
    }

    public void Quit()
    {
        Application.Quit();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aqui eu uso a função LoadScene para carregar a cena de jogo, passando  o nome dela por parâmetro.&lt;/p&gt;

&lt;p&gt;e SetLevel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class SetLevel : MonoBehaviour
{
    [SerializeField] private List&amp;lt;Sprite&amp;gt; skinsEnemy;
    [SerializeField] private ElementsLevel configLevel;


    public void SetConfig(int num)
    {
        if (skinsEnemy.Count == 0)
        {
            Debug.LogError("Enemy skins list is empty");
            return;
        }

        if (num &amp;lt; 0 || num &amp;gt;= skinsEnemy.Count)
        {
            Debug.LogError("Provided number is out of bounds for the enemy skins list");
            num = 0;
        }

        Sprite currentSkinEnemy = skinsEnemy[num];
        configLevel.skinPaddleNPC = currentSkinEnemy;

    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aqui eu inicio uma lista de skins e um &lt;a href="https://docs.unity3d.com/Manual/class-ScriptableObject.html"&gt;ScriptableObject&lt;/a&gt; que é a estratégia que estou usando para definir a skin do inimigo.&lt;/p&gt;

&lt;p&gt;Em cada botão eu coloco o evento de click da seguinte maneira&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5dw49qwye4h2covv26cp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5dw49qwye4h2covv26cp.png" alt="Image description" width="298" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Escolho a skin que vai ser usada, o número sendo de 0 até o número de skins que tenho até o momento e a cena é a mesma GameOne&lt;/p&gt;

&lt;h2&gt;
  
  
  Definindo o ScriptableObject
&lt;/h2&gt;

&lt;p&gt;Para definir o scriptableObject faça assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[CreateAssetMenu(fileName = "ElementsLevel", menuName = "ElementsLevel", order = 1)]
/**
 * &amp;lt;summary&amp;gt;
 * Define game params.
 * &amp;lt;/summary&amp;gt;
 */
public class ElementsLevel : ScriptableObject
{
    public Sprite skinPlayer;
    public Sprite skinPaddleNPC;
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com esse scriptable object eu defino a skin que será usada pelo npc e dentro do nivel eu defino ela no objeto do npc usando um script 'Config Level'.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F09u3scll23yudfgg3p2i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F09u3scll23yudfgg3p2i.png" alt="Image description" width="330" height="96"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class ConfigLevel : MonoBehaviour
{

    [SerializeField] private SpriteRenderer paddleNPC;
    [SerializeField] private ElementsLevel configLevel;

    void Start()
    {
        paddleNPC.sprite = configLevel.skinPaddleNPC;
    }

}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>unity3d</category>
      <category>braziliandevs</category>
      <category>ui</category>
      <category>mobile</category>
    </item>
  </channel>
</rss>
