<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="pt-BR"><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://savi8sant8s.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://savi8sant8s.com/" rel="alternate" type="text/html" hreflang="pt-BR" /><updated>2026-08-11T13:45:09+00:00</updated><id>https://savi8sant8s.com/feed.xml</id><title type="html">Sávio Santos</title><subtitle>Portfólio e blog de Sávio Santos - Engenheiro de Software e Mestre focado em Inteligência Artificial, Visão Computacional e LLMs.</subtitle><author><name>Sávio Santos</name></author><entry><title type="html">Extreme Programming (XP) na Era da IA Generativa: Levando os Princípios ao Extremo Real</title><link href="https://savi8sant8s.com/extreme-programming-na-era-da-ia-generativa/" rel="alternate" type="text/html" title="Extreme Programming (XP) na Era da IA Generativa: Levando os Princípios ao Extremo Real" /><published>2026-08-05T00:00:00+00:00</published><updated>2026-08-05T00:00:00+00:00</updated><id>https://savi8sant8s.com/extreme-programming-na-era-da-ia-generativa</id><content type="html" xml:base="https://savi8sant8s.com/extreme-programming-na-era-da-ia-generativa/"><![CDATA[<p>Nos anos 90, Kent Beck apresentou o <strong>Extreme Programming (XP)</strong> com uma premissa simples, porém radical: <em>“Se uma prática de engenharia é boa, vamos levá-la ao extremo”</em>. Se testar o código é bom, testamos o tempo todo (TDD). Se fazer revisão de código é boa, revisamos o tempo todo (Pair Programming). Se integração contínua é boa, integramos várias vezes ao dia.</p>

<p>Por muitos anos, contudo, manter o XP exigia um esforço disciplinar enorme das equipes. O custo de escrever testes exaustivos, refatorar constantemente ou manter o alinhamento em pares nem sempre escalava sem fricção.</p>

<p>Com a popularização dos <strong>Modelos de Linguagem (LLMs), Copilotos e Agentes de Código</strong>, essa dinâmica mudou drasticamente. As IAs generativas de código não vieram para substituir a engenharia de software, mas sim para <strong>eliminar a fricção mecânica do desenvolvimento</strong>.</p>

<p>Ironicamente, a IA tornou os princípios do Extreme Programming mais atuais, práticos e extremamente viáveis do que nunca.</p>

<hr />

<h2 id="-a-recontextualização-dos-princípios-do-xp-com-ia">⚡ A Recontextualização dos Princípios do XP com IA</h2>

<h3 id="1-pair-programming-rightarrow-desenvolvedor-como-navigator-ia-como-driver">1. Pair Programming $\rightarrow$ Desenvolvedor como Navigator, IA como Driver</h3>
<p>No XP tradicional, dois desenvolvedores compartilham a mesma estação de trabalho: um <em>Driver</em> (escreve o código) e um <em>Navigator</em> (revisa em tempo real e pensa na arquitetura/cenários futuros).</p>

<p>Com assistentes e agentes modernos:</p>
<ul>
  <li><strong>A IA assume o papel de Driver:</strong> Escreve a sintaxe, cuida do <em>boilerplate</em>, lida com tipos e rascunha a implementação inicial.</li>
  <li><strong>O Engenheiro assume o papel definitivo de Navigator:</strong> Foca na validação dos requisitos de negócio, arquitetura do sistema, edge-cases e alinhamento com a intenção original.</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌────────────────────────────────────────────────────────┐
│               FLUXO DE PAIR PROGRAMMING                │
├───────────────────────────┬────────────────────────────┤
│         XP TRADICIONAL    │        XP + IA             │
├───────────────────────────┼────────────────────────────┤
│ Driver: Dev 1 (Sintaxe)   │ Driver: Agente de IA       │
│ Navigator: Dev 2 (Design) │ Navigator: Engenheiro      │
└───────────────────────────┴────────────────────────────┘
</code></pre></div></div>

<hr />

<h3 id="2-feedback-rápido--errar-mais-rápido">2. Feedback Rápido &amp; “Errar Mais Rápido”</h3>
<p>Um dos pilares morais do XP é que falhar cedo é infinitamente mais barato do que descobrir um erro em produção.</p>

<p>Antes, rodar uma hipótese de arquitetura ou protótipo levava dias. Com ferramentas de geração e execução assistida:</p>
<ul>
  <li>O ciclo de <strong>hipótese $\rightarrow$ código $\rightarrow$ execução $\rightarrow$ diagnóstico</strong> cai de horas para microssegundos.</li>
  <li>A IA permite gerar suítes de testes de estresse, simular falhas e validar ideias em minutos.</li>
  <li><strong>Errar rápido e barato</strong> tornou-se a vantagem competitiva central de quem desenvolve com agentes.</li>
</ul>

<hr />

<h3 id="3-tdd-test-driven-development-sem-a-barreira-do-custo">3. TDD (Test-Driven Development) sem a Barreira do Custo</h3>
<p>Apesar de ser aclamado, o TDD costumava ser abandonado em prazos apertados devido ao tempo necessário para escrever cenários de teste complexos e mocks.</p>

<p>Com IA, entramos no <strong>Generative-TDD</strong>:</p>
<ol>
  <li>O desenvolvedor escreve a especificação e as asserções de contrato (ou pede à IA para sugerir os cenários limite).</li>
  <li>A IA gera a suíte de testes unitários ou de integração (fase <em>Red</em>).</li>
  <li>O desenvolvedor/IA implementa a menor quantidade de código possível para fazer os testes passarem (fase <em>Green</em>).</li>
  <li>A IA sugere otimizações mantendo a suíte verde (fase <em>Refactor</em>).</li>
</ol>

<hr />

<h3 id="4-refatoração-merciless-sem-piedade">4. Refatoração Merciless (Sem Piedade)</h3>
<p>No XP clássico, o código deve ser constantemente limpo e simplificado. Porém, em sistemas legados grandes, refatorar sem quebrar dependências implícitas causava apreensão.</p>

<p>Com modelos de contexto amplo e análise estática via IA:</p>
<ul>
  <li>Refatorações de arquivos inteiros, renomeações de APIs, adequação a <em>design patterns</em> e migração de versões são realizadas de forma assistida e segura.</li>
  <li>A hesitação em “mexer no código que está funcionando” desaparece quando o custo do <em>Refactor</em> tende a zero e a suíte de testes valida as mudanças instantaneamente.</li>
</ul>

<hr />

<h3 id="5-design-simples-kiss--yagni">5. Design Simples (KISS / YAGNI)</h3>
<p>O princípio <strong>YAGNI</strong> (<em>You Aren’t Gonna Need It</em>) prega que você não deve adicionar funcionalidades até que sejam estritamente necessárias.</p>

<p>Com a IA capaz de gerar centenas de linhas em segundos, a tentação da superengenharia aumenta. É aqui que a disciplina XP se destaca:</p>
<ul>
  <li>O papel do engenheiro é <strong>restringir o escopo</strong> e exigir que a IA proponha o <strong>design mais simples possível</strong>.</li>
  <li>Em vez de aceitar abstrações desnecessárias criadas pelo modelo, o dev exige a solução mínima elegante.</li>
</ul>

<h2 id="-conclusão">🎯 Conclusão</h2>

<p>A IA não eliminou a necessidade de bons princípios de software — na verdade, aumentou o valor deles.</p>

<p>Um desenvolvedor sem método usando IA apenas produz <strong>código ruim mais rápido</strong>. Por outro lado, um desenvolvedor que aplica os princípios do Extreme Programming (feedback contínuo, simplicidade, testes e parceria de código) consegue multiplicar a entrega de valor com um nível de qualidade sem precedentes.</p>]]></content><author><name>Sávio Santos</name></author><summary type="html"><![CDATA[Como as IAs generativas e assistentes de código resgata ram os princípios do Extreme Programming (XP), eliminando o custo da iteração e tornando o desenvolvimento ágil verdadeiramente extremo.]]></summary></entry><entry><title type="html">Você realmente precisa de um LLM para processar uma planilha ou um JSON?</title><link href="https://savi8sant8s.com/voce-realmente-precisa-de-llm-para-processar-planilha-ou-json/" rel="alternate" type="text/html" title="Você realmente precisa de um LLM para processar uma planilha ou um JSON?" /><published>2026-08-04T00:00:00+00:00</published><updated>2026-08-04T00:00:00+00:00</updated><id>https://savi8sant8s.com/voce-realmente-precisa-de-llm-para-processar-planilha-ou-json</id><content type="html" xml:base="https://savi8sant8s.com/voce-realmente-precisa-de-llm-para-processar-planilha-ou-json/"><![CDATA[<p>Nos últimos anos, com a popularização dos Grandes Modelos de Linguagem (LLMs), vimos uma corrida para resolver qualquer problema de software jogando prompts na tela. Se o documento é um PDF não estruturado, um contrato escaneado ou uma transcrição de áudio, o LLM é fantástico e insubstituível.</p>

<p>Porém, quando o assunto é <strong>dado estruturado ou semi-estruturado (como planilhas Excel, CSVs ou grandes JSONs)</strong>, jogar a massa de dados inteira para a janela de contexto do modelo é um dos erros arquiteturais mais caros e ineficientes que podemos cometer.</p>

<p>A pergunta que devemos nos fazer é: <strong>Será que não existe uma maneira mais barata, rápida e precisa de resolver isso usando ferramentas determinísticas para auxiliar o modelo?</strong></p>

<p>Neste artigo, compartilho a filosofia de usar <strong>o LLM apenas como um compilador de intenção</strong>, delegando o processamento pesado para motores determinísticos.</p>

<hr />

<h2 id="-o-paradigma-llm-como-roteador-de-intenção-não-como-engine-de-execução">💡 O Paradigma: LLM como Roteador de Intenção, não como Engine de Execução</h2>

<p>Modelos de linguagem são probabilísticos. Eles são ótimos para inferir <em>o que</em> precisa ser feito, mas não para realizar operações matemáticas, paginações ou transformações repetitivas em grandes volumes de dados.</p>

<p>A literatura acadêmica e a prática de engenharia já comprovaram limitações severas da dependência cega da janela de contexto:</p>

<ol>
  <li><strong>Lost in the Middle</strong>: Pesquisadores de Stanford, UC Berkeley e Samaya AI (<em>Liu et al., 2023</em>) demonstraram no estudo <em>“Lost in the Middle: How Language Models Use Long Contexts”</em> que o desempenho dos LLMs cai drasticamente quando a informação necessária está no meio de um contexto longo, mesmo em modelos treinados para 100k+ tokens.</li>
  <li><strong>Custo e Latência Quadrática/Linear</strong>: Manter contextos massivos infla o custo por requisição e aumenta a latência de resposta a níveis inaceitáveis para produção.</li>
  <li><strong>Alucinação Numérica e Estrutural</strong>: LLMs prevêem o próximo <em>token</em> mais provável; eles não possuem uma ULA (Unidade Lógica e Aritmética) nativa para garantir agregamentos exatos ou estruturas de chave-valor estritas.</li>
</ol>

<h3 id="o-fluxo-híbrido-llm--motor-determinístico">O Fluxo Híbrido LLM + Motor Determinístico</h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌─────────────────┐       Sintaxe / Query       ┌────────────────────────┐
│   Prompt LLM    │ ──────────────────────────&gt; │  Motor Determinístico  │
│ (Intenção/DDL)  │                             │  (DuckDB / JSONata)    │
└─────────────────┘                             └────────────────────────┘
                                                            │
                                                     Dados │ Filtrados
                                                           ▼
                                                ┌────────────────────────┐
                                                │ Mapeador Programático  │
                                                │  (JSON de Saída 100%)  │
                                                └────────────────────────┘
</code></pre></div></div>

<ol>
  <li><strong>LLM (Probabilístico):</strong> Lê os metadados (esquema, nomes de colunas, chaves do JSON) + a intenção do usuário e gera uma instrução determinística (uma query SQL ou uma expressão JSONata).</li>
  <li><strong>Motor Determinístico:</strong> Executa essa instrução diretamente na memória do servidor com velocidade nativa (C++/Rust) e custo zero de tokens.</li>
  <li><strong>Mapeador Programático:</strong> Transforma o resultado no formato final esperado pela aplicação via código determinístico.</li>
</ol>

<hr />

<h2 id="-cenário-1-processando-planilhas-grandes-sem-estourar-contexto-o-padrão-duckdb">📊 Cenário 1: Processando Planilhas Grandes sem Estourar Contexto (O Padrão DuckDB)</h2>

<h3 id="o-problema-tradicional">O Problema Tradicional</h3>
<p>Você tem uma planilha Excel com milhares de linhas ou múltiplas abas e precisa extrair apenas certas informações para alimentar uma API. A abordagem ingênua é converter a planilha para texto/HTML/Markdown e injetar tudo no prompt.</p>

<h3 id="a-abordagem-determinística-duckdb--sql">A Abordagem Determinística (DuckDB + SQL)</h3>
<p>Em vez de enviar os dados da planilha para o modelo:</p>

<ol>
  <li><strong>Envie apenas o Esquema (<code class="language-plaintext highlighter-rouge">DDL</code>):</strong> Converta a planilha para tabelas temporárias no <a href="https://duckdb.org/">DuckDB</a> (um banco OLAP analítico de altíssima performance em memória) e extraia apenas a DDL dos esquemas (<code class="language-plaintext highlighter-rouge">CREATE TABLE table_0 ("data" DATE, "valor" DOUBLE, ...)</code>).</li>
  <li><strong>Peça ao LLM para Gerar SQL:</strong> O prompt recebe apenas o esquema e a lista de entidades desejadas. O LLM retorna uma consulta SQL compatível com DuckDB, utilizando <em>aliases</em> (<code class="language-plaintext highlighter-rouge">AS</code>) que correspondem exatamente aos identificadores dos campos solicitados.</li>
  <li><strong>Execução Local Nativa:</strong> O DuckDB executa a query em microssegundos direto na memória local.</li>
  <li><strong>Mapeamento via Código:</strong> Um script simples lê a tabela resultante já filtrada e monta a estrutura JSON de saída com 100% de precisão estrutural.</li>
</ol>

<blockquote>
  <p><strong>Ganha-se:</strong> Custo reduzido drasticamente (tokens caem de centenas de milhares para poucas centenas do esquema), zero risco de alucinação de dados e processamento instantâneo.</p>
</blockquote>

<hr />

<h2 id="-cenário-2-transformando-e-filtrando-jsons-complexos-o-padrão-jsonata">🔄 Cenário 2: Transformando e Filtrando JSONs Complexos (O Padrão JSONata)</h2>

<h3 id="o-problema-tradicional-1">O Problema Tradicional</h3>
<p>Você recebe um payload JSON gigante de uma API externa com dezenas de níveis aninhados, arrays e atributos irrelevantes, e precisa reformatar esse JSON para um esquema simplificado. Passar o JSON inteiro para o LLM reescrever é ineficiente e propício a erros de digitação de chaves.</p>

<h3 id="a-abordagem-determinística-jsonata">A Abordagem Determinística (JSONata)</h3>
<p>Em vez de pedir para o LLM reescrever a string do JSON:</p>

<ol>
  <li><strong>Apresente o Esquema ao LLM:</strong> Passe uma amostra das chaves do JSON e a estrutura desejada.</li>
  <li><strong>Gere uma Expressão JSONata:</strong> O LLM atua apenas gerando uma consulta declarativa em <a href="https://jsonata.org/">JSONata</a> (linguagem leve de consulta e transformação de dados JSON).</li>
  <li><strong>Execução pelo Evaluator JSONata:</strong> Um evaluator JSONata na sua aplicação aplica a expressão diretamente sobre o JSON original em memória.</li>
</ol>

<blockquote>
  <p><strong>Ganha-se:</strong> Nenhuma mutação acidental de dados, garantia de tipo, performance de microssegundos e facilidade de auditar a regra de transformação gerada.</p>
</blockquote>

<hr />

<h2 id="️-o-paralelo-com-agentes-modernos-ex-claude-code">🛠️ O Paralelo com Agentes Modernos (ex: Claude Code)</h2>

<p>Esta filosofia de não confiar a memória inteira ao LLM e sim delegar para ferramentas determinísticas não é nova. É a base de engenharia por trás do <a href="https://docs.anthropic.com/en/docs/agents-and-tools/claude-code/overview">Claude Code</a> e de agentes autônomos de código:</p>

<ul>
  <li><strong>Gerenciamento de Memória por Apontadores:</strong> O Claude Code não mantém o histórico completo do seu repositório na janela de contexto (o que destruiria o orçamento de tokens e a atenção do modelo).</li>
  <li><strong>Offloading para Sistema de Arquivos:</strong> Ele lê e grava arquivos locais (<code class="language-plaintext highlighter-rouge">CLAUDE.md</code>, arquivos temporários de planejamento) como estado de verdade e dispara ferramentas determinísticas nativas (<code class="language-plaintext highlighter-rouge">grep</code>, <code class="language-plaintext highlighter-rouge">glob</code>, <code class="language-plaintext highlighter-rouge">ast-grep</code>) para recortar cirurgicamente apenas as linhas necessárias antes de raciocinar sobre elas.</li>
</ul>

<hr />

<h2 id="️-pormenores-e-resiliência-na-prática">🛡️ Pormenores e Resiliência na Prática</h2>

<p>Quando aplicamos essa estratégia no dia a dia em produção, é crucial incluir pequenas camadas de proteção (Guardrails):</p>

<ol>
  <li><strong>Normalização Prévia de Esquemas:</strong> Nomes de colunas em planilhas humanas frequentemente vêm sujos, com espaços ou caracteres especiais. Fazer uma higienização simples (<code class="language-plaintext highlighter-rouge">col.strip().lower().replace(" ", "_")</code>) reduz falhas de sintaxe SQL drasticamente.</li>
  <li><strong>Prompts Rígidos de Identificadores:</strong> Instrua o LLM a sempre utilizar aspas duplas nos identificadores de colunas e tabelas (<code class="language-plaintext highlighter-rouge">"coluna" AS "entidade"</code>) para evitar erros de parser SQL no DuckDB.</li>
  <li><strong>Fallbacks Gracioso em Camadas:</strong> Se o LLM gerar uma consulta SQL/JSONata com erro de sintaxe, sua aplicação deve tratar o erro de forma resiliente:
    <ul>
      <li><strong>Fallback por Tabela:</strong> Se a query de uma aba falhar, capture o erro e recupere a tabela original completa via <code class="language-plaintext highlighter-rouge">SELECT * FROM table_name</code>.</li>
      <li><strong>Fallback por Pipeline:</strong> Se o motor falhar por completo, a aplicação pode recorrer à estratégia tradicional de loteamento/paginação.</li>
    </ul>
  </li>
</ol>

<hr />

<h2 id="-conclusão">📌 Conclusão</h2>

<p>Sempre que você estiver prestes a enviar uma massa de dados estruturados para um LLM, pergunte-se: <strong>Eu preciso que a IA processe estes dados, ou preciso apenas que ela entenda o que fazer e escreva a instrução de processamento?</strong></p>

<p>Na maioria das vezes, combinar a capacidade de interpretação do LLM com motores determinísticos em memória como <strong>DuckDB</strong> e <strong>JSONata</strong> vai te entregar uma solução mais barata, infinitamente mais rápida e com zero margem para alucinações.</p>]]></content><author><name>Sávio Santos</name></author><summary type="html"><![CDATA[Por que terceirizar o processamento de dados estruturados e semi-estruturados para LLMs é ineficiente e como combinar motores determinísticos (DuckDB, JSONata) para obter 100% de precisão com custo reduzido.]]></summary></entry><entry><title type="html">Mapeando a Tech Stack de 5.571 Prefeituras do Brasil: Um Estudo com Python e Async I/O</title><link href="https://savi8sant8s.com/mapeando-tech-stack-prefeituras-brasil/" rel="alternate" type="text/html" title="Mapeando a Tech Stack de 5.571 Prefeituras do Brasil: Um Estudo com Python e Async I/O" /><published>2026-08-02T00:00:00+00:00</published><updated>2026-08-02T00:00:00+00:00</updated><id>https://savi8sant8s.com/mapeando-tech-stack-prefeituras-brasil</id><content type="html" xml:base="https://savi8sant8s.com/mapeando-tech-stack-prefeituras-brasil/"><![CDATA[<p>Você já parou para pensar em qual tecnologia roda nos sites dos municípios do Brasil? Seja para emitir uma nota fiscal, consultar o Diário Oficial ou acessar o Portal da Transparência, milhões de cidadãos interagem diariamente com a infraestrutura tecnológica das prefeituras.</p>

<p>Para responder a essa pergunta com dados reais, desenvolvi um <strong>inspector de tecnologia assíncrono em Python</strong> capaz de coletar, resolver domínios e analisar a <em>tech stack</em> de todas as <strong>5.571 prefeituras catalogadas pelo IBGE</strong>.</p>

<p>Neste artigo, compartilho os principais achados do estudo, os gráficos com as estatísticas nacionais e os detalhes técnicos do crawler que desenvolvi.</p>

<hr />

<h2 id="-principais-descobertas-e-análise-dos-dados">📊 Principais Descobertas e Análise dos Dados</h2>

<p>Dos <strong>5.571 municípios</strong> catalogados pelo IBGE, o crawler localizou e analisou com sucesso <strong>5.107 prefeituras ativas (91,67% de taxa de resolução)</strong>.</p>

<h3 id="1-php-é-o-rei-absoluto-do-backend-municipal">1. PHP é o Rei Absoluto do Backend Municipal</h3>
<p>Ao analisar as linguagens e linguagens server-side identificadas:</p>

<p><img src="/images/tech-backend-chart.png" alt="Linguagens e Frameworks Backend" /></p>

<ul>
  <li><strong>PHP</strong>: Está presente em <strong>77,8% (3.973 prefeituras)</strong> dos sites analisados.</li>
  <li><strong>ASP.NET (Microsoft)</strong>: Representa <strong>26,2% (1.338 sites)</strong>, refletindo portais legados e sistemas corporativos.</li>
  <li><strong>Java</strong>: Presente em <strong>16,4% (838 sites)</strong>.</li>
  <li><strong>Laravel (PHP)</strong>: Aparece em <strong>8,0% (408 sites)</strong> como a escolha moderna para novos portais sob medida.</li>
  <li><strong>Python e Node.js</strong>: Representam juntos cerca de 5,5% do total.</li>
</ul>

<hr />

<h3 id="2-cms-wordpress-domina-a-comunicação-institucional">2. CMS: WordPress Domina a Comunicação Institucional</h3>
<p>Em termos de Gerenciadores de Conteúdo (CMS):</p>

<ul>
  <li><strong>WordPress</strong>: É a plataforma isolada mais utilizada, identificada em <strong>mais de 1.480 prefeituras (~30% do total)</strong>.</li>
  <li><strong>Joomla</strong>: Mantém presença histórica em <strong>170 prefeituras</strong>.</li>
  <li><strong>Drupal &amp; GovBR/Plone</strong>: Utilizados principalmente por capitais e grandes metrópoles devido aos requisitos de acessibilidade e governança.</li>
  <li><strong>Wix</strong>: Identificado em 72 pequenos municípios.</li>
</ul>

<hr />

<h3 id="3-servidores-web-e-a-crescente-adoção-de-cloudflare">3. Servidores Web e a Crescente Adoção de Cloudflare</h3>

<p><img src="/images/tech-servers-chart.png" alt="Servidores Web e CDN" /></p>

<ul>
  <li><strong>Apache (32,5%)</strong> e <strong>Nginx (26,1%)</strong> dividem a liderança do processamento web.</li>
  <li><strong>Cloudflare</strong>: Detectado em <strong>994 sites (19,4%)</strong>, revelando uma forte preocupação das prefeituras com proteção contra ataques de negação de serviço (DDoS), aceleração via CDN e certificados SSL gratuitos.</li>
</ul>

<hr />

<h3 id="4-frontend-bootstrap-universal-e-elementor-em-alta">4. Frontend: Bootstrap Universal e Elementor em Alta</h3>

<p><img src="/images/tech-frontend-chart.png" alt="Frameworks Frontend" /></p>

<ul>
  <li><strong>Bootstrap</strong>: Presente em impressionantes <strong>86,3% (4.406 sites)</strong> dos portais. Tornou-se o padrão <em>de facto</em> para garantir responsividade no setor público.</li>
  <li><strong>jQuery</strong>: Ainda acompanha <strong>55,5% (2.836 sites)</strong>.</li>
  <li><strong>Elementor</strong>: O page builder visual do WordPress foi detectado em <strong>551 prefeituras (10,8%)</strong>, facilitando a edição por equipes municipais sem conhecimento técnico de código.</li>
  <li><strong>React &amp; Vue.js</strong>: Apresentam adoção em crescimento (5,2% e 2,0% respectivamente), impulsionados por novos portais de transparência construídos como Single Page Applications (SPAs).</li>
</ul>

<hr />

<h2 id="️-a-engenharia-por-trás-do-crawler-3-minutos-para-5570-sites">🛠️ A Engenharia por Trás do Crawler (3 Minutos para 5.570 Sites)</h2>

<p>Varrer mais de 5.500 domínios com checagem de respostas HTTP, parsing de cabeçalhos e análise de HTML pode levar horas se feito de forma síncrona.</p>

<p>Para resolver o problema da escala e da performance, a arquitetura do projeto foi estruturada em módulos desacoplados:</p>

<ol>
  <li><strong>Coleta de Dados e Resolução de Domínios</strong>:
    <ul>
      <li>Integração com a API do IBGE + cruzamento com dados abertos da comunidade.</li>
      <li>Algoritmo de normalização e permutação de URLs (<code class="language-plaintext highlighter-rouge">.gov.br</code>, <code class="language-plaintext highlighter-rouge">pm...gov.br</code>, sem conectores <em>de/da/do</em>).</li>
    </ul>
  </li>
  <li><strong>I/O Assíncrono com <code class="language-plaintext highlighter-rouge">aiohttp</code> e <code class="language-plaintext highlighter-rouge">asyncio</code></strong>:
    <ul>
      <li>Utilização de <code class="language-plaintext highlighter-rouge">asyncio.Semaphore</code> para controlar a concorrência sem sobrecarregar a rede ou a resolução DNS local.</li>
      <li>Ajuste de <em>connect timeout</em> para 2.5s, descartando rapidamente domínios inativos sem travar o worker.</li>
      <li>Com concorrência em <strong>100 requisições simultâneas</strong>, o pipeline completo executou em <strong>apenas 2 minutos e 40 segundos</strong> (uma taxa de ~30 sites/segundo).</li>
    </ul>
  </li>
  <li><strong>Tech Inspector (Fingerprinting)</strong>:
    <ul>
      <li>Inspeção de cabeçalhos HTTP (<code class="language-plaintext highlighter-rouge">X-Powered-By</code>, <code class="language-plaintext highlighter-rouge">Server</code>, <code class="language-plaintext highlighter-rouge">Set-Cookie</code>, <code class="language-plaintext highlighter-rouge">X-Generator</code>).</li>
      <li>Parsing do HTML com <code class="language-plaintext highlighter-rouge">BeautifulSoup</code> em busca de meta tags, caminhos de scripts estáticos (<code class="language-plaintext highlighter-rouge">wp-content</code>, <code class="language-plaintext highlighter-rouge">sites/all/themes</code>) e objetos em memória de frameworks SPA/SSR (<code class="language-plaintext highlighter-rouge">__NEXT_DATA__</code>, <code class="language-plaintext highlighter-rouge">__NUXT__</code>).</li>
    </ul>
  </li>
</ol>

<hr />

<h2 id="️-limitações-da-pesquisa-os-833-não-raspados">⚠️ Limitações da Pesquisa: Os 8,33% Não Raspados</h2>

<p>Cerca de <strong>464 prefeituras (8,33%)</strong> não puderam ter sua <em>tech stack</em> raspada ou identificada durante esta edição da pesquisa. As razões observadas foram:</p>

<ol>
  <li><strong>Domínios Inativos ou Inexistentes</strong>: Pequenos municípios que não possuem portal próprio oficial ativo no momento da varredura.</li>
  <li><strong>Bloqueios de Segurança (WAF / Rate Limit)</strong>: Firewalls que rejeitam requisições automatizadas em lote sem navegação completa de browser.</li>
  <li><strong>Erros de SSL/TLS &amp; Servidores Fora do Ar</strong>: Certificados com erro de cadeia ou servidores temporariamente inalcançáveis.</li>
</ol>

<hr />

<h2 id="-créditos-e-fontes-de-dados-abertos">🤝 Créditos e Fontes de Dados Abertos</h2>

<p>Construir um estudo dessa magnitude exige reconhecer o trabalho fundamental da comunidade de dados abertos no Brasil:</p>

<ul>
  <li><strong>API de Localidades do IBGE</strong>: Fonte dos dados cadastrais dos 5.571 municípios.</li>
  <li><strong>Dataset <a href="https://github.com/franklinbaldo/sites_prefeituras"><code class="language-plaintext highlighter-rouge">sites_prefeituras</code></a></strong>: Crédito e agradecimento especial ao projeto mantido por <strong><a href="https://github.com/franklinbaldo">Franklin Baldo</a></strong>. A base pré-catalogada de URLs municipais acelerou significativamente a resolução de domínios.</li>
</ul>

<hr />

<h2 id="-conclusão">🎯 Conclusão</h2>

<p>O estudo revela uma infraestrutura municipal brasileira fortemente ancorada no ecossistema <strong>PHP + WordPress + Bootstrap + Apache/Nginx</strong>, combinada com uma transição contínua para camadas de segurança em nuvem (Cloudflare).</p>

<h3 id="código-fonte-e-dataset-aberto">Código-Fonte e Dataset Aberto</h3>

<p>O projeto completo, com código-fonte em Python estruturado em módulos e o dataset final em CSV e JSON com as 5.571 prefeituras, está disponível publicamente no GitHub:</p>

<p>🔗 <strong><a href="https://github.com/savi8sant8s/stacks-usadas-sites-prefeituras-brasil">GitHub: stacks-usadas-sites-prefeituras-brasil</a></strong></p>

<p>Sinta-se à vontade para explorar o repositório, clonar o projeto ou utilizar a base de dados em suas próprias análises!</p>]]></content><author><name>Sávio Santos</name></author><summary type="html"><![CDATA[Analisamos mais de 5.500 sites de prefeituras brasileiras para descobrir quais linguagens, CMS, servidores web e frameworks dominam a gestão pública municipal.]]></summary></entry></feed>