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, gera relatórios em PDF ou edita documentos do Word, 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 e a introdução à automação 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:
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():
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:
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):
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:
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:
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:
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:
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 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:
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:
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:
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 instalado no sistema) com pytesseract (que exige o Tesseract):
pip install pdf2image pytesseract
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.
Boas práticas e armadilhas
- Feche os arquivos. Sempre use
with pdfplumber.open(...) as pdfpara 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 e CSV, e com a capacidade de gerar PDFs 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.
Equipe Python Brasil
Contribuidor do Python Brasil — Aprenda Python em Português