Texto da Web Limpo para RAG: Um Pipeline de Busca, Extração e Fragmentação
Web Data Collection Specialist
Principais Conclusões:
- A qualidade do RAG é a qualidade do corpus. As respostas de recuperação são tão boas quanto o texto que você indexou — e a maioria das falhas no fluxo de trabalho se deve a páginas que nunca foram renderizadas, elementos de navegação que foram incorporados ou partes que foram cortadas no meio da ideia.
- A etapa de busca é a instável. Páginas modernas são renderizadas em JavaScript e verificadas por bots; um simples HTTP GET retorna uma casca vazia ou uma página de desafio, e esse lixo flui silenciosamente para o seu armazenamento vetorial.
- Um POST retorna a página renderizada. O desbloqueador da web Scrapeless pega uma URL e fornece de volta o HTML totalmente renderizado como
{"code": 200, "data": "<html…>"}— a renderização e o tratamento anti-bot ocorrem no servidor. - Extração é subtração. Remova scripts, estilos, navegação e rodapés antes de ler o texto; o que resta é a prosa que vale a pena incorporar.
- Divida com sobreposição, mantenha a proveniência. Janelas de palavras fixas com sobreposição preservam o contexto entre limites, e cada pedaço deve carregar sua URL de origem — a recuperação sem proveniência não pode ser auditada.
- Gratuito para começar. Novas contas Scrapeless incluem créditos de teste gratuitos — inscreva-se em app.scrapeless.com.
Fluxo de Trabalho em um Relance
Um sistema RAG recupera pedaços de texto e os alimenta em um modelo; tudo a montante herda o que foi para o índice. Este guia constrói o lado de ingestão do início ao fim:
- Buscar — obter HTML totalmente renderizado para uma lista de URLs através do desbloqueador da web, para que páginas construídas em JavaScript e sites verificados por bots retornem conteúdo real.
- Extrair — remover o chrome da página e manter a prosa.
- Dividir — separar em janelas de palavras sobrepostas com proveniência, prontas para qualquer modelo de incorporação e armazenamento vetorial.
A saída é corpus.jsonl: um pedaço por linha com sua URL de origem e posição — o formato neutro que todos os fluxos de trabalho de incorporação aceitam. As etapas 2 e 3 são transformações puras; apenas a etapa 1 toca na rede.
Por que a etapa de busca falha primeiro
Três modos de falha dominam a ingestão de texto da web, e todos os três são invisíveis até que a qualidade da recuperação caia:
- Renderização do lado do cliente. O HTML que um simples GET retorna é uma casca de carregamento; o artigo chega mais tarde via JavaScript. Seu extrator lê um
<div id="root">vazio e não indexa nada. - Intersticiais anti-bot. Páginas de desafio retornam HTTP 200 com uma prosa de "verificando seu navegador" — que se incorpora lindamente e é recuperada com confiança.
- Soft-404s. URLs mortas que renderizam uma página estilizada de "não encontrado", novamente com um status 200.
A solução é buscar através de uma infraestrutura que renderiza e limpa essas camadas no servidor. O desbloqueador da web Universal Scraping API faz exatamente isso: um POST por URL, HTML renderizado de volta.
Pré-requisitos
- Uma conta Scrapeless e chave de API — inscreva-se em app.scrapeless.com.
- Python 3.10+ com
requestsebeautifulsoup4. - Uma lista de URLs que você tem o direito de ingerir (veja a nota de sourcing abaixo).
bash
export SCRAPELESS_API_KEY=seu_token_api_aqui
Etapa 1 — Buscar páginas renderizadas
Um POST por URL para o endpoint do desbloqueador. A resposta é JSON com o documento renderizado em data:
python
# fetch.py — lista de URLs -> pages/*.html (totalmente renderizado)
import os
import pathlib
import requests
ENDPOINT = "https://api.scrapeless.com/api/v1/unlocker/request"
HEADERS = {
"Content-Type": "application/json",
"x-api-token": os.environ["SCRAPELESS_API_KEY"],
}
URLS = [
"https://www.scrapeless.com/pt/blog/best-llm-scrapers-2026",
"https://www.scrapeless.com/pt/blog/google-ai-overview-scraper-api-2026",
]
pathlib.Path("pages").mkdir(exist_ok=True)
for url in URLS:
resp = requests.post(
ENDPOINT,
headers=HEADERS,
json={
"actor": "unlocker.webunlocker",
"input": {"url": url, "type": "html", "redirect": True, "method": "GET"},
},
timeout=120,
)
resp.raise_for_status()
html = resp.json()["data"]
name = url.rstrip("/").rsplit("/", 1)[-1] + ".html"
pathlib.Path("pages", name).write_text(html, encoding="utf-8")
print(f"{url} -> pages/{name} ({len(html):,} bytes)")
Uma busca saudável resulta em centenas de kilobytes de documento renderizado por página de artigo. Alguns kilobytes geralmente significam uma casca ou um intersticial — vale a pena conferir antes de chegar ao índice.
Obtenha sua chave de API no plano gratuito: app.scrapeless.com
Etapas 2 e 3 — Extraia a prosa, divida com proveniência
A extração é subtração: remova os elementos que nunca são prosa, e então leia o texto do que resta. O agrupamento é uma janela de palavras fixa com sobreposição, e cada bloco mantém sua URL de origem e posição:
python
# build_corpus.py — pages/*.html -> corpus.jsonl (blocos com proveniência)
import json
import pathlib
from bs4 import BeautifulSoup
CHUNK_WORDS = 220 # tamanho da janela
OVERLAP_WORDS = 40 # levado para o próximo bloco
STRIP_TAGS = ["script", "style", "noscript", "nav", "header", "footer", "aside", "form", "svg"]
def extract_text(html: str) -> str:
soup = BeautifulSoup(html, "html.parser")
for tag in soup(STRIP_TAGS):
tag.decompose()
root = soup.find("article") or soup.find("main") or soup.body or soup
text = root.get_text(" ", strip=True)
return " ".join(text.split())
def chunk(words: list[str]):
step = CHUNK_WORDS - OVERLAP_WORDS
for start in range(0, max(len(words) - OVERLAP_WORDS, 1), step):
yield start, " ".join(words[start:start + CHUNK_WORDS])
total = 0
with open("corpus.jsonl", "w", encoding="utf-8") as out:
for page in sorted(pathlib.Path("pages").glob("*.html")):
text = extract_text(page.read_text(encoding="utf-8"))
words = text.split()
for start, body in chunk(words):
out.write(json.dumps({
"source": page.stem,
"word_offset": start,
"n_words": len(body.split()),
"text": body,
}) + "\n")
total += 1
print(f"{page.name}: {len(words):,} palavras")
print(f"{total} blocos -> corpus.jsonl")
O que sai, uma linha por bloco:
json
// amostra ilustrativa — esquema de uma execução ao vivo do build_corpus.py; texto resumido
{
"source": "best-llm-scrapers-2026",
"word_offset": 180,
"n_words": 220,
"text": "…o ator retorna a resposta mais suas citações como campos estruturados…"
}
A partir daqui, qualquer fluxo de trabalho de incorporação assume o controle: leia corpus.jsonl, incorpore text, armazene o vetor com source e word_offset como metadados. Os campos de proveniência são o que permite rastrear uma recuperação ruim até a página e a posição de onde veio.
Fontes responsáveis
Um corpus de treinamento ou recuperação herda peso legal de suas fontes. Ingestão apenas de páginas publicamente acessíveis que você tem o direito de usar; verifique os termos de serviço e as diretivas de robôs de cada site antes de adicioná-lo à lista de URLs; mantenha o volume de solicitações modesto por host; e trate o texto com direitos autorais como algo que você recupera e atribui em vez de republicar. Quando um corpus inclui conteúdo de terceiros, manter o campo source intacto é a diferença entre uma citação e uma cópia.
Perguntas frequentes
P: Por que não apenas usar requests.get nas URLs?
Para páginas estáticas funciona. Para sites renderizados em JavaScript ou verificados por bots, retorna shells e interstícios que envenenam o índice silenciosamente — o desbloqueador existe exatamente para isso.
P: Qual deve ser o tamanho dos blocos?
A janela 220/40 aqui é um padrão razoável para modelos de incorporação de classe transformadora de sentenças. Ajuste ao contexto do seu modelo e à sua granularidade de recuperação; mantenha alguma sobreposição para que ideias que cruzam uma fronteira sobrevivam.
P: Como posso detectar uma recuperação ruim antes que chegue ao índice?
Verificações de tamanho e conteúdo: páginas de artigos renderizados são grandes (as páginas do exemplo trabalhado ficam na casa das centenas de kilobytes), e texto extraído de algumas centenas de palavras de uma página que deveria ser um artigo é um sinal vermelho que vale a pena registrar.
P: Este método pode buscar páginas por trás de fornecedoras de anti-bots pesados?
A tarefa do desbloqueador é limpar as camadas de anti-bots do lado do servidor. Onde uma página específica ainda não pode ser limpa, trate-a como não recuperável e deixe-a de fora — uma página ausente é recuperável, um índice envenenado não é.
P: Eu preciso de um proxy?
Não. A saída e a renderização são tratadas dentro do ator; o POST que você envia é toda a integração.
P: Onde entram as incorporações e o armazenamento de vetores?
A montante de corpus.jsonl, com qualquer pilha que você já utiliza. Este pipeline para intencionalmente em blocos limpos, etiquetados com proveniência — o formato que toda ferramenta de incorporação aceita.
Conclusão: limpo dentro, limpo fora
O pipeline de ingestão se reduz a três arquivos curtos: busque HTML renderizado através do desbloqueador, subtraia o chrome, agrupe com sobreposição e proveniência. Nada disso é glamouroso, e tudo decide se as respostas de recuperação vêm de texto real de artigo ou de um shell de carregador que escorregou para o índice. Aponte a lista de URLs para as fontes que seu assistente deve conhecer, agende a execução e mantenha as páginas brutas — elas são o trilho de auditoria.
Pronto para Construir Seu Pipeline de Ingestão de RAG?
Junte-se à nossa comunidade para reivindicar um plano gratuito e se conectar com desenvolvedores construindo pipelines de dados: Discord · Telegram.
Inscreva-se em app.scrapeless.com para créditos de teste gratuitos, e aponte a fase de busca para as páginas que seu corpus de recuperação necessita. Consulte preços para os níveis atuais.
Na Scorretless, acessamos apenas dados disponíveis ao público, enquanto cumprem estritamente as leis, regulamentos e políticas de privacidade do site aplicáveis. O conteúdo deste blog é apenas para fins de demonstração e não envolve atividades ilegais ou infratoras. Não temos garantias e negamos toda a responsabilidade pelo uso de informações deste blog ou links de terceiros. Antes de se envolver em qualquer atividade de raspagem, consulte seu consultor jurídico e revise os termos de serviço do site de destino ou obtenha as permissões necessárias.



