ProxynetProxynet

O que é parsing de dados? Tipos, erros e exemplos

Publicado:

15 min de leitura

Acar Diveroli
Autor: Acar Diveroli
Fios brancos emaranhados com trechos de código chegam a um núcleo azul; trilhos levam a quatro linhas e uma rejeitada

Um scraper baixa a página de um produto e a salva em disco. O arquivo tem 180 KB de HTML e, em algum lugar dentro dele, estão as quatro coisas que você realmente queria: o nome do produto, o preço, a disponibilidade em estoque e o SKU. Até que um programa encontre esses valores, confira-os e grave-os em campos com nome, o download é só texto. Essa etapa, do texto bruto aos campos, é a análise sintática de dados (parsing).

Este artigo explica o que significa parsing, como um parser trabalha (duas etapas centrais e os passos em volta delas) e que tipo de parser serve para HTML, JSON, CSV, logs e formatos próprios. Ele separa o parsing do scraping e da extração, mostra um exemplo curto e testado em Python com BeautifulSoup e o módulo json, cobre os erros que quebram parsers em projetos reais (HTML malformado, JSON inválido, desvio de esquema) e termina com um guia para decidir entre construir ou comprar.

O que é parsing de dados?

Fazer parsing significa analisar uma entrada segundo um conjunto de regras e produzir uma estrutura que represente o que essa entrada diz. A entrada costuma ser uma string ou um fluxo de bytes. A saída é algo com nomes e tipos: uma árvore de elementos HTML, um dicionário Python, uma lista de linhas, um registro com um campo price que guarda um número em vez do texto "$1,249.00".

O seu navegador faz o parsing do HTML para montar a página, o seu cliente de API faz o parsing do JSON em objetos, a sua planilha faz o parsing do CSV em células. Você só percebe o parsing quando a entrada não corresponde ao que o parser esperava, e o programa para com um erro ou, pior, segue em frente com valores errados.

No trabalho com dados, a palavra é usada em duas camadas:

  • Parsing do formato. Transformar bytes na estrutura própria do formato: HTML em uma árvore DOM, JSON em objetos, CSV em linhas. As bibliotecas fazem isso.
  • Parsing de dados no sentido estrito. Pegar essa estrutura e tirar dela os valores de que você precisa, com os tipos certos: o preço como decimal, a data como data, o estoque como verdadeiro ou falso. Essa parte normalmente é você quem escreve.

Como um parser funciona?

Quase todo parser, de uma biblioteca JSON ao motor HTML de um navegador, segue as mesmas duas etapas centrais, a análise léxica e a análise sintática, com um passo de leitura antes e a seleção de valores e a validação depois.

  1. Ler a entrada como texto. Os bytes são decodificados em caracteres com uma codificação, normalmente UTF-8. Um palpite errado aqui produz caracteres embaralhados antes mesmo de o parsing começar; erros de codificação Unicode em Python trata dessa falha.
  2. Tokenizar (análise léxica). O parser corta o fluxo de caracteres em tokens, as menores partes com significado: uma tag de abertura, um atributo, uma string, um número, uma vírgula, uma chave de fechamento.
  3. Montar a estrutura (análise sintática). Os tokens são organizados segundo a gramática do formato. No HTML, o resultado é uma árvore de elementos aninhados; no JSON, objetos e arrays aninhados; no CSV, linhas de campos.
  4. Selecionar os valores. O seu código percorre a estrutura e escolhe os campos de que precisa, por exemplo com um seletor CSS ou XPath sobre uma árvore HTML. Seletor CSS vs XPath compara as duas formas de apontar para um elemento.
  5. Converter e validar. O texto vira dado tipado: "$34.50" vira 34.50, "In stock" vira true. Registros sem um campo obrigatório são sinalizados em vez de salvos em silêncio.

O padrão HTML descreve o parser de um navegador exatamente com essas etapas. O capítulo de parsing do WHATWG o divide em tokenização e construção da árvore, e também define como um parser deve se recuperar de erros; é por isso que os navegadores mostram páginas quebradas em vez de recusá-las.

Parsing, scraping e extração: qual a diferença

As três palavras são usadas muitas vezes como sinônimos, mas nomeiam etapas diferentes de um mesmo pipeline.

TermoO que fazEntradaSaída
CrawlingEncontra páginas seguindo linksUma URL inicialUma lista de URLs
ScrapingBaixa o conteúdo dessas páginasURLsHTML, JSON ou arquivos brutos
ParsingTransforma conteúdo bruto em estruturaTexto brutoÁrvores, objetos, linhas
ExtraçãoEscolhe os valores necessários dentro da estruturaUma árvore ou objetoCampos com nome
Validação e limpezaConfere tipos, remove duplicatas, corrige formatosCamposRegistros confiáveis
ArmazenamentoGrava os registros em algum lugarRegistrosCSV, JSON Lines, um banco de dados

No dia a dia, "parsing" cobre parsing, extração e parte da validação ao mesmo tempo, e é nesse sentido que o termo aparece no restante do artigo. Crawling e scraping são o lado da coleta; web scraping vs web crawling explica essa divisão. Onde os registros vão parar é o tema de como salvar dados de scraping em CSV, JSON e SQLite, e a cadeia inteira como um processo repetível é o assunto de O que é ETL?.

Tipos de parsers

Entradas diferentes pedem parsers diferentes. Usar o tipo errado, por exemplo uma expressão regular sobre HTML aninhado, é a origem de muitos scrapers frágeis.

Tipo de parserMelhor paraExemplosPonto fraco
Parser HTML / DOMPáginas web, inclusive com marcação quebradaBeautifulSoup com html.parser, lxml ou html5lib; Cheerio no Node.jsDepende de seletores que mudam quando o layout da página muda
Parser JSONRespostas de API, dados embutidos na páginajson do Python, JSON.parse no JavaScriptRígido: uma vírgula a mais derruba o documento inteiro
Parser CSV / delimitadoExportações, planilhas, relatórioscsv do Python, read_csv do pandasAspas, delimitadores e codificações variam conforme quem gera o arquivo
Parser XMLFeeds, sitemaps, APIs corporativas antigaslxml, xml.etree.ElementTreeNamespaces deixam os seletores prolixos
Expressões regularesPadrões pequenos e planos dentro de um campo conhecido: preços, datas, IDsre do PythonNão acompanham aninhamento; quebram com mudanças de layout
Parser baseado em gramáticaFormatos próprios, linguagens de consulta, arquivos de configuraçãoGeradores de parser como ANTLR, LarkEscrever a gramática leva tempo
Parser baseado em modelosTexto bagunçado sem layout fixoModelos de linguagem que retornam JSONA saída precisa ser validada; os resultados podem variar entre execuções

Duas linhas merecem um comentário. Parsers HTML não são iguais: o BeautifulSoup funciona sobre um parser que você escolhe, e a sua documentação mostra o trecho quebrado <a></p> gerando três árvores diferentes em html.parser, lxml e html5lib. Indique o parser de forma explícita, ou a sua saída pode mudar em uma máquina que tenha outro instalado. O parsing baseado em modelos é o modo como os scrapers com IA leem páginas cujo layout muda o tempo todo; ele troca regras exatas por flexibilidade, então a validação importa ainda mais, como explica como funcionam os web scrapers com IA.

Um exemplo curto de parsing em Python

O exemplo faz o parsing de uma pequena página de produtos com um parser HTML, seletores CSS, uma expressão regular para o campo de preço, uma checagem de campos obrigatórios e um parsing JSON separado para os dados embutidos na página. Salve isto como page.html; o segundo card tem um <span> sem fechamento e o terceiro não tem preço:

html
<!doctype html>
<html lang="en">
<head>
  <title>Desk lamps</title>
  <script type="application/ld+json">
  {"@context": "https://schema.org", "@type": "ItemList",
   "itemListElement": [
     {"@type": "ListItem", "position": 1, "url": "/p/arc-lamp"},
     {"@type": "ListItem", "position": 2, "url": "/p/clip-lamp"}
   ]}
  </script>
</head>
<body>
  <div class="product" data-sku="L-100">
    <h2 class="name">Arc Desk Lamp</h2>
    <span class="price">$1,249.00</span>
    <span class="stock">In stock</span>
  </div>
  <div class="product" data-sku="L-200">
    <h2 class="name">  Clip Lamp </h2>
    <span class="price">$34.50</span>
    <span class="stock">Out of stock
  </div>
  <div class="product" data-sku="L-300">
    <h2 class="name">Floor Lamp</h2>
    <span class="stock">In stock</span>
  </div>
</body>
</html>

Instale as duas bibliotecas com pip install beautifulsoup4 lxml e salve isto como parse_products.py ao lado da página:

python
import json
import re
from decimal import Decimal
from pathlib import Path

from bs4 import BeautifulSoup

PRICE_RE = re.compile(r"[\d.,]+")


def parse_price(text):
    """'$1,249.00' -> Decimal('1249.00'); None se não houver número."""
    match = PRICE_RE.search(text or "")
    if not match:
        return None
    return Decimal(match.group().replace(",", ""))


def parse_products(html):
    soup = BeautifulSoup(html, "lxml")
    rows, problems = [], []

    for card in soup.select("div.product"):
        name = card.select_one(".name")
        price = card.select_one(".price")
        stock = card.select_one(".stock")
        row = {
            "sku": card.get("data-sku"),
            "name": name.get_text(strip=True) if name else None,
            "price": parse_price(price.get_text()) if price else None,
            "in_stock": stock is not None and stock.get_text(strip=True) == "In stock",
        }
        missing = [key for key in ("sku", "name", "price") if row[key] is None]
        if missing:
            problems.append({"sku": row["sku"], "missing": missing})
            continue
        rows.append(row)

    # Dados estruturados embutidos na página: faça o parsing como JSON, não como HTML.
    urls = []
    for tag in soup.select('script[type="application/ld+json"]'):
        try:
            data = json.loads(tag.string or "")
        except json.JSONDecodeError as err:
            problems.append({"json_ld": f"line {err.lineno}, col {err.colno}: {err.msg}"})
            continue
        urls += [item.get("url") for item in data.get("itemListElement", [])]

    return rows, urls, problems


if __name__ == "__main__":
    html = Path("page.html").read_text(encoding="utf-8")
    rows, urls, problems = parse_products(html)
    print(json.dumps(rows, indent=2, default=str))
    print("urls:", urls)
    print("problems:", problems)

Rodar python parse_products.py com BeautifulSoup 4.15.0, lxml 6.1.3 e Python 3.13 imprime:

text
[
  {
    "sku": "L-100",
    "name": "Arc Desk Lamp",
    "price": "1249.00",
    "in_stock": true
  },
  {
    "sku": "L-200",
    "name": "Clip Lamp",
    "price": "34.50",
    "in_stock": false
  }
]
urls: ['/p/arc-lamp', '/p/clip-lamp']
problems: [{'sku': 'L-300', 'missing': ['price']}]

O <span> sem fechamento não quebrou nada porque o lxml consertou a árvore, o nome com espaços saiu limpo e a luminária sem preço foi para problems em vez de ser salva vazia. Quando, como teste, acrescentamos uma vírgula final ao bloco JSON-LD, o script continuou rodando e informou line 5, col 64: Illegal trailing comma before end of object, o que aponta direto para o defeito. JSONDecodeError: Expecting Value lista as outras mensagens que esse parser gera e o que causa cada uma.

O mesmo parser escrito para Node.js usa Cheerio em vez de BeautifulSoup; veja web scraping com Cheerio. Para um scraper completo com requisições, paginação e gravação, comece pelo tutorial de BeautifulSoup.

Erros comuns de parsing e suas causas

  • HTML malformado. Tags sem fechamento, tags de fechamento soltas e tags no lugar errado são normais na web. Navegadores e parsers HTML as consertam, mas cada parser do seu jeito, então um seletor que funciona com html5lib pode falhar com html.parser. Fixe a escolha do parser e teste com páginas salvas.
  • JSON inválido. JSON é rígido. A RFC 8259 define a gramática, e vírgulas finais, aspas simples e comentários não fazem parte dela. Uma causa frequente nem é JSON: o servidor devolveu uma página de erro HTML ou um corpo vazio, e o parser JSON falha no primeiro caractere.
  • Chaves duplicadas. A RFC 8259 diz que, quando nomes se repetem em um objeto, o comportamento de quem recebe é imprevisível. O módulo json do Python fica com o último valor sem gerar erro, então {"price": 10, "price": 12} vira 12 em silêncio.
  • Aspas e delimitadores no CSV. Uma vírgula dentro do nome de um produto divide um campo em dois se ele não estiver entre aspas. A RFC 4180 descreve a convenção de aspas mais comum, mas é apenas informativa, e muitas exportações usam ponto e vírgula ou tabulação. Use uma biblioteca CSV, nunca line.split(",").
  • Números e datas conforme a região. 1.249,00 passa de mil na Alemanha e dá pouco mais de um em um parser ingênuo; 03/04/2026 é março ou abril dependendo do país. Faça o parsing com um formato explícito para cada fonte.
  • Desvio de esquema (schema drift). O site renomeia uma classe ou move o preço para um novo elemento, e o parser continua rodando, mas retorna None ou o valor errado. Nada quebra, e é isso que torna essa a falha mais cara. Checagens de campos obrigatórios, como a lista problems acima, transformam o desvio silencioso em uma contagem visível.
  • Conteúdo que não está no HTML. Algumas páginas montam o conteúdo com JavaScript depois de carregar, então os dados nunca estiveram no arquivo baixado. Páginas estáticas vs dinâmicas mostra como diferenciar.

Construir ou comprar um parser?

Para formatos padrão, você nunca escreve o parser de baixo nível; as bibliotecas estão maduras. A decisão é sobre a camada de extração que fica em cima: seletores, conversões e checagens por site.

Construa você mesmo quando tiver um número limitado de fontes que mudam pouco. O seu próprio código é transparente, não custa nada por página e é fácil de testar com amostras salvas.

Use uma ferramenta ou um serviço pronto quando acompanhar centenas de sites cujo layout muda com frequência, ou quando a entrada não tiver layout fixo nenhum, como e-mails e PDFs. Você paga por volume ou por usuário e aceita menos controle sobre a saída.

Um modelo híbrido é comum: APIs oficiais ou JSON embutido onde existirem, parsers escritos à mão para as fontes principais, uma alternativa baseada em modelos para a cauda longa e a mesma etapa de validação antes do armazenamento para os três.

Onde o parsing é usado

  • Coleta de dados em escala. Todo pipeline de scraping faz parsing entre o download e o banco de dados; veja data scraping.
  • Crawlers e auditorias de sites. Um crawler faz o parsing de cada página em busca de links e metadados; veja web crawler.
  • Monitoramento de preços. Preços convertidos em números podem ser comparados ao longo do tempo, como no monitoramento de preços da concorrência.
  • Monitoramento de mudanças. Comparar campos já processados em vez do HTML bruto evita alarmes falsos causados por anúncios e carimbos de data e hora; veja monitoramento de mudanças em sites.
  • Análise de dados. Registros tipados são o ponto de partida para encontrar padrões; veja O que é mineração de dados?.
  • Logs e segurança. As linhas de log passam por parsing em carimbo de data e hora, endereço IP, status e caminho antes que alguém consiga contar os erros.

Erros frequentes

  • Fazer parsing do site ao vivo enquanto desenvolve. Salve algumas páginas reais em disco e escreva o parser em cima delas: menos requisições ao site e testes repetíveis.
  • Usar regex em documentos HTML inteiros. Faça primeiro o parsing da árvore e use regex só dentro do texto de um único campo.
  • Guardar preços como texto ou float. Converta cedo para Decimal ou para centavos inteiros e mantenha a string original para depuração.
  • Engolir todas as exceções. Um try/except: pass sem nada oculta o desvio de esquema. Registre as falhas com o ID do registro e confira a contagem depois de cada execução.
  • Ignorar o JSON embutido. Muitas páginas de produto trazem JSON-LD com os mesmos valores em uma forma mais limpa que o HTML visível.
  • Culpar o parser por requisições bloqueadas. Quando o "HTML" é uma página de bloqueio ou um erro 429, nenhum seletor vai corresponder. Verifique o código de status antes do parsing e diminua o ritmo se o site pedir.

Guia de decisão

A sua entradaAbordagem recomendada
Uma API que retorna JSONUse a API; faça o parsing com a biblioteca JSON padrão e valide os campos obrigatórios
Páginas HTML estáticas de poucos sitesBeautifulSoup com lxml, ou Cheerio no Node.js, mais seletores CSS
Páginas que renderizam o conteúdo com JavaScriptProcure primeiro JSON embutido ou a API do site; use um navegador headless só se for preciso
Exportações CSV ou planilhasUma biblioteca CSV ou pandas, com delimitador e codificação definidos de forma explícita
Logs de servidor em formato fixoRegex por linha ou um parser de logs, e depois converter os campos para os tipos certos
Um formato de texto próprio que você controlaUm parser baseado em gramática (ANTLR, Lark)
E-mails, PDFs, texto livre sem layoutUm extrator baseado em modelos com validação rígida da saída
Centenas de sites com layouts que mudamUm serviço comercial de parsing ou uma configuração híbrida

Perguntas frequentes

O que é parsing de dados em termos simples?

É ler texto bruto e transformá-lo em partes rotuladas que um programa pode usar. Entra uma página web e sai um registro com nome, preço e disponibilidade em estoque.

Qual a diferença entre parsing e scraping?

O scraping baixa conteúdo de um site; o parsing transforma esse conteúdo em dados estruturados. Um scraper sem parser deixa você com arquivos HTML brutos.

Qual biblioteca Python é usada para fazer parsing de HTML?

O BeautifulSoup é a mais usada e funciona sobre html.parser, lxml ou html5lib. O lxml também pode ser usado diretamente e suporta XPath. Para JSON, o módulo nativo json basta.

Posso fazer parsing de HTML com expressões regulares?

Só para trechos de texto muito pequenos e planos. O HTML é aninhado e muitas vezes quebrado, e uma expressão regular não consegue acompanhar o aninhamento. Faça o parsing da página com um parser HTML e, se precisar, use regex dentro de um único campo.

Por que o meu parser de repente retorna valores vazios?

Geralmente o site mudou a marcação e os seus seletores não correspondem mais. Outras causas: uma página de erro no lugar do conteúdo, ou conteúdo carregado depois por JavaScript.

Preciso de proxy para fazer parsing de dados?

O parsing em si roda na sua própria máquina e não precisa de proxy. Os proxies importam no lado da coleta, quando um scraper reúne páginas públicas em volume ou precisa ver uma página como os visitantes de outro país a veem. Os endereços de Proxies residenciais permitem escolher país e cidade, e o Proxies rotativos distribui as requisições entre vários endereços; em qualquer caso, respeite os termos e os limites de taxa de cada site.

Em resumo

O parsing de dados transforma uma entrada bruta em registros estruturados e tipados: um tokenizador corta o texto em partes, um parser as organiza segundo as regras do formato e o seu código escolhe, converte e confere os valores de que precisa. Escolha o parser pela entrada e mantenha a regex dentro de campos individuais. A maior parte do trabalho em um projeto real vai para as falhas, principalmente o desvio de esquema que nenhuma mensagem de erro anuncia; por isso, valide cada registro e conte as falhas depois de cada execução. Quando o lado da coleta precisar de endereços em países específicos, veja os nossos serviços de proxy.