0Pricing
AI Agents · Aula

Analisando PDFs com PyMuPDF e pdfplumber

Extração programática de texto, tabelas e metadados de PDFs.

Analisando PDFs com PyMuPDF e pdfplumber é uma aula grátis de AI Agents no CoddyKit. Esta é a aula 1 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de AI Agents, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de AI Agents inclui 4 aulas no total.

Por que a análise de PDF não é trivial

PDFs são um formato de apresentação, não um formato de dados. O texto é armazenado como glifos posicionados, não como parágrafos lógicos. Extrair texto significativo exige compreender a disposição, a ordem de leitura e as propriedades das fontes, além de lidar com casos especiais como disposições em várias colunas, cabeçalhos e rodapés e imagens incorporadas.

Duas bibliotecas se destacam: PyMuPDF (velocidade) e pdfplumber (extração de tabelas).

Noções básicas de PyMuPDF

PyMuPDF (importado como fitz) é a biblioteca Python mais rápida para PDFs. Ela lida com extração de texto, metadados, imagens e renderização. Instale com pip install pymupdf.

import fitz  # PyMuPDF

# Open a PDF
doc = fitz.open('document.pdf')

print(f'Pages: {len(doc)}')
print(f'Metadata: {doc.metadata}')

# Extract text from all pages
full_text = ''
for page_num in range(len(doc)):
    page = doc[page_num]
    text = page.get_text()  # plain text extraction
    full_text += f'--- Page {page_num + 1} ---\n{text}\n'

doc.close()
print(full_text[:500])

Modos de extração de texto do PyMuPDF

page.get_text() oferece diferentes formatos de saída. Use 'text' para texto simples, 'blocks' para blocos de texto com caixas delimitadoras e 'dict' para uma saída estruturada avançada, incluindo nomes e tamanhos de fontes.

import fitz

doc = fitz.open('report.pdf')
page = doc[0]

# Mode 1: plain text
plain = page.get_text('text')

# Mode 2: blocks (each block has bbox + text)
blocks = page.get_text('blocks')
for block in blocks:
    x0, y0, x1, y1, text, block_no, block_type = block
    if block_type == 0:  # text block (1 = image)
        print(f'Block at ({x0:.0f},{y0:.0f}): {text[:80]}')

# Mode 3: dict (full detail including font info)
page_dict = page.get_text('dict')
for block in page_dict['blocks']:
    if block.get('type') == 0:  # text
        for line in block['lines']:
            for span in line['spans']:
                print(f"Font: {span['font']}, Size: {span['size']:.1f}, Text: {span['text']}")

doc.close()

Extração de metadados da página

Os metadados da página ajudam os agentes a compreender a estrutura do documento: número de páginas, título do documento, autor, data de criação e dimensões da página. O PyMuPDF disponibiliza todas essas informações.

import fitz

def extract_pdf_metadata(filepath):
    doc = fitz.open(filepath)
    meta = doc.metadata
    info = {
        'title':    meta.get('title', 'Unknown'),
        'author':   meta.get('author', 'Unknown'),
        'subject':  meta.get('subject', ''),
        'creator':  meta.get('creator', ''),
        'created':  meta.get('creationDate', ''),
        'modified': meta.get('modDate', ''),
        'pages':    len(doc),
        'page_size': {
            'width':  doc[0].rect.width,
            'height': doc[0].rect.height
        }
    }
    doc.close()
    return info

meta = extract_pdf_metadata('contract.pdf')
print(f"Title: {meta['title']}, Pages: {meta['pages']}")

pdfplumber para extração de tabelas

pdfplumber é excelente para extrair tabelas de PDFs. Ele usa análise geométrica para detectar os limites das células, mesmo em PDFs sem marcação explícita de tabela.

Instale com pip install pdfplumber.

import pdfplumber

with pdfplumber.open('financial_report.pdf') as pdf:
    for page_num, page in enumerate(pdf.pages):
        tables = page.extract_tables()
        for table_idx, table in enumerate(tables):
            print(f'Page {page_num+1}, Table {table_idx+1}:')
            # table is a list of rows; each row is a list of cell strings
            headers = table[0]
            for row in table[1:]:
                row_dict = dict(zip(headers, row))
                print(row_dict)

Configurações de tabelas do pdfplumber

A extração de tabelas do pdfplumber pode ser ajustada com configurações para lidar com diferentes estilos de tabela: linhas explícitas, colunas separadas por espaços ou disposições mistas.

import pdfplumber

# Custom table settings for borderless tables
table_settings = {
    'vertical_strategy':   'text',   # 'lines', 'lines_strict', 'text', 'explicit'
    'horizontal_strategy': 'text',
    'snap_tolerance':       5,
    'join_tolerance':       3,
    'edge_min_length':     50,
    'min_words_vertical':   3,
    'min_words_horizontal': 1
}

with pdfplumber.open('nolines_table.pdf') as pdf:
    page = pdf.pages[0]
    table = page.extract_table(table_settings)
    if table:
        import csv
        import io
        output = io.StringIO()
        writer = csv.writer(output)
        writer.writerows(table)
        csv_string = output.getvalue()
        print(csv_string[:300])

Tratamento de disposições em várias colunas

Artigos acadêmicos e jornais usam disposições em várias colunas. A extração ingênua de texto lê as colunas da esquerda para a direita, produzindo um texto desordenado. Corrija isso ordenando primeiro os blocos de texto por coluna.

import fitz

def extract_multicolumn_text(page, n_columns=2):
    page_width = page.rect.width
    col_width = page_width / n_columns

    blocks = page.get_text('blocks')
    # Filter text blocks only
    text_blocks = [b for b in blocks if b[6] == 0]

    # Assign each block to a column based on x position
    columns = [[] for _ in range(n_columns)]
    for block in text_blocks:
        x0 = block[0]
        col_idx = min(int(x0 / col_width), n_columns - 1)
        columns[col_idx].append(block)

    # Sort each column by vertical position
    for col in columns:
        col.sort(key=lambda b: b[1])  # sort by y0

    # Read columns left to right
    full_text = ''
    for col in columns:
        for block in col:
            full_text += block[4] + '\n'
    return full_text

Filtragem de cabeçalhos e rodapés

Os cabeçalhos e rodapés dos PDFs se repetem em todas as páginas e poluem o texto extraído. Identifique-os pela posição vertical (nos 10% superiores ou inferiores da página) e exclua-os da extração de conteúdo.

import fitz

def extract_without_headers_footers(page, margin_ratio=0.08):
    page_height = page.rect.height
    top_margin = page_height * margin_ratio
    bottom_margin = page_height * (1 - margin_ratio)

    blocks = page.get_text('blocks')
    content_blocks = []

    for block in blocks:
        x0, y0, x1, y1, text, block_no, block_type = block
        if block_type != 0:
            continue  # skip image blocks
        # Skip blocks in header or footer zone
        if y0 < top_margin or y1 > bottom_margin:
            continue
        content_blocks.append(text)

    return '\n'.join(content_blocks)

Divisão do texto de PDFs em blocos para agentes

PDFs longos precisam ser divididos em blocos para vetorização e recuperação. Divida-os em limites naturais: parágrafos, seções ou páginas. Inclua sobreposição entre os blocos para evitar interromper o contexto no meio de uma frase.

import fitz

def pdf_to_chunks(filepath, chunk_size=1000, overlap=200):
    doc = fitz.open(filepath)
    chunks = []

    for page_num in range(len(doc)):
        page = doc[page_num]
        page_text = page.get_text()

        # Split into chunks with overlap
        start = 0
        while start < len(page_text):
            end = start + chunk_size
            chunk = page_text[start:end]
            chunks.append({
                'text': chunk,
                'page': page_num + 1,
                'char_start': start,
                'source': filepath
            })
            start += chunk_size - overlap  # overlap

    doc.close()
    return chunks

chunks = pdf_to_chunks('research_paper.pdf')
print(f'Total chunks: {len(chunks)}')
print(f'Sample: {chunks[0]["text"][:200]}')

Combinando PyMuPDF e pdfplumber

Use PyMuPDF para extração de texto (mais rápida) e pdfplumber para detecção de tabelas (mais precisa). Um extrator combinado executa ambos em cada página e retorna conteúdo estruturado, com texto e tabelas separados.

import fitz
import pdfplumber

def full_pdf_extract(filepath):
    result = {'text_by_page': [], 'tables': []}

    # Text extraction with PyMuPDF
    doc = fitz.open(filepath)
    for i in range(len(doc)):
        text = extract_without_headers_footers(doc[i])
        result['text_by_page'].append({'page': i + 1, 'text': text})
    doc.close()

    # Table extraction with pdfplumber
    with pdfplumber.open(filepath) as pdf:
        for page_num, page in enumerate(pdf.pages):
            tables = page.extract_tables()
            for t in tables:
                result['tables'].append({
                    'page': page_num + 1,
                    'headers': t[0] if t else [],
                    'rows': t[1:] if t and len(t) > 1 else []
                })

    return result

Salvando texto extraído em arquivos

Depois de extrair o texto dos PDFs, salve-o em um formato que os agentes posteriores possam consumir. Arquivos de texto simples funcionam bem para fluxos de vetorização; JSON preserva a estrutura das páginas para o rastreamento de citações.

import json, os

class FakePage:
    def __init__(self, text): self.text = text
    def get_text(self): return self.text

class FakeDoc(list):
    def close(self): pass

def fitz_open(path):
    return FakeDoc([FakePage('Page 1 text'), FakePage('Page 2 text')])

def pdf_to_text_file(pdf_path, output_dir):
    doc = fitz_open(pdf_path)
    base = os.path.splitext(os.path.basename(pdf_path))[0]
    txt_path = os.path.join(output_dir, base + '.txt')
    with open(txt_path, 'w', encoding='utf-8') as f:
        for i, page in enumerate(doc):
            f.write(f'--- Page {i+1} ---\n{page.get_text()}\n')
    json_path = os.path.join(output_dir, base + '.json')
    pages = [{'page': i+1, 'text': p.get_text()} for i, p in enumerate(doc)]
    with open(json_path, 'w') as f:
        json.dump({'source': pdf_path, 'pages': pages}, f, indent=2)
    doc.close()
    print(f'Saved: {txt_path} and {json_path}')
    return txt_path, json_path

pdf_to_text_file('sample.pdf', '.')

Verificação de conhecimento

Qual biblioteca Python é mais adequada para extrair tabelas de arquivos PDF?

Recapitulação: análise de PDFs com PyMuPDF e pdfplumber

PyMuPDF (fitz) é a opção rápida para extração de texto, metadados e tratamento de layouts com várias colunas. pdfplumber se destaca na extração de tabelas com estratégias geométricas configuráveis.

Técnicas principais: use get_text('blocks') para extração sensível à posição, filtre cabeçalhos e rodapés pela posição vertical, trate layouts com várias colunas ordenando os blocos por coluna e divida o texto em blocos com sobreposição para sistemas de recuperação de agentes. Combine as duas bibliotecas para obter os melhores resultados.

Perguntas Frequentes

A aula “Analisando PDFs com PyMuPDF e pdfplumber” é grátis?

Sim — o texto completo de “Analisando PDFs com PyMuPDF e pdfplumber” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de AI Agents, atualize para CoddyKit PRO. O curso de AI Agents inclui 4 aulas no total.

O que vou aprender em “Analisando PDFs com PyMuPDF e pdfplumber”?

Extração programática de texto, tabelas e metadados de PDFs. Você pratica AI Agents com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar AI Agents?

Nenhuma experiência prévia é necessária. AI Agents no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 1 de 4.

Quanto tempo leva a aula “Analisando PDFs com PyMuPDF e pdfplumber”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de AI Agents?

Sim. Cada aula de AI Agents inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Analisando PDFs com PyMuPDF e pdfplumber
  2. OCR para documentos digitalizados
  3. Agentes de perguntas e respostas em vários documentos
  4. Classificação e roteamento de documentos
← Voltar para AI Agents