Guía práctica para conectar datos de web scraping a RAG
"Quiero crear un chatbot de IA que responda con datos de nuestra empresa." — Esta solicitud es muy común en estos días. Aunque ChatGPT es inteligente, para que responda basado en nuestros datos más recientes de la empresa, se necesita RAG. Y al final, el rendimiento de RAG depende de la calidad de los datos.
En este artículo, se resume el proceso completo de conectar los datos recopilados mediante web scraping a la tubería de RAG, con código práctico.
Contenidos
- ¿Qué es RAG?
- Flujo general de la tubería
- Paso 1: Web scraping — Recopilación de datos originales
- Paso 2: Chunking — Dividir el texto en tamaños adecuados
- Paso 3: Incrustación + Almacenamiento en base de datos vectorial
- Paso 4: Consulta de RAG — Hacer preguntas a LLM
- La calidad de los datos influye en el rendimiento de RAG
- Integración de HashScraper MCP + LangChain
- Conclusión
¿Qué es RAG?
RAG (Generación Aumentada por Recuperación) es simplemente "búsqueda + generación".
Antes de que LLM genere una respuesta, busca documentos relevantes en una base de datos externa para proporcionar contexto. Esto permite a GPT utilizar información actualizada, documentos internos y datos especializados de dominio para reducir significativamente la alucinación.
La clave es esta: LLM es inteligente, pero no sabe todo. RAG complementa lo que LLM "no sabe" con búsquedas.
Flujo general de la tubería
El flujo general de la tubería de RAG se divide en 5 etapas:
웹 크롤링 → 텍스트 청킹 → 임베딩 변환 → 벡터DB 저장 → LLM 쿼리
Vamos a examinar cada etapa con su respectivo código.
Paso 1: Web scraping — Recopilación de datos originales
El punto de partida de RAG son los datos. La información de productos, noticias, documentos técnicos y publicaciones comunitarias recopilados en la web pueden ser fuentes de RAG.
Aquí, la extracción de texto limpio es crucial. Si se incluyen etiquetas HTML, anuncios y menús de navegación en los datos, el rendimiento de RAG se verá afectado negativamente.
import requests
from bs4 import BeautifulSoup
def crawl_page(url):
"""단순 크롤링 예시 — 실전에서는 봇 차단, JS 렌더링 등 고려 필요"""
response = requests.get(url, headers={
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
})
soup = BeautifulSoup(response.text, "html.parser")
# 본문 텍스트만 추출 (네비게이션, 광고 등 제거)
for tag in soup(["nav", "header", "footer", "script", "style", "aside"]):
tag.decompose()
text = soup.get_text(separator="\n", strip=True)
return text
Sin embargo, la realidad no es tan simple. Páginas que requieren renderizado con JavaScript, páginas que requieren inicio de sesión y sitios con bloqueo de bots tienen limitaciones con solo solicitudes.
Paso 2: Chunking — Dividir el texto en tamaños adecuados
Incrustar un documento completo afecta la precisión de la búsqueda. Es crucial dividir el texto en trozos de tamaño adecuado.
from langchain_text_splitters import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(
chunk_size=500, # 청크당 최대 500자
chunk_overlap=50, # 청크 간 50자 겹침 (문맥 유지)
separators=["\n\n", "\n", ". ", " "] # 분할 우선순위
)
documents = splitter.split_text(crawled_text)
print(f"총 {len(documents)}개 청크 생성")
Consejos para chunking:
- Si es muy pequeño, se pierde el contexto; si es muy grande, la precisión de la búsqueda disminuye.
- Para textos en coreano, los trozos de 500 a 800 caracteres suelen tener un buen rendimiento.
- Configure chunk_overlap para evitar que las oraciones se corten.
Paso 3: Incrustación + Almacenamiento en base de datos vectorial
Convierta los trozos en vectores (arreglos numéricos) y guárdelos en una base de datos vectorial. Aquí se utiliza la combinación de incrustaciones de OpenAI y ChromaDB.
from langchain_openai import OpenAIEmbeddings
from langchain_chroma import Chroma
# 임베딩 모델 초기화
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
# 벡터DB에 저장
vectorstore = Chroma.from_texts(
texts=documents,
embedding=embeddings,
collection_name="crawled_data",
persist_directory="./chroma_db"
)
print(f"{len(documents)}개 청크를 벡터DB에 저장 완료")
Otras bases de datos vectoriales (Pinecone, Weaviate, Qdrant, etc.) también son compatibles con LangChain a través de la misma interfaz.
Paso 4: Consulta de RAG — Hacer preguntas a LLM
Cuando llega la pregunta del usuario, se buscan documentos relevantes en la base de datos vectorial y se envían a LLM con contexto.
from langchain_openai import ChatOpenAI
from langchain.chains import RetrievalQA
# LLM 설정
llm = ChatOpenAI(model="gpt-4o", temperature=0)
# RAG 체인 구성
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff",
retriever=vectorstore.as_retriever(search_kwargs={"k": 3})
)
# 질문하기
answer = qa_chain.invoke("이 제품의 최신 가격은 얼마인가요?")
print(answer["result"])
Nota:
RetrievalQAes la interfaz de cadena heredada de LangChain. Aunque se recomienda una configuración de RAG basada en LangGraph en las versiones más recientes, se explica de manera más intuitiva con este enfoque.
Este es el flujo general de RAG. Web scraping → Chunking → Incrustación → Base de datos vectorial → Consulta de LLM. La estructura en sí es simple.
La calidad de los datos influye en el rendimiento de RAG
La parte más subestimada en RAG es la calidad de los datos de entrada.
Incluso con un buen modelo de incrustación y LLM, si los datos de entrada son desordenados, los resultados también serán desordenados. De hecho, la mayoría de los problemas de rendimiento de RAG provienen de problemas de datos, no del modelo.
Problemas comunes de calidad de datos:
- Texto de navegación y barra lateral mezclado con el cuerpo principal → Generación de ruido en la búsqueda
- Web scraping incompleto (falla en el renderizado de JS) → Información clave omitida
- Datos duplicados → Sesgo en los resultados de búsqueda
- Problemas de codificación, errores de caracteres especiales → Disminución de la calidad de la incrustación
Basura entra, basura sale. Asegurar datos limpios en la etapa de web scraping determina el éxito de toda la tubería de RAG.
Integración de HashScraper MCP + LangChain
Crear un rastreador personalizado implica dedicar tiempo a problemas secundarios como bloqueo de bots, renderizado de JS, gestión de proxy, etc. Utilizar el servidor MCP (Protocolo de Contexto de Modelo) de HashScraper permite concentrarse en la lógica de RAG sin preocupaciones sobre la infraestructura de rastreo.
# 해시스크래퍼 MCP를 LangChain Document Loader로 활용하는 예시
from langchain_core.documents import Document
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_chroma import Chroma
from langchain_openai import OpenAIEmbeddings
# 해시스크래퍼 API로 데이터 수집 — 봇 차단 사이트도 OK
import requests
response = requests.post(
"https://api.hashscraper.com/api/scrape",
json={
"url": "https://target-site.com/products",
"format": "markdown" # markdown 또는 text
},
headers={
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json; version=2"
}
).json()
# LangChain Document로 변환
docs = [
Document(
page_content=response["data"]["content"],
metadata={
"url": response["data"]["url"],
"title": response["data"]["title"]
}
)
]
# 이후는 동일: 청킹 → 임베딩 → 벡터DB → RAG
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
chunks = splitter.split_documents(docs)
vectorstore = Chroma.from_documents(chunks, embeddings)
Razones para usar HashScraper como fuente de datos de RAG:
- Extracción de texto limpio de sitios con bloqueo de bots de forma estable
- Automatización del renderizado de JavaScript, gestión de inicio de sesión
- Gestión de proxy, rotación de IP integrada — sin preocupaciones por la infraestructura
- Salida de datos estructurados → Mejora de la calidad de chunking/incrustación
Conclusión
La tubería de RAG es estructuralmente simple. Sin embargo, en la práctica, lo que finalmente afecta el rendimiento es la calidad de la recopilación de datos en la primera etapa.
En lugar de dedicar tiempo a crear y mantener un rastreador, puede ser más eficiente concentrarse en la lógica de RAG sobre una infraestructura de rastreo verificada.
Si necesita construir una tubería de RAG basada en datos de web scraping, consulte a HashScraper. Con base en experiencias prácticas, le ayudarán desde la recopilación de datos hasta la integración con IA.




