---
title: "O que é parsing de dados? Tipos, erros e exemplos"
description: "O parsing de dados transforma HTML, JSON, CSV ou logs em registros estruturados para o seu código. Como um parser funciona, os tipos e os erros mais comuns."
url: https://proxynet.io/pt-br/blog/what-is-data-parsing
date: 2026-09-28
author: "Acar Diveroli"
category: "Web scraping, Proxy 101"
lang: pt-BR
---

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

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.

> **Nota: Resposta rápida**
>
> Parsing de dados é o processo de ler uma entrada bruta, como uma página HTML, uma resposta JSON, um arquivo CSV ou uma linha de log, e transformá-la em uma estrutura com a qual um programa consegue trabalhar: objetos, linhas ou pares chave-valor. Um parser primeiro divide a entrada em tokens e depois organiza esses tokens de acordo com as regras do formato. No web scraping, o scraper busca a página e o parser transforma essa página em registros limpos, que depois são validados e armazenados.

## 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](/pt-br/blog/python-unicode-encoding-errors) trata dessa falha.
1. **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.
1. **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.
1. **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](/pt-br/blog/css-selector-vs-xpath) compara as duas formas de apontar para um elemento.
1. **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](https://html.spec.whatwg.org/multipage/parsing.html) 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.

| Termo | O que faz | Entrada | Saída |
|---|---|---|---|
| Crawling | Encontra páginas seguindo links | Uma URL inicial | Uma lista de URLs |
| Scraping | Baixa o conteúdo dessas páginas | URLs | HTML, JSON ou arquivos brutos |
| Parsing | Transforma conteúdo bruto em estrutura | Texto bruto | Árvores, objetos, linhas |
| Extração | Escolhe os valores necessários dentro da estrutura | Uma árvore ou objeto | Campos com nome |
| Validação e limpeza | Confere tipos, remove duplicatas, corrige formatos | Campos | Registros confiáveis |
| Armazenamento | Grava os registros em algum lugar | Registros | CSV, 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](/pt-br/blog/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](/pt-br/blog/save-scraped-data-csv-json-sqlite), e a cadeia inteira como um processo repetível é o assunto de [O que é ETL?](/pt-br/blog/what-is-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 parser | Melhor para | Exemplos | Ponto fraco |
|---|---|---|---|
| Parser HTML / DOM | Páginas web, inclusive com marcação quebrada | BeautifulSoup com `html.parser`, `lxml` ou `html5lib`; Cheerio no Node.js | Depende de seletores que mudam quando o layout da página muda |
| Parser JSON | Respostas de API, dados embutidos na página | `json` do Python, `JSON.parse` no JavaScript | Rígido: uma vírgula a mais derruba o documento inteiro |
| Parser CSV / delimitado | Exportações, planilhas, relatórios | `csv` do Python, `read_csv` do pandas | Aspas, delimitadores e codificações variam conforme quem gera o arquivo |
| Parser XML | Feeds, sitemaps, APIs corporativas antigas | `lxml`, `xml.etree.ElementTree` | Namespaces deixam os seletores prolixos |
| Expressões regulares | Padrões pequenos e planos dentro de um campo conhecido: preços, datas, IDs | `re` do Python | Não acompanham aninhamento; quebram com mudanças de layout |
| Parser baseado em gramática | Formatos próprios, linguagens de consulta, arquivos de configuração | Geradores de parser como ANTLR, Lark | Escrever a gramática leva tempo |
| Parser baseado em modelos | Texto bagunçado sem layout fixo | Modelos de linguagem que retornam JSON | A 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](https://www.crummy.com/software/BeautifulSoup/bs4/doc/) 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](/pt-br/blog/ai-web-scraper-how-it-works-2026).

## 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](/pt-br/blog/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](/pt-br/blog/cheerio-web-scraping). Para um scraper completo com requisições, paginação e gravação, comece pelo [tutorial de BeautifulSoup](/pt-br/blog/beautifulsoup-tutorial).

## 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](https://www.rfc-editor.org/rfc/rfc8259) 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](https://docs.python.org/3/library/json.html) 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](https://www.rfc-editor.org/rfc/rfc4180) 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](/pt-br/blog/static-vs-dynamic-pages) 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](/pt-br/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](/pt-br/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](/pt-br/blog/competitor-price-tracking).
- **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](/pt-br/blog/website-change-monitoring).
- **Análise de dados.** Registros tipados são o ponto de partida para encontrar padrões; veja [O que é mineração de dados?](/pt-br/blog/what-is-data-mining).
- **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 entrada | Abordagem recomendada |
|---|---|
| Uma API que retorna JSON | Use 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 sites | BeautifulSoup com `lxml`, ou Cheerio no Node.js, mais seletores CSS |
| Páginas que renderizam o conteúdo com JavaScript | Procure primeiro JSON embutido ou a API do site; use um navegador headless só se for preciso |
| Exportações CSV ou planilhas | Uma biblioteca CSV ou pandas, com delimitador e codificação definidos de forma explícita |
| Logs de servidor em formato fixo | Regex por linha ou um parser de logs, e depois converter os campos para os tipos certos |
| Um formato de texto próprio que você controla | Um parser baseado em gramática (ANTLR, Lark) |
| E-mails, PDFs, texto livre sem layout | Um extrator baseado em modelos com validação rígida da saída |
| Centenas de sites com layouts que mudam | Um 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](https://proxynet.io/pt-br/residential-proxy) permitem escolher país e cidade, e o [Proxies rotativos](https://proxynet.io/pt-br/rotating-proxy) 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](/pt-br/proxy).
