---
title: "Extrair Texto e Tabelas de PDF em Python com pypdf e pdfplumber"
url: "https://python.dev.br/blog/extrair-texto-pdf-python-pypdf-pdfplumber/"
markdown_url: "https://python.dev.br/blog/extrair-texto-pdf-python-pypdf-pdfplumber.MD"
description: "Aprenda a extrair texto e tabelas de PDF em Python com pypdf e pdfplumber: leitura página por página, metadados, mesclar e dividir arquivos, exportar tabelas de notas fiscais e boletos para Excel e CSV, e OCR de PDFs escaneados com Tesseract. Guia prático em português brasileiro."
date: "2026-07-17"
author: "Equipe Python Brasil"
---

# Extrair Texto e Tabelas de PDF em Python com pypdf e pdfplumber

Aprenda a extrair texto e tabelas de PDF em Python com pypdf e pdfplumber: leitura página por página, metadados, mesclar e dividir arquivos, exportar tabelas de notas fiscais e boletos para Excel e CSV, e OCR de PDFs escaneados com Tesseract. Guia prático em português brasileiro.


O PDF é o formato dominante na papelada brasileira: notas fiscais eletrônicas impressas em DANFE, boletos bancários, holerites, contratos, relatórios contábeis e editais. Quase todo escritório, contador ou analista já perdeu tempo copiando dados de um PDF, linha por linha, para uma planilha. A boa notícia é que o Python lê PDFs muito bem: com **pypdf** e **pdfplumber** você extrai texto, tabelas e metadados de forma programática e transforma horas de trabalho manual em um script de alguns minutos.

Este tutorial mostra como extrair texto e tabelas de PDFs em Python, do caso mais simples (texto selecionável) ao mais desafiador (PDF escaneado que exige OCR), com exemplos voltados para a realidade brasileira. Se você já [automatiza planilhas](/blog/python-e-excel-openpyxl/), [gera relatórios em PDF](/blog/python-gerar-pdf-relatorios/) ou [edita documentos do Word](/blog/python-e-word-python-docx/), este é o complemento natural: agora você também consegue *ler* de volta o que o escritório recebeu. Quem está começando pode revisar o [guia de Python para iniciantes](/blog/python-para-iniciantes-guia-completo/) e a [introdução à automação com Python](/blog/automatizacao-com-python/).

## pypdf ou pdfplumber? (e onde entra o PyMuPDF)

Antes de instalar, vale entender qual ferramenta usar em cada situação:

- **pypdf** — biblioteca pura em Python, sem dependências nativas. Excelente para extrair texto simples, ler metadados (autor, título, data) e estruturar PDFs (mesclar, dividir, girar páginas). É o substituto moderno do antigo PyPDF2, renomeado em 2022.
- **pdfplumber** — construído sobre o pdfminer.six. É a melhor escolha para **extrair tabelas** e para preservar o posicionamento do texto na página. É mais lento que o pypdf em arquivos grandes, mas devolve dados muito mais estruturados.
- **PyMuPDF** (importado como `fitz`) — o mais rápido dos três, ideal para processar milhares de PDFs. Depende de uma biblioteca em C, o que pode dificultar a instalação em alguns servidores.

A regra prática: comece com **pypdf** para texto e estruturação, e traga o **pdfplumber** quando aparecer uma tabela. Vamos cobrir os dois.

Instale os dois pacotes no seu [ambiente virtual](/blog/virtual-environments-python/):

```bash
pip install pypdf pdfplumber
```

## Extraindo texto com pypdf

O `pypdf` organiza um PDF em um objeto `PdfReader`, que expõe a lista de páginas. Cada página tem o método `extract_text()`:

```python
from pypdf import PdfReader

reader = PdfReader("nota-fiscal.pdf")
print(f"Total de páginas: {len(reader.pages)}")

# Texto de todas as páginas concatenado
texto_completo = ""
for pagina in reader.pages:
    texto_completo += pagina.extract_text() + "\n"

print(texto_completo[:500])
```

Para ler apenas uma página, use o índice: `reader.pages[0].extract_text()`. Em notas fiscais, a primeira página costuma trazer o cabeçalho com emitente, destinatário e totais; as seguintes podem trazer o detalhamento dos itens.

### Metadados do documento

Os metadados ficam em `reader.metadata` e ajudam a identificar origem e data de emissão — útil para organizar arquivos recebidos por e-mail em lotes:

```python
meta = reader.metadata
print(meta.get("/Title"))      # título definido pelo emissor
print(meta.get("/Author"))     # autor
print(meta.get("/CreationDate"))  # ex.: D:20260717143000-03'00'
```

O campo `/CreationDate` segue um padrão próprio do PDF (`D:YYYYMMDDHHmmss±TZ`). Se for relevante, recorte os oito primeiros dígitos após `D:` para obter a data.

### Mesclar e dividir PDFs

O `pypdf` também resolve tarefas estruturais que antes exigiam ferramentas pagas. Para **juntar** vários PDFs (por exemplo, agrupar os DANFEs de um mês):

```python
from pypdf import PdfWriter

escritor = PdfWriter()
for arquivo in ["nf-001.pdf", "nf-002.pdf", "nf-003.pdf"]:
    escritor.append(arquivo)

with open("notas-janeiro.pdf", "wb") as saida:
    escritor.write(saida)
```

Para **dividir** — extrair apenas as páginas de 1 a 3 de um contrato, por exemplo:

```python
from pypdf import PdfReader, PdfWriter

reader = PdfReader("contrato.pdf")
escritor = PdfWriter()
for i in range(0, 3):                # páginas 1, 2 e 3 (índices começam em 0)
    escritor.add_page(reader.pages[i])

with open("contrato-resumo.pdf", "wb") as saida:
    escritor.write(saida)
```

## Extraindo tabelas com pdfplumber

Quando o dado que você precisa está em uma tabela — itens de uma nota fiscal, parcelas de um boleto, demonstrativo de resultados — o `pdfplumber` é a ferramenta certa. Ele entende linhas e colunas e devolve listas de listas prontas para virar planilha:

```python
import pdfplumber

with pdfplumber.open("demonstrativo.pdf") as pdf:
    pagina = pdf.pages[0]
    texto = pagina.extract_text()
    tabelas = pagina.extract_tables()

for i, tabela in enumerate(tabelas, start=1):
    print(f"--- Tabela {i} ({len(tabela)} linhas) ---")
    for linha in tabela:
        print(linha)
```

Cada `linha` é uma lista de células, em que células vazias aparecem como `None`. O método `extract_table()` devolve apenas a primeira tabela da página; `extract_tables()` devolve todas.

### Ajustando a estratégia de extração

Nem toda tabela tem bordas visíveis. O `pdfplumber` permite ajustar como ele detecta colunas e linhas:

```python
tabela = pagina.extract_table({
    "vertical_strategy": "lines",     # "lines", "text" ou "explicit"
    "horizontal_strategy": "lines",
})
```

Use `"lines"` quando o documento tem grade completa (notas fiscais com bordas), e `"text"` quando as colunas são definidas apenas pelo espaçamento entre as palavras (comum em boletos e relatórios financeiros). É normal experimentar: rode uma vez, inspecione o resultado e ajuste.

### Limpando as linhas extraídas

PDFs reais trazem linhas em branco, cabeçalhos repetidos e células com quebras de linha. Uma função de limpeza deixa a tabela pronta para exportar:

```python
def limpar_tabela(tabela):
    limpa = []
    for linha in tabela:
        if not linha or all(celula is None for celula in linha):
            continue                      # descarta linhas vazias
        linha = [(celula or "").strip().replace("\n", " ") for celula in linha]
        limpa.append(linha)
    return limpa

tabela = limpar_tabela(tabela)
```

Depois disso, vale validar com [expressões regulares](/blog/expressoes-regulares-python/) os campos críticos: conferir se o CNPJ tem 14 dígitos, se o valor bate com o total da nota e se a data está no formato `DD/MM/AAAA`.

## Exportando para Excel e CSV

A tabela extraída ganha vida quando vira planilha. Para **CSV**, use o módulo da biblioteca padrão descrito no [guia de leitura e escrita de CSV](/blog/python-csv-leitura-escrita-arquivos/):

```python
import csv

with open("itens-nota.csv", "w", encoding="utf-8", newline="") as f:
    escritor = csv.writer(f, delimiter=";")
    escritor.writerows(tabela)
```

Para **Excel**, use o [openpyxl](/blog/python-e-excel-openpyxl/):

```python
from openpyxl import Workbook

wb = Workbook()
ws = wb.active
for linha in tabela:
    ws.append(linha)
wb.save("itens-nota.xlsx")
```

Cuidado com a **vírgula decimal brasileira**: valores extraídos costumam vir como `"1.234,56"`. Converta para `float` antes de gravar como número, trocando os separadores:

```python
def para_numero(texto):
    if not texto:
        return None
    texto = texto.replace(".", "").replace(",", ".")
    try:
        return float(texto)
    except ValueError:
        return None
```

Assim, `"1.234,56"` vira `1234.56` e é gravado corretamente na planilha.

## Quando o PDF é uma imagem: OCR com Tesseract

Se o `extract_text()` devolver uma string vazia ou praticamente nada, o PDF provavelmente é uma **imagem escaneada** — não há texto selecionável. Nesse caso, é preciso converter as páginas em imagem e aplicar OCR. A combinação clássica é `pdf2image` (que exige o [poppler](https://poppler.freedesktop.org/) instalado no sistema) com `pytesseract` (que exige o [Tesseract](https://tesseract-ocr.github.io/)):

```bash
pip install pdf2image pytesseract
```

```python
from pdf2image import convert_from_path
import pytesseract

imagens = convert_from_path("boleto-escaneado.pdf", dpi=300)
for i, imagem in enumerate(imagens, start=1):
    texto = pytesseract.image_to_string(imagem, lang="por")  # "por" = português
    print(f"--- Página {i} ---")
    print(texto)
```

O parâmetro `lang="por"` ativa o pacote de idioma português do Tesseract, essencial para reconhecer acentos corretamente. Como o OCR nunca é perfeito, sempre revise campos sensíveis como valores, datas e CNPJ. Para chamar o Tesseract diretamente da linha de comando, combinar com outras ferramentas nativas ou orquestrar conversões, vale conhecer o [guia do módulo subprocess](/blog/python-subprocess-comandos-externos/).

## Boas práticas e armadilhas

- **Feche os arquivos.** Sempre use `with pdfplumber.open(...) as pdf` para liberar os recursos ao final.
- **Cuidado com a memória em lotes grandes.** Processar milhares de PDFs de uma vez exige liberar cada `PdfReader`/objeto de página entre iterações; considere processar em lotes e gravar resultados incrementalmente.
- **Não confie cegamente no OCR.** Para documentos fiscais, cruze o total extraído com o campo de total da nota. Para dados sensíveis de pessoas, siga a LGPD: armazene apenas o necessário e controle o acesso.
- **Diferencie texto de imagem logo no início.** Se `extract_text()` devolver vazio, pule direto para o fluxo de OCR em vez de insistir.
- **Padronize nomes de saída.** Salve os resultados com identificadores extraídos do próprio PDF (número da nota, CNPJ do emitente) para evitar arquivos duplicados.

## Conclusão

Extrair texto e tabelas de PDFs é uma das automações de maior impacto para quem trabalha com a papelada brasileira. Com **pypdf** você lê texto, metadados e estrutura arquivos; com **pdfplumber** você transforma tabelas de notas fiscais, boletos e demonstrativos em dados limpos; e quando o documento é uma imagem, o fluxo de **OCR com Tesseract** recupera o texto escaneado. Combinado com a exportação para [Excel](/blog/python-e-excel-openpyxl/) e [CSV](/blog/python-csv-leitura-escrita-arquivos/), e com a capacidade de [gerar PDFs](/blog/python-gerar-pdf-relatorios/) quando preciso, o Python fecha o ciclo completo de manipulação de documentos. Comece com um PDF pequeno e selecionável, valide o resultado e expanda gradualmente para os cenários mais complexos — sempre com revisão humana nos campos críticos.
