Formatos e fontes de dados 4 min de leitura

Parsing de PDF: extração de texto e tabelas, OCR e exemplos em várias linguagens

Extração de texto e tabelas de arquivos PDF: camadas de texto versus digitalizações, OCR com Tesseract e exemplos de código em Python, JavaScript e Java.

EW
Equipe Web-Scraping.biz
Coleta de dados para as demandas do negócio
Publicado: 30 março 2025

PDF é um formato pensado para impressão e visualização, não para o armazenamento de dados. Justamente por isso é o formato do qual é mais difícil extrair informação de forma confiável entre todos os do nosso panorama do parsing de documentos. Em PDF chegam faturas, contratos, especificações, listas de preços, extratos bancários e documentos de órgãos públicos — e quase sempre é preciso convertê-los em dados estruturados.

A grande bifurcação: texto ou imagem

A primeira coisa que determina toda a estratégia é como o texto está armazenado dentro do arquivo. Em um PDF «digital» (gerado a partir do Word, de uma diagramação ou do navegador) o texto está guardado como caracteres selecionáveis — dá para extraí-lo diretamente. Em um PDF digitalizado, a página é uma imagem: sem reconhecimento óptico (OCR) ela não contém caracteres e a extração devolverá o vazio. Verificar é simples: se no visualizador o texto pode ser selecionado com o mouse, é digital; se não, é preciso OCR. Os dois casos exigem ferramentas completamente diferentes, então convém começar sempre por essa verificação.

Extração de texto de PDFs digitais

Python

Para extrair texto e, sobretudo, tabelas, a melhor opção é o pdfplumber. Ele entende as coordenadas dos caracteres e das linhas e, por isso, sabe reconstruir a estrutura tabular.

python
import pdfplumber

with pdfplumber.open("invoice.pdf") as pdf:
    page = pdf.pages[0]

    text = page.extract_text()
    print(text)

    for table in page.extract_tables():
        for row in table:
            print(row)  # row é a lista de células da linha

Quando só o texto é necessário e a velocidade vem em primeiro lugar, recorre-se ao PyMuPDF (importado como fitz) — é rapidíssimo e respeita bem a disposição do texto.

python
import fitz  # PyMuPDF

doc = fitz.open("contract.pdf")
for page in doc:
    print(page.get_text())

Para tarefas simples, como extrair o texto página a página ou trabalhar com os metadados, serve o pypdf (o sucessor do obsoleto PyPDF2).

python
from pypdf import PdfReader

reader = PdfReader("report.pdf")
for page in reader.pages:
    print(page.extract_text())

JavaScript / Node.js

No Node, o caminho rápido para obter todo o texto do documento é o pdf-parse.

javascript
const fs = require("fs");
const pdf = require("pdf-parse");

const buffer = fs.readFileSync("invoice.pdf");
pdf(buffer).then((data) => {
  console.log(data.text);   // todo o texto
  console.log(data.numpages);
});

Quando é necessário controle de baixo nível ou trabalhar no navegador, usa-se o pdf.js da Mozilla — ele dá acesso aos fragmentos de texto individuais com suas coordenadas.

Java

Nos projetos corporativos, o Apache PDFBox é amplamente usado. Atenção à mudança de API entre versões: no PDFBox 3.x o documento é aberto com Loader.loadPDF(...), enquanto no 2.x era PDDocument.load(...).

java
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import java.io.File;

try (PDDocument doc = Loader.loadPDF(new File("report.pdf"))) {
    String text = new PDFTextStripper().getText(doc);
    System.out.println(text);
}

As tabelas: uma dor à parte

Em PDF não existe o conceito de «tabela»: o que uma pessoa vê como tabela é, na verdade, um conjunto de blocos de texto e linhas com coordenadas. Por isso a extração de tabelas é sempre uma heurística. O pdfplumber as reconstrói a partir das linhas da grade e funciona bem quando a tabela está traçada. Para tabelas complexas sem linhas, em Python empregam-se o Camelot (método baseado na disposição) ou o tabula-py (um invólucro do motor Java Tabula). Se as tabelas são muitas e homogêneas, o habitual é escolher uma ferramenta e calibrá-la para aquele layout específico.

Muitas vezes o mais prático é despejar o resultado diretamente em uma tabela — a partir daí, o processamento continua no Excel ou em CSV, como com qualquer fonte tabular.

Digitalizações e OCR

Se o texto não se deixa selecionar, antes de extraí-lo é preciso reconhecer a página. A pilha clássica em Python: renderizar as páginas como imagens (com o próprio PyMuPDF) e reconhecê-las com o motor Tesseract por meio do invólucro pytesseract.

python
import fitz
import pytesseract
from PIL import Image
import io

doc = fitz.open("scan.pdf")
for page in doc:
    pix = page.get_pixmap(dpi=300)              # renderizamos a página como imagem
    img = Image.open(io.BytesIO(pix.tobytes()))
    text = pytesseract.image_to_string(img, lang="por")
    print(text)

A qualidade do OCR depende muito da resolução (use 300 DPI no mínimo), da limpeza da digitalização e do idioma. Para documentos em português, indique sempre o pacote de idioma por. Não espere do OCR uma precisão de cem por cento: o resultado quase sempre exige pós-processamento e revisão.

Quando é melhor não parsear o PDF diretamente

Às vezes o documento também existe em outro formato: o mesmo extrato está disponível como exportação CSV ou uma API entrega os dados em JSON. Isso é quase sempre mais confiável do que extrair uma tabela da versão para impressão, então verifique a fonte antes de partir para cima do PDF.

PDF é um formato em que a solução «universal» não existe: uma fatura, um contrato e uma digitalização exigem ferramentas diferentes. Se você recebe um fluxo regular de documentos homogêneos — faturas, romaneios, especificações —, configuramos a extração de dados dos seus PDFs para aquele layout específico, tabelas e OCR de digitalizações incluídos, com a carga do resultado no sistema de que você precisa.