Skip to content

Instantly share code, notes, and snippets.

@rodrigols89
Created January 29, 2026 08:49
Show Gist options
  • Select an option

  • Save rodrigols89/04346f5001893cf9cf473833b39ef672 to your computer and use it in GitHub Desktop.

Select an option

Save rodrigols89/04346f5001893cf9cf473833b39ef672 to your computer and use it in GitHub Desktop.
Extraindo textos por tipo de arquivo (v2)

Extraindo textos por tipo de arquivo

Conteúdo


O que vamos fazer aqui?

No RAG, você nunca embeda arquivos (.pdf, .docx, etc.).

Você embeda texto puro.

Portanto, antes de chunking e embeddings, precisamos:

  • Abrir o arquivo físico
  • Extrair o texto corretamente (dependendo do tipo)
  • Retornar texto limpo
  • ⚠️ Garantir que nenhum dado de outro usuário entre no processo

Extraindo conteúdo de arquivos TXT e Markdown

Aqui nós vamos criar o arquivo rag/services/extraction.py que vai ter as seguintes funções:

  • extract_txt(path)
  • extract_md(path)

Essas funções servem para ler o conteúdo de arquivos de texto simples (.txt e .md) e retornar todo o texto em formato de string, já pronto para ser processado em etapas seguintes do pipeline (como chunking e geração de embeddings).

Vamos começar definindo a função extract_txt(path: Path):

rag/services/extraction.py

def extract_txt(path: Path) -> str:
    ...
  • 🔹 O que essa função faz?
    • Lê todo o conteúdo de um arquivo .txt
    • Retorna esse conteúdo como texto puro
  • 🔹 Quais parâmetros ela recebe?
    • path (obrigatório)
      • Tipo: Path (pathlib.Path)
      • Representa o caminho físico do arquivo no sistema
  • 🔹 O que ela retorna?
    • Tipo: str
    • Uma string contendo todo o texto do arquivo

Continuando, agora nós vamos retornar esse texto:

rag/services/extraction.py

from pathlib import Path


def extract_txt(path: Path) -> str:
    return path.read_text(
        encoding="utf-8",
        errors="ignore"
    )
  • 🔹 O que esse bloco faz?
    • Abre o arquivo apontado por path
    • Lê todo o conteúdo como texto
    • Retorna o texto imediatamente

Seguindo a mesma lógica agora vamos implementar a função extract_md(path: Path):

rag/services/extraction.py

def extract_md(path: Path) -> str:
    return path.read_text(
        encoding="utf-8",
        errors="ignore"
    )

Extraindo texto de arquivos PDF (extract_pdf)

A função extract_pdf() é responsável por ler um arquivo PDF página por página e extrair todo o texto possível, retornando esse conteúdo como uma única string.

NOTE:
Ela é usada no pipeline RAG quando o tipo de arquivo identificado é .pdf, permitindo que documentos PDF — que não são texto puro — possam ser transformados em texto indexável.

Porém, antes de começar a implementar essa função, primeiro nós vamos instalar a biblioteca pdfplumber:

poetry add pdfplumber@latest

Agora, vamos atualizar os arquivos de dependências:

task exportdev
task exportprod

Ótimo, agora partindo para a implementação vamos importar a biblioteca pdfplumber e definir a função extract_pdf(path: Path):

rag/services/extraction.py

import pdfplumber


def extract_pdf(path):
    ...

Continuando, agora nós vamos criar uma lista vazia para armazenar os textos das páginas:

rag/services/extraction.py

def extract_pdf(path):

    text_parts = []
  • 🔹 O que isso faz?
    • Cria uma lista vazia para armazenar:
      • o texto extraído de cada página
  • 🔹 Por que usar uma lista?
    • Strings são imutáveis em Python
    • Acumular em lista + join() é:
      • mais eficiente
      • mais limpo
      • mais performático

Agora, nós vamos utilizar pdfplumber.open(path) com with para abrir o PDF:

rag/services/extraction.py

def extract_pdf(path):

    text_parts = []

    with pdfplumber.open(path) as pdf:
        ...
  • 🔹 O que isso faz?
    • Abre o arquivo PDF usando um context manager
    • Garante que o arquivo será fechado corretamente
  • Função utilizada: pdfplumber.open(path)
    • O que faz?
      • Abre um arquivo PDF para leitura
    • Quais parâmetros recebe?
      • path - Caminho do arquivo PDF
    • O que retorna?
      • Um objeto PDF do pdfplumber

Ótimo, sabendo que dentro desse bloco (with) nós teremos o PDF aberto, vamos iterar página por página:

rag/services/extraction.py

def extract_pdf(path):

    ...

    with pdfplumber.open(path) as pdf:
        for page in pdf.pages:
  • 🔹 O que isso faz?
    • Percorre todas as páginas do PDF
  • 🔹 Atributo utilizado: pdf.pages
    • O que é?
      • Uma lista de objetos Page
      • Cada Page representa:
        • uma página individual do PDF

Mas o que fazer em cada página lida?

Então, em cada página nós vamos:

  • Extrair o texto da página atual:
    • page_text = page.extract_text()
  • Verificar se o texto extraído tem conteúdo, ou seja é diferente de None:
    • if page_text
      • Se ele for True, então adicionar o conteúdo na lista:
        • text_parts.append(page_text)
      • Se page_text for None, não adicionaremos nada na lista text_parts.

Nosso código ficará assim:

rag/services/extraction.py

def extract_pdf(path):

    text_parts = []

    with pdfplumber.open(path) as pdf:
        for page in pdf.pages:
            page_text = page.extract_text()
            if page_text:
                text_parts.append(page_text)

Por fim, vamos retornar nossa lista, porém, juntando todos os textos das páginas separando por uma quebra de linha (\n):

rag/services/extraction.py

def extract_pdf(path):

    ...

    return "\n".join(text_parts)

Extraindo texto de arquivos DOCX (extract_docx)

A função extract_docx() é responsável por ler documentos do Microsoft Word (.docx) e extrair todo o texto contido nos parágrafos, retornando esse conteúdo como uma string única.

NOTE:
Ela permite que arquivos .docx, muito comuns em ambientes corporativos, possam ser indexados e utilizados no pipeline RAG, assim como PDFs e arquivos de texto.

Porém, antes de começar a implementar essa função, primeiro nós vamos instalar a biblioteca python-docx:

poetry add python-docx@latest

Agora, vamos atualizar os arquivos de dependências:

task exportdev
task exportprod

Ótimo, agora partindo para a implementação vamos importar o módulo Document e definir a função extract_docx(path):

rag/services/extraction.py

def extract_docx(path):
  • 🔹 O que essa função faz?
    • Abre um arquivo .docx
    • Extrai o texto de todos os parágrafos
    • Ignora parágrafos vazios
    • Retorna o texto consolidado
  • 🔹 O que ela retorna?
    • Uma str com todo o texto do documento
    • Cada parágrafo separado por uma quebra de linha (\n)

Agora, nós vamos utilizar a função Document(path) para abrir o documento:

rag/services/extraction.py

def extract_docx(path):
    """Extract text from a DOCX file."""

    document = Document(path)
  • 🔹 O que essa linha faz?
    • Carrega o arquivo .docx em memória
  • 🔹 Função utilizada: Document()
    • O que faz?
      • Abre e interpreta um arquivo .docx
    • Quais parâmetros recebe?
      • path - Caminho do arquivo
    • O que retorna?
      • Um objeto Document, representando o documento Word

Continuando, agora nós vamos criar uma list comprehension para:

  • Percorre todos os parágrafos do documento
  • Extrai apenas o texto (p.text)
  • Ignora parágrafos vazios

rag/services/extraction.py

def extract_docx(path):
    """Extract text from a DOCX file."""

    document = Document(path)
    paragraphs = [p.text for p in document.paragraphs if p.text]

Por fim, nós vamos juntar todos os parágrafos em uma string, separando-os por uma quebra de linha (\n) e enviar como retorno:

rag/services/extraction.py

def extract_docx(path):
    """Extract text from a DOCX file."""

    document = Document(path)
    paragraphs = [p.text for p in document.paragraphs if p.text]
    
    return "\n".join(paragraphs)

Extraindo texto de arquivos HTML (extract_html)

A função extract_html() é responsável por ler um arquivo HTML, remover elementos que não representam conteúdo textual relevante (como scripts e estilos) e extrair apenas o texto visível, retornando tudo como uma string limpa.

Porém, antes de começar a implementar essa função, primeiro nós vamos instalar a biblioteca beautifulsoup4:

poetry add beautifulsoup4@latest

Agora, vamos atualizar os arquivos de dependências:

task exportdev
task exportprod

Ótimo, agora partindo para a implementação vamos importar a biblioteca BeautifulSoup e definir a função extract_html(path: Path):

rag/services/extraction.py

from bs4 import BeautifulSoup

def extract_html(path):
    ...

Continuando, agora nós vamos ler todo o arquivo HTML como texto e ignorar caracteres inválidos:

rag/services/extraction.py

def extract_html(path):

    html = path.read_text(
        encoding="utf-8",
        errors="ignore"
    )
  • 🔹 Função utilizada: Path.read_text()
    • O que faz?
      • Lê o conteúdo de um arquivo de texto
    • Quais parâmetros recebe?
      • encoding="utf-8" - Codificação
      • errors="ignore" - Ignora erros
    • O que retorna?
      • Uma str com o conteúdo do arquivo

NOTE:
📌 Essa abordagem garante robustez contra HTMLs malformados ou com encoding inconsistente.

Continuando, agora nós vamos converter o HTML em um objeto BeautifulSoup, que nada mais é que uma estrutura navegável de elementos HTML:

rag/services/extraction.py

def extract_html(path):

    ...

    soup = BeautifulSoup(
        html,
        "html.parser"
    )
  • 🔹 Função utilizada: BeautifulSoup()
    • O que faz?
      • Analisa o HTML e cria uma árvore de nós
    • Quais parâmetros recebe?
      • markup (str) → HTML bruto
      • parser (str) → "html.parser"
    • O que retorna?
      • Um objeto BeautifulSoup

Agora, nós vamos remover tags HTML que nós consideramos irrelevantes, como scripts e estilos:

rag/services/extraction.py

def extract_html(path):

    ...

    for tag in soup(["script", "style"]):
        tag.decompose()
  • 🔹 O que esse bloco faz?
    • Localiza todas as tags <script> e <style>
    • Remove completamente essas tags da árvore
  • soup(["script", "style"])
    • O que faz?
      • Busca todas as tags com esses nomes
    • Quais parâmetros recebe?
      • Uma lista de nomes de tags
    • O que retorna?
      • Uma lista de elementos encontrados
  • tag.decompose()
    • O que faz?
      • Remove a tag e todo o seu conteúdo da árvore
    • Quais parâmetros recebe?
      • Nenhum
    • O que retorna?
      • None

NOTE:
📌 Isso evita que códigos JavaScript, regras de CSS entrem no texto indexado.

Agora, nós vamos:

  • Extrair todo o texto visível do HTML
  • Separar por blocos de texto com quebras de linha (\n)
  • Por fim, enviar como retorno da função

rag/services/extraction.py

def extract_html(path):

    ...

    return soup.get_text(separator="\n")
  • 🔹 Função utilizada: soup.get_text()
    • O que faz?
      • Coleta todo o texto da árvore HTML
    • Quais parâmetros recebe?
      • separator="\n" - Define como os blocos de texto serão separados
    • O que retorna?
      • Uma str com o texto final

Despachando a extração de texto de forma segura no pipeline RAG

A função extract_text() é o ponto central de extração de conteúdo textual no pipeline RAG.

  • Ela recebe um arquivo já autorizado
  • Decide qual extractor usar com base no tipo do arquivo
  • Devolve o texto bruto pronto para chunking e embeddings.

Vamos começar:

  • Definindo uma função chamada extract_text()
  • Importando os módulos/funções que vamos usar

rag/services/extraction.py

from pathlib import Path


def extract_text(file_info):
    ...

Agora, nós vamos converter o caminho absoluto (string) do arquivo recebido (file_info) em um objeto Path que irá facilitar operações de leitura de arquivos:

rag/services/extraction.py

def extract_text(file_info):

    file_path = Path(file_info["absolute_path"])
  • 🔹 Função utilizada: Path()
    • O que faz?
      • Cria um objeto de caminho de arquivo
    • Quais parâmetros recebe?
      • Uma string representando o caminho
    • O que retorna?
      • Um objeto pathlib.Path

Agora, nós vamos pegar a extensão do arquivo:

NOTE:
📌 Essa padronização foi garantida anteriormente por get_file_type().

rag/services/extraction.py

def extract_text(file_info):

    ...

    file_type = file_info["file_type"]

Agora, nós vamos criar vários ifs (dispatcher) para decidir qual tipo de arquivo vamos extrair:

rag/services/extraction.py

def extract_text(file_info):

    ...

    if file_type == ".txt":
        return extract_txt(file_path)

    if file_type == ".pdf":
        return extract_pdf(file_path)

    if file_type == ".docx":
        return extract_docx(file_path)

    if file_type == ".md":
        return extract_md(file_path)

    if file_type == ".html":
        return extract_html(file_path)

E se for passado um tipo que nós não validamos ainda?

Nesse, caso nós vamos precisar lançar uma exceção para isso:

rag/services/extraction.py

def extract_text(file_info):

    ...

    raise ValueError(f"Tipo de arquivo não suportado: {file_type}")
  • 🔹 O que isso faz?
    • Interrompe a execução se o tipo não for reconhecido
    • Evita:
      • comportamentos inesperados
      • leitura de formatos não previstos

Rodrigo Leite da Silva - rodrigols89

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment