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

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

3,234
将网络爬虫数据连接到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集成。

评论

发表评论

您的邮箱不会公开,仅用于回复通知。

继续阅读

Get notified of new posts

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

Your email will only be used for new post notifications.