将网络爬虫数据连接到RAG的实战指南

了解用于RAG(检索增强生成)的网络爬虫数据处理方法和实际代码。还讨论了数据质量对RAG性能的影响,以及HashScraper MCP,LangChain等内容。

19
将网络爬虫数据连接到RAG的实战指南

将网络爬虫数据连接到RAG的实用指南

"我们想要制作一个能够以我们公司的数据作出回答的AI聊天机器人。" — 最近我们听到了这样的请求很多次。ChatGPT可能很聪明,但是要让它根据我们公司独有的最新数据来回答问题,就需要RAG。而RAG的性能最终取决于数据质量

本文将总结使用网络爬虫收集的数据连接到RAG管道的整个过程,并附上实际代码。

目录

RAG是什么?

RAG(检索增强生成)简单来说是"检索 + 生成"

在LLM生成答案之前,它会首先从外部数据库中检索相关文档并提供上下文。这样,GPT可以利用最新信息、内部文档和领域特定数据,大大减少幻觉(hallucination)的发生。

关键在于:LLM很聪明,但不知道的东西就是不知道。 RAG是一种通过搜索来补充LLM所不知道的内容的结构。

整体管道流程

RAG管道的整体流程分为5个阶段:

웹 크롤링 → 텍스트 청킹 → 임베딩 변환 → 벡터DB 저장 → LLM 쿼리

让我们逐步查看每个阶段的代码。

步骤1:爬取 — 收集原始数据

RAG的起点是数据。从网络上收集的产品信息、新闻、技术文档、社区帖子等都可以成为RAG的信息源。

这里重要的是进行干净的文本提取。如果将包含HTML标记、广告和导航菜单的数据直接输入,RAG的性能会大幅下降。

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

但是现实并不那么简单。对于使用JavaScript进行渲染的SPA、需要登录的页面、被机器人阻止的网站,仅使用requests可能会有限制。

步骤2:分块 — 将文本分割为适当大小的块

如果将整个文档嵌入,搜索准确性会降低。将文本分割为适当大小的块是关键。

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)}개 청크 생성")

分块提示:
- 如果块太小,上下文会中断;如果太大,搜索准确性会降低
- 对于韩文文本,通常使用500~800个字符的块可以获得良好的性能
- 设置chunk_overlap以防止句子被切断

步骤3:嵌入 + 存储向量数据库

将块转换为向量(数字数组),并将其存储在向量数据库中。这里使用OpenAI嵌入 + 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에 저장 완료")

其他向量数据库(如Pinecone、Weaviate、Qdrant等)也可以在LangChain中使用相同的接口。

步骤4:RAG查询 — 向LLM提问

现在当用户提出问题时,从向量数据库中检索相关文档并将上下文传递给LLM。

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"])

注意: RetrievalQA是LangChain的传统Chain接口。在最新版本中,推荐使用基于LangGraph的RAG配置,但为了理解概念,我们使用最直观的方法来解释。

这就是RAG的整体流程。爬取 → 分块 → 嵌入 → 向量数据库 → LLM查询。结构本身很简单。

数据质量决定RAG性能

RAG中最容易被低估的部分是输入数据的质量

即使使用了优秀的嵌入模型和LLM,如果输入数据混乱,结果也会混乱。实际上,RAG性能问题的大部分源于数据问题,而不是模型。

常见的数据质量问题:
- 导航、侧边栏文本与正文混合 → 搜索时产生噪音
- 不完整的爬取(JS渲染失败) → 重要信息丢失
- 重复数据 → 搜索结果偏向
- 编码错误、特殊字符问题 → 嵌入质量下降

垃圾进,垃圾出。 在爬取阶段获取干净的数据将决定RAG管道的成功与否。

HashScraper MCP + LangChain集成

如果自己编写爬虫,会花费时间处理机器人阻止、JS渲染、代理管理等附加问题。使用HashScraper的MCP(Model Context Protocol)服务器,您可以专注于RAG管道而无需担心爬取基础设施。

# 해시스크래퍼 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)

将HashScraper用作RAG数据源的原因:
- 即使在机器人阻止网站上,也可以稳定地提取干净文本
- 自动处理JavaScript渲染、登录流程
- 内置代理管理、IP轮换 — 无需担心基础设施
- 结构化的数据输出 → 提高分块/嵌入质量

结束语

RAG管道在结构上很简单。但在实践中,决定性能的最终是第一阶段的数据收集质量

与其花时间编写和维护爬虫,不如在经过验证的爬取基础设施上专注于RAG逻辑,这可能是更有效的选择。

如果您需要构建基于爬取数据的RAG管道,请在HashScraper上咨询。我们将根据实际经验帮助您从数据收集到AI集成。

Comments

Add Comment

Your email won't be published and will only be used for reply notifications.

继续阅读

Get notified of new posts

We'll email you when 해시스크래퍼 기술 블로그 publishes new content.

Your email will only be used for new post notifications.