---
title: "Como extrair dados de PDF: tabelas, texto e OCR"
description: "Verifique primeiro se o PDF tem camada de texto. Se tiver, o Excel ou o pdfplumber leem as tabelas; páginas digitalizadas precisam de OCR. Com código testado."
url: https://proxynet.io/pt-br/blog/extract-data-from-pdf
date: 2026-09-28
author: "Acar Diveroli"
category: "Tutoriais, Web scraping"
lang: pt-BR
---

# Como extrair dados de PDF: tabelas, texto e OCR

Um fornecedor envia a lista de preços dele todo mês em um PDF de 40 páginas. A equipe financeira recebe os extratos bancários do mesmo jeito, e o relatório de mercado que você comprou na semana passada tem a melhor tabela na página 17. Você precisa dessas linhas em uma planilha, e copiá-las à mão quebra as colunas, perde os sinais de negativo e toma uma hora que você vai gastar de novo no mês que vem.

Este artigo começa pela pergunta que define o método, se o arquivo tem camada de texto, e depois passa pelo conector de PDF do Excel, pdfplumber, Camelot e tabula-py, OCR com Tesseract para documentos digitalizados e um script em lote que transforma uma pasta de PDFs em um único CSV. Todos os exemplos foram executados em PDFs de teste que geramos com o ReportLab.

> **Nota: Resposta rápida**
>
> Primeiro verifique se dá para selecionar o texto do PDF. Se der, o arquivo tem camada de texto: para poucos arquivos, a opção **Dados > Obter Dados > Do Arquivo > Do PDF** do Excel carrega as tabelas diretamente, e para trabalhos recorrentes um script Python com `pdfplumber` extrai texto e tabelas de uma pasta inteira para CSV. Se não der para selecionar o texto, as páginas são imagens: renderize-as e aplique OCR (Tesseract via `pytesseract`) e depois confira os números, porque o resultado do OCR é uma estimativa, não uma cópia.

## O que significa extrair dados de um PDF?

Extrair dados de um PDF é transformar um conteúdo diagramado para impressão em linhas e campos que você pode ordenar e carregar em outro lugar. Um PDF não guarda "uma tabela com quatro colunas". Ele guarda instruções como "desenhe `1,007.50` nesta posição com esta fonte" e "trace uma linha daqui até ali". Toda ferramenta de extração de dados reconstrói a tabela a partir dessas coordenadas, e é por isso que o mesmo arquivo sai limpo em uma ferramenta e embaralhado em outra.

É o mesmo trabalho de tirar campos de uma página web ([Como extrair dados de um site](/pt-br/blog/extract-data-from-website)), só que com caracteres posicionados no lugar de tags HTML. Coletar PDFs de sites em grande escala faz parte de um fluxo mais amplo de [extração de dados](/pt-br/data-scraping).

## PDF de texto ou PDF digitalizado: como saber?

- **PDF de texto (digital).** Exportado do Word, de um sistema contábil ou de uma ferramenta de relatórios. Os caracteres ficam armazenados como texto, então a extração lê os números exatos do arquivo.
- **PDF digitalizado (imagem).** Cada página é uma foto de um papel. Não existe texto até o OCR (reconhecimento óptico de caracteres) deduzir os caracteres a partir dos pixels.

O teste rápido: pressione Ctrl+F e procure uma palavra que você está vendo. Se ela for encontrada, existe camada de texto. No código, uma lista `page.chars` vazia no pdfplumber indica que aquela página é uma digitalização. Alguns arquivos misturam os dois (um relatório digital com uma página de assinaturas digitalizada), então verifique página por página, não arquivo por arquivo.

## Como funciona a extração de tabelas de PDF?

Seja no Excel, no pdfplumber ou no Camelot, os mesmos passos rodam por trás:

1. **A página é analisada.** Cada caractere é lido com sua posição, fonte e tamanho, além das linhas e retângulos desenhados.
2. **Os caracteres viram palavras e linhas.** Caracteres próximos na mesma linha de base formam palavras; palavras na mesma altura formam uma linha.
3. **As áreas de tabela são encontradas.** A partir de linhas de grade que formam uma malha, ou de colunas de palavras alinhadas com espaço em branco entre elas.
4. **As células são montadas.** Cruzamentos de linhas ou vãos entre colunas definem os limites das células, e cada palavra vai para a célula que a contém.
5. **As linhas são devolvidas.** Uma lista de linhas (ou um DataFrame) que você limpa e salva.

O passo 3 causa a maior parte dos problemas. Uma grade completa é fácil; uma tabela sem bordas obriga a ferramenta a adivinhar as colunas pelo espaço em branco, e um nome de produto comprido pode deslocar todas as colunas.

## Métodos de extração de PDF lado a lado

| Método | Precisa de código? | Lê digitalizações? | Ideal para | Onde trava |
|---|---|---|---|---|
| Copiar e colar | Não | Não | Uma tabela pequena, uma vez | Colunas se juntam em uma célula, tabelas de várias páginas |
| Excel, Obter Dados > Do PDF | Não | Não | Poucos arquivos por mês, análise no Excel | Tabelas sem bordas, muitos arquivos com layouts diferentes |
| pdfplumber (Python) | Sim | Não | Texto e tabelas, trabalhos em lote, controle fino | Exige ajuste para tabelas sem bordas |
| Camelot (Python) | Sim | Extra opcional | Tabelas com grade, relatório de precisão por tabela | Texto livre em volta das tabelas |
| tabula-py (Python) | Sim | Não | DataFrames rápidos de arquivos cheios de tabelas | Exige Java instalado na máquina |
| Tesseract via pytesseract | Sim | Sim | Páginas digitalizadas, fotos de documentos | A precisão depende da qualidade da digitalização; as tabelas perdem a estrutura |

## Opções sem código: copiar e Excel

**Copiar.** Para uma tabela pequena, selecione-a no visualizador e cole. Se cada linha cair em uma única célula, use **Data > Text to Columns** (Dados > Texto para Colunas). Isso deixa de funcionar assim que um nome de produto tem espaços.

**O conector de PDF do Excel.** O Excel para Microsoft 365 no Windows consegue ler arquivos PDF pelo Power Query:

1. Abra uma pasta de trabalho em branco e vá em **Dados > Obter Dados > Do Arquivo > Do PDF**.
2. Selecione o PDF e clique em **Abrir**.
3. O **Navegador** lista o que o Power Query encontrou: cada tabela detectada (Table001, Table002…) e cada página inteira (Page001…). Clique em um item para ver a prévia.
4. Escolha **Carregar** para levar a tabela a uma planilha, ou **Transformar Dados** para limpá-la antes no Editor do Power Query (remover linhas de cabeçalho repetidas, mudar o tipo da coluna de preço para número).
5. No mês seguinte, substitua o arquivo e clique em **Data > Refresh All** (Dados > Atualizar Tudo); os mesmos passos rodam de novo.

A [documentação do conector de PDF](https://learn.microsoft.com/pt-br/power-query/connectors/pdf) da Microsoft lista as opções por trás dele: `Pdf.Tables` aceita `StartPage` e `EndPage` para arquivos grandes e uma opção `MultiPageTables` que junta uma tabela que continua em várias páginas. O conector não faz OCR, e o Power Query no Excel para Mac não oferece PDF como fonte. O conector de pasta combina PDFs com o mesmo layout; quando os layouts são diferentes, um script é mais fácil de manter.

## Extraindo texto e tabelas com pdfplumber

O [pdfplumber](https://github.com/jsvine/pdfplumber) é uma biblioteca Python construída sobre o pdfminer.six, com seu próprio localizador de tabelas. A versão atual é a 0.11.10 (junho de 2026); o README diz que ela funciona melhor com PDFs gerados por máquina e que não faz OCR. Instale-a em um ambiente virtual:

```bash
python -m venv .venv
.venv\Scripts\activate        # macOS/Linux: source .venv/bin/activate
pip install pdfplumber pandas
```

O básico cabe em poucas linhas:

```python
import pdfplumber

with pdfplumber.open("pdfs/price-list-2026-08.pdf") as pdf:
    page = pdf.pages[0]
    print(page.extract_text())          # todo o texto, linha por linha
    table = page.extract_table()        # a maior tabela da página
    print(table[:2])
# [['SKU', 'Product', 'Unit', 'Price'], ['B-001', 'Cable set 1', 'box', '13.40']]
```

`extract_tables()` devolve todas as tabelas da página como listas de strings de célula. Por padrão, o pdfplumber procura linhas desenhadas; para uma tabela sem bordas, mude para a estratégia de texto:

```python
settings = {"vertical_strategy": "text", "horizontal_strategy": "text"}
rows = page.extract_tables(table_settings=settings)
```

Escolha a estratégia conforme a tabela. Na nossa lista de preços com grade, a estratégia de texto dividiu "Cable set 1" em duas colunas e juntou "Unit" e "Price", porque tentou adivinhar pelos vãos entre as palavras o que as linhas já mostravam. Quando só uma parte da página é tabela, recorte primeiro com `page.crop((x0, top, x1, bottom))`.

## Um script completo: uma pasta de PDFs para um único CSV

O script abaixo lê todos os PDFs de uma pasta, pega o número do documento no texto da primeira página, tira as linhas de tabela de todas as páginas, pula os cabeçalhos repetidos, converte os preços em números e grava um único CSV. Páginas sem camada de texto são registradas para OCR, e um arquivo corrompido não interrompe o lote.

```python
import csv
import logging
import re
from pathlib import Path

import pdfplumber

logging.basicConfig(level=logging.INFO, format="%(levelname)s %(message)s")

IN_DIR = Path("pdfs")
OUT_CSV = Path("price_lists.csv")
HEADER = ["SKU", "Product", "Unit", "Price"]
DOC_NO = re.compile(r"price list (\S+)", re.IGNORECASE)

def to_number(text):
    """'1,007.50' -> 1007.5; returns None for empty or broken cells."""
    if not text:
        return None
    try:
        return float(text.replace(",", "").strip())
    except ValueError:
        return None

def rows_from_pdf(path):
    with pdfplumber.open(path) as pdf:
        first_text = pdf.pages[0].extract_text() or ""
        match = DOC_NO.search(first_text)
        doc_no = match.group(1) if match else path.stem

        for page in pdf.pages:
            if not page.chars:  # sem camada de texto: provavelmente uma digitalização
                logging.warning("%s p.%d has no text layer, needs OCR", path.name, page.page_number)
                continue
            for table in page.extract_tables():
                for row in table:
                    cells = [(c or "").strip() for c in row]
                    if cells == HEADER:  # cabeçalho repetido em toda página
                        continue
                    if len(cells) != len(HEADER):
                        logging.warning("%s p.%d skipped row %r", path.name, page.page_number, cells)
                        continue
                    sku, product, unit, price = cells
                    yield {
                        "file": path.name,
                        "doc_no": doc_no,
                        "page": page.page_number,
                        "sku": sku,
                        "product": product,
                        "unit": unit,
                        "price": to_number(price),
                    }

def main():
    fields = ["file", "doc_no", "page", "sku", "product", "unit", "price"]
    count = 0
    with OUT_CSV.open("w", newline="", encoding="utf-8-sig") as f:
        writer = csv.DictWriter(f, fieldnames=fields)
        writer.writeheader()
        for path in sorted(IN_DIR.glob("*.pdf")):
            try:
                for row in rows_from_pdf(path):
                    writer.writerow(row)
                    count += 1
            except Exception as exc:  # um arquivo corrompido não deve interromper o lote
                logging.error("%s failed: %s", path.name, exc)
    logging.info("wrote %d rows to %s", count, OUT_CSV)

if __name__ == "__main__":
    main()
```

Na nossa pasta de teste (uma lista de preços de 70 linhas em duas páginas, outra de 8 linhas e uma cópia digitalizada), a saída foi:

```bash
WARNING price-list-scan.pdf p.1 has no text layer, needs OCR
INFO wrote 78 rows to price_lists.csv
```

`utf-8-sig` faz o Excel mostrar corretamente nomes acentuados como "Café", e `file`, `doc_no` e `page` em cada linha levam cada número de volta à sua página. Onde guardar as linhas depois está em [Como salvar dados de scraping em CSV, JSON e SQLite](/pt-br/blog/save-scraped-data-csv-json-sqlite); a limpeza, em [Como limpar dados de scraping com pandas em Python](/pt-br/blog/clean-scraped-data-with-pandas).

## Camelot e tabula-py: quando usar

Duas outras bibliotecas se concentram só em tabelas.

O **Camelot** chegou à versão 2.0.0 em junho de 2026. `read_pdf()` usa por padrão o modo `lattice` para tabelas com grade; `stream` e `network` cuidam das tabelas sem bordas, e `auto` escolhe por página. Cada tabela tem um `parsing_report` com uma pontuação de precisão para sinalizar páginas ruins. Veja a [documentação do Camelot](https://camelot-py.readthedocs.io/en/latest/).

O **tabula-py** é um wrapper Python do tabula-java, por isso precisa de Java instalado. `tabula.read_pdf()` devolve diretamente uma lista de DataFrames do pandas.

```python
import camelot
import tabula

PDF = "pdfs/price-list-2026-09.pdf"

tables = camelot.read_pdf(PDF, pages="1-end", flavor="lattice")
for t in tables:
    print(t.page, t.shape, t.parsing_report["accuracy"])
tables[0].df.to_csv("camelot_page1.csv", index=False)

dfs = tabula.read_pdf(PDF, pages="all", lattice=True)
print(len(dfs), [df.shape for df in dfs])
```

Na nossa lista de preços de duas páginas, as duas encontraram uma tabela por página. O Camelot informou precisão de `100.0` e manteve o cabeçalho como primeira linha; o tabula o usou como nomes de coluna. As três bibliotecas acertaram a tabela com grade, então escolha pelo resto do trabalho: pdfplumber se você também precisa de texto livre, Camelot para ter uma pontuação por tabela, tabula-py para DataFrames com o mínimo de código se o Java estiver instalado.

## PDFs digitalizados: OCR com Tesseract

Quando uma página não tem camada de texto, é preciso reconhecer os caracteres a partir da imagem. O Tesseract é o motor de OCR de código aberto mais comum, e o [pytesseract](https://github.com/h/pytesseract) é o wrapper dele para Python. O wrapper não inclui o motor: instale primeiro o próprio Tesseract (se depois ele não estiver no PATH, defina `tesseract_cmd` como mostrado abaixo) e então:

```bash
pip install pytesseract pypdfium2
```

O script renderiza cada página a 300 DPI em tons de cinza, aplica OCR e imprime a confiança média por palavra, que mostra quais páginas precisam de revisão humana:

```python
import sys

import pypdfium2 as pdfium
import pytesseract

# No Windows, aponte o pytesseract para o executável se ele não estiver no PATH:
# pytesseract.pytesseract.tesseract_cmd = r"C:\Program Files\Tesseract-OCR\tesseract.exe"

def ocr_pdf(path, lang="eng", dpi=300):
    pdf = pdfium.PdfDocument(path)
    pages = []
    for i, page in enumerate(pdf, start=1):
        image = page.render(scale=dpi / 72).to_pil().convert("L")  # tons de cinza ajudam
        text = pytesseract.image_to_string(image, lang=lang, config="--psm 6")
        pages.append(text)
        # Confiança por palavra: -1 significa "não é uma palavra"; caso contrário, 0-100.
        data = pytesseract.image_to_data(image, lang=lang, output_type=pytesseract.Output.DICT)
        confs = [float(c) for c in data["conf"] if float(c) >= 0]
        if confs:
            print(f"page {i}: mean confidence {sum(confs) / len(confs):.1f}")
    return pages

if __name__ == "__main__":
    try:
        for text in ocr_pdf(sys.argv[1] if len(sys.argv) > 1 else "scans/price-list-scan.pdf"):
            print(text)
    except pytesseract.TesseractNotFoundError:
        sys.exit("Tesseract is not installed or not on PATH")
```

O valor de 300 DPI vem do [guia de melhoria de qualidade](https://tesseract-ocr.github.io/tessdoc/ImproveQuality.html) do Tesseract. `--psm 6` trata a página como um único bloco uniforme de texto. O mesmo guia observa que tabelas exigem segmentação própria e que as bordas da digitalização podem ser lidas como caracteres.

O OCR confunde `0` e `O`, `1` e `l`, e a vírgula e o ponto de um preço; digitalizações apagadas ou tortas pioram o resultado. Para números que importam, confira se os itens somam o total e peça para uma pessoa revisar as páginas com baixa confiança. O OCR devolve texto, não a estrutura da tabela: reconstrua as colunas com uma expressão regular por linha ou teste o extra opcional `ocr` do Camelot.

## Onde a extração de dados de PDF é usada

- **Listas de preços de fornecedores.** PDFs mensais transformados em um histórico de preços que você compara ao longo do tempo, a base do [monitoramento de preços](/pt-br/price-monitoring).
- **Relatórios de mercado e do setor.** Tabelas de relatórios públicos alimentando um modelo de [pesquisa de mercado](/pt-br/market-research) em vez de serem redigitadas.
- **Faturas e extratos.** Totais, datas e números de referência levados para a contabilidade ou a conciliação, um trabalho comum nas equipes de [finanças](/pt-br/finance).
- **Documentos públicos e estatísticas.** Muitos órgãos ainda publicam tabelas só em PDF; um script transforma anos delas em um único conjunto de dados, um primeiro passo típico antes da [mineração de dados](/pt-br/blog/what-is-data-mining).
- **Pipelines de ETL.** Ler PDFs é o "extract" de um fluxo maior; [O que é ETL](/pt-br/blog/what-is-etl) explica como as etapas de transformação e carga se encaixam em volta.

## Baixando muitos PDFs de sites

Os PDFs costumam estar em um portal de fornecedores ou na página de publicações de um órgão regulador. Baixar centenas deles é um trabalho de web scraping: use o download oficial ou a API, se existir, leia o robots.txt e os termos de uso e espace as requisições. O downloader abaixo pula os arquivos que já tem, não tenta de novo em erros 4xx, respeita `Retry-After` no HTTP 429 e confere se a resposta é mesmo um PDF:

```python
import os
import time
from pathlib import Path
from urllib.parse import urlparse

import requests

PROXY = os.environ.get("PROXY_URL", "http://user:pass@pr.proxynet.io:8000")
URLS = os.environ.get("PDF_URLS", "https://example.com/reports/price-list.pdf").split()
OUT = Path("pdfs")
OUT.mkdir(exist_ok=True)

session = requests.Session()
session.proxies = {"http": PROXY, "https": PROXY}
session.headers["User-Agent"] = "price-list-archiver/1.0 (contact: data@example.com)"

def download(url, retries=3):
    target = OUT / Path(urlparse(url).path).name
    if target.exists():  # já baixado em uma execução anterior
        return target
    for attempt in range(1, retries + 1):
        try:
            r = session.get(url, timeout=30)
            if r.status_code == 429:
                time.sleep(int(r.headers.get("Retry-After", 30)))
                continue
            if 400 <= r.status_code < 500:  # 403, 404...: tentar de novo não adianta
                print(f"{url} returned {r.status_code}, skipped")
                return None
            r.raise_for_status()
            if not r.content.startswith(b"%PDF"):  # uma página de erro HTML, não um PDF
                print(f"{url} did not return a PDF, skipped")
                return None
            target.write_bytes(r.content)
            return target
        except requests.RequestException as exc:
            print(f"attempt {attempt} failed: {exc}")
            time.sleep(2 ** attempt)
    return None

for url in URLS:
    print(url, "->", download(url))
    time.sleep(2)  # seja gentil com o servidor
```

Por meio de um proxy de teste local com user:pass, um PDF válido foi salvo, um `.pdf` falso e um 404 foram pulados, e uma segunda execução não baixou nada de novo. Um proxy ajuda quando uma fonte entrega documentos diferentes conforme o país (um [Proxies residenciais](https://proxynet.io/pt-br/residential-proxy) com país de destino) ou quando o download longo de um arquivo histórico esbarra em limites por IP (um [Proxies rotativos](https://proxynet.io/pt-br/rotating-proxy)). Mesmo assim, desacelerar vem primeiro, como explica [HTTP 429 Too Many Requests](/pt-br/blog/http-429-too-many-requests).

## Problemas comuns e como resolver

- **Células mescladas voltam como `None`.** O pdfplumber preenche só a primeira linha de uma célula mesclada; `ffill()` do pandas copia o valor para baixo (exemplo mais abaixo).
- **A tabela continua na página seguinte.** Extraia página por página, descarte as linhas de cabeçalho repetidas (como o script acima faz) e concatene. No Excel, a opção `MultiPageTables` faz isso por você.
- **Os números chegam como texto.** `"1,007.50"`, `"(250.00)"` para negativos, `"1.007,50"` em um arquivo alemão. Normalize conforme o formato; nunca adivinhe o separador decimal a partir de um único valor.
- **Letras acentuadas aparecem quebradas.** Normalmente o problema está no visualizador, não no texto: um console do Windows, ou o Excel abrindo UTF-8 sem BOM (veja [erros de codificação Unicode no Python](/pt-br/blog/python-unicode-encoding-errors)). Se o próprio `extract_text()` devolve símbolos estranhos, a fonte não tem mapeamento Unicode e o OCR é o caminho confiável.
- **As colunas se deslocam em tabelas sem bordas.** Mude para a estratégia de texto, recorte a área da tabela ou passe posições de coluna explícitas com `"vertical_strategy": "explicit"` e `"explicit_vertical_lines"`.
- **Zero linhas e nenhum erro.** A página é uma digitalização, a tabela é uma imagem ou o arquivo está protegido por senha (`pdfplumber.open(path, password="...")` para arquivos que você tem direito de abrir).

Esta é a correção completa para células mescladas, testada em uma tabela em que "North" ocupa duas linhas:

```python
import pandas as pd
import pdfplumber

with pdfplumber.open("merged.pdf") as pdf:
    rows = pdf.pages[0].extract_table()

df = pd.DataFrame(rows[1:], columns=rows[0])
df["Region"] = df["Region"].ffill()  # uma célula mesclada volta como None abaixo da primeira linha
df["Price"] = pd.to_numeric(df["Price"].str.replace(",", ""), errors="coerce")
print(df)
```

## Qual método escolher?

| Necessidade | Recomendação |
|---|---|
| Uma tabela de um arquivo, uma vez | Copiar e colar, depois Texto para Colunas |
| Poucos PDFs de texto por mês, análise no Excel | Excel, Dados > Obter Dados > Do Arquivo > Do PDF |
| Texto e tabelas de uma pasta, todo mês | Script de pdfplumber gravando CSV |
| Tabelas com grade e pontuação de qualidade por tabela | Camelot, modo `lattice` |
| DataFrames com o mínimo de código, com Java disponível | tabula-py |
| Páginas digitalizadas ou fotos | Renderizar com pypdfium2 a 300 DPI + Tesseract, com revisão humana dos números |
| Centenas de PDFs de um site | Primeiro o download oficial ou a API; senão, um downloader com pausas, com proxy se a fonte for regional |

## Perguntas frequentes

### Dá para extrair dados de PDF de graça?

Sim. pdfplumber, Camelot, tabula-py e Tesseract são de código aberto, e o conector de PDF faz parte do Excel para Microsoft 365 no Windows. As ferramentas pagas acrescentam principalmente editores de modelos e um OCR melhor para digitalizações ruins.

### Como passar uma tabela de PDF para o Excel?

No Excel para Microsoft 365 no Windows, use Dados > Obter Dados > Do Arquivo > Do PDF, escolha a tabela no Navegador e clique em Carregar. Em Python, extraia as linhas com o pdfplumber e grave-as com `to_excel()` do pandas ou como um CSV que o Excel abre.

### Por que a extração do meu PDF devolve texto vazio?

O mais provável é que a página não tenha camada de texto. Confira `page.chars` no pdfplumber ou tente Ctrl+F em um visualizador; se nada for encontrado, aplique OCR.

### O pdfplumber é melhor que o PyPDF para tabelas?

Para tabelas, sim. O pypdf é bom para dividir, juntar e ler texto simples, mas não tem localizador de tabelas. O pdfplumber guarda a posição de cada caractere e reconstrói as células a partir de linhas ou alinhamento, que é o que a extração de tabelas exige.

### Qual é a precisão do OCR em PDFs digitalizados?

Depende da digitalização. Páginas impressas limpas a 300 DPI costumam sair bem; digitalizações tortas, apagadas ou de baixa resolução, letra de mão e fontes pequenas, não. Confira as pontuações de confiança e verifique os totais.

### É legal extrair dados de PDFs que eu baixo?

Extrair dados de arquivos que você tem direito de usar (suas próprias faturas, relatórios públicos) normalmente não é problema, mas o conteúdo ainda pode ter direitos autorais e os dados pessoais nele continuam sujeitos a leis como a GDPR e a LGPD. Leia os termos da fonte antes de baixar em massa; nosso artigo sobre a [legalidade do web scraping](/pt-br/blog/is-data-web-scraping-legal) cobre o quadro geral. Isto não é aconselhamento jurídico.

## Em resumo

Todo trabalho com PDF começa com uma verificação: existe camada de texto? Se existir, o conector de PDF do Excel resolve as tabelas ocasionais e um script de pdfplumber transforma uma pasta em um único CSV, com Camelot ou tabula-py para o trabalho só com tabelas. Se não existir, renderize a 300 DPI, rode o Tesseract e verifique os números. Guarde o arquivo de origem e a página em cada linha, e trate downloads de PDF em massa como qualquer outro trabalho de web scraping. Quando esses downloads vêm de fontes regionais ou com limite de requisições, nossos planos de [proxy](/pt-br/proxy) dão ao fluxo os endereços de que ele precisa.
