RAG 数据导入完整指南
从 TXT 到 CSV 再到网页,全面掌握 RAG 系统的数据导入技术
文档日期:2026-04-17
目录
一、概述
1.1 RAG 数据导入的核心流程
┌─────────────────────────────────────────────────────────┐
│ RAG 数据导入流程 │
├─────────────────────────────────────────────────────────┤
│ │
│ 原始数据 → 读取 → 转换 → 分块 → 向量化 → 存储 │
│ │ │
│ ├─ TXT 文件 → 直接读取 │
│ ├─ CSV 文件 → 结构化转换 │
│ └─ 网页 → HTML 解析 + 正文提取 │
│ │
└─────────────────────────────────────────────────────────┘
1.2 为什么需要不同的加载器?
| 数据类型 | 特点 | 挑战 |
|---|---|---|
| TXT | 非结构化 | 分块策略 |
| CSV | 结构化 | 如何转成自然语言 |
| 网页 | 半结构化 | HTML 标签清理、动态内容、反爬 |
二、TXT 文件导入
2.1 基础方法
python
# 最简单的方式
with open('data.txt', 'r', encoding='utf-8') as f:
text = f.read()
2.2 分块策略
| 方法 | 说明 | 适用场景 |
|---|---|---|
| 固定长度 | 按字符数切分 | 均匀文本 |
| 按段落 | 保持段落完整 | 访谈录、文章 |
| 按章节 | 保持章节结构 | 技术文档、书籍 |
| 句子边界 | 在句子结束处分 | 需要语义完整 |
2.3 推荐配置
python
CHUNK_SIZE = 400 # 每块 400 字符
CHUNK_OVERLAP = 200 # 重叠 50%,保持上下文连贯
三、CSV 表格导入
3.1 核心挑战
CSV 是结构化数据,RAG 需要非结构化文本
┌─────────────────────────────────────────┐
│ CSV 原始数据 │
│ name,age,city,job │
│ 小明,25,北京,工程师 │
│ 小红,30,上海,设计师 │
└─────────────────────────────────────────┘
↓ 转换
┌─────────────────────────────────────────┐
│ 自然语言描述 │
│ "小明是一位 25 岁的北京工程师" │
│ "小红是一位 30 岁的上海设计师" │
└─────────────────────────────────────────┘
3.2 三种加载器对比
| 加载器 | 所属生态 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| pandas | 独立 | 轻量、完全控制 | 需手动转换 | 轻量级项目 |
| LangChain CSVLoader | LangChain | 返回 Document,无缝集成 | 依赖重,格式固定 | LangChain 项目 |
| UnstructuredCSVLoader | unstructured | 自动编码检测,metadata 丰富 | 安装复杂,需转换返回值 | 多格式统一处理 |
3.3 详细对比
LangChain CSVLoader
python
from langchain_community.document_loaders import CSVLoader
loader = CSVLoader(
file_path="data.csv",
source_column="标题",
metadata_columns=["分类", "作者"],
encoding="utf-8"
)
docs = loader.load()
# 直接返回 Document 对象
优点:
- ✅ 开箱即用,返回 Document 对象
- ✅ 与 LangChain 无缝集成
- ✅ 支持自定义 metadata 列
缺点:
- ❌ 依赖重(~200MB)
- ❌ 编码需手动指定
- ❌ 转换方式固定(
列名:值格式)
UnstructuredCSVLoader
python
from unstructured.csv import UnstructuredCSVLoader
loader = UnstructuredCSVLoader(
file_path="data.csv",
encoding=None, # 自动检测
include_headers=True
)
elements = loader.load()
# 返回 Element 对象,需转换
优点:
- ✅ 自动编码检测(中文不乱码)
- ✅ 统一 API 处理 20+ 格式
- ✅ metadata 丰富(语言、编码等)
缺点:
- ❌ 安装复杂(需要 libmagic)
- ❌ 返回值需手动转换
- ❌ 文档相对较少
pandas(推荐用于轻量级项目)
python
import pandas as pd
df = pd.read_csv("data.csv", encoding="utf-8")
# 自定义转换逻辑
chunks = []
for _, row in df.iterrows():
text = f"问题:{row['问题']}\n答案:{row['答案']}"
chunks.append(text)
优点:
- ✅ 依赖小(或无需额外依赖)
- ✅ 完全控制转换逻辑
- ✅ 符合轻量级风格
缺点:
- ❌ 需手动编写转换代码
- ❌ 不自动检测编码
3.4 CSV 转换策略
| 数据类型 | 转换策略 | 示例输出 |
|---|---|---|
| 问答对 | 逐行转换 | "问题:X 答案:Y" |
| 人员信息 | 字段组合 | "小明是一位 25 岁的工程师" |
| 产品目录 | 模板生成 | "产品【iPhone 15】售价 6999 元" |
| 知识库 | 标题 + 内容 | "【标题】RAG【内容】..." |
四、网页加载
4.1 核心挑战
| 挑战 | 说明 | 解决方案 |
|---|---|---|
| HTML 标签 | 需要清理 | BeautifulSoup/trafilatura |
| 动态内容 | JavaScript 渲染 | Selenium/Firecrawl |
| 反爬虫 | User-Agent/频率限制 | 代理/商业服务 |
| 编码问题 | GBK/Big5 等 | 自动检测 |
4.2 十种加载方案完整对比
| 方案 | 静态 | 动态 | 反爬 | 文章提取 | 递归 | 依赖 | 成本 | 推荐度 |
|---|---|---|---|---|---|---|---|---|
| requests+bs4 | ✅ | ❌ | ❌ | ⚠️ | ❌ | 小 | 免费 | ⭐⭐⭐ |
| WebBaseLoader | ✅ | ❌ | ❌ | ⚠️ | ❌ | 大 | 免费 | ⭐⭐⭐ |
| Unstructured HTMLLoader | ✅ | ❌ | ⚠️ | ✅ | ❌ | 中 | 免费 | ⭐⭐⭐ |
| Selenium | ✅ | ✅ | ✅ | ❌ | ❌ | 大 | 免费 | ⭐⭐ |
| Playwright | ✅ | ✅ | ✅ | ❌ | ❌ | 大 | 免费 | ⭐⭐ |
| trafilatura | ✅ | ❌ | ⚠️ | ✅✅✅ | ❌ | 小 | 免费 | ⭐⭐⭐⭐ |
| RecursiveURLLoader | ✅ | ❌ | ❌ | ⚠️ | ✅ | 大 | 免费 | ⭐⭐⭐⭐ |
| SitemapLoader | ✅ | ❌ | ❌ | ⚠️ | ⚠️ | 大 | 免费 | ⭐⭐⭐⭐ |
| Firecrawl | ✅ | ✅ | ✅✅✅ | ✅ | ✅ | 小 | 付费 | ⭐⭐⭐⭐⭐ |
| Scrapfly/ScraperAPI | ✅ | ✅ | ✅✅✅ | ⚠️ | ⚠️ | 小 | 付费 | ⭐⭐⭐ |
4.3 方案详解
4.3.1 trafilatura(文章提取首选)
python
import trafilatura
url = "https://example.com/article"
downloaded = trafilatura.fetch_url(url)
text = trafilatura.extract(downloaded)
优点:
- ✅ 专业文章提取,效果最好
- ✅ 自动过滤导航、广告
- ✅ 依赖小,速度快
- ✅ 支持中文
缺点:
- ❌ 只适合文章类网页
- ❌ 无法处理动态内容
4.3.2 RecursiveURLLoader(文档站首选)
python
from langchain_community.document_loaders import RecursiveURLLoader
loader = RecursiveURLLoader(
url="https://python.langchain.com/docs",
max_depth=2,
exclude_dirs=["/api/"]
)
docs = loader.load()
优点:
- ✅ 自动递归爬取整个网站
- ✅ 深度可控
- ✅ 自动去重
缺点:
- ❌ 依赖 LangChain
- ❌ 无法处理动态网页
4.3.3 SitemapLoader(博客/新闻站)
python
from langchain_community.document_loaders import SitemapLoader
loader = SitemapLoader(
web_path="https://example.com/sitemap.xml",
filter_urls=lambda url: "/blog/" in url
)
docs = loader.load()
优点:
- ✅ 通过官方 sitemap 获取 URL
- ✅ 覆盖全面
- ✅ 效率高
缺点:
- ❌ 依赖 sitemap
- ❌ 可能过期
4.3.4 Firecrawl(动态网页/反爬)
python
from firecrawl import FirecrawlApp
app = FirecrawlApp(api_key="xxx")
# 爬取整个网站
result = app.crawl_url(
url="https://example.com",
params={"limit": 100}
)
优点:
- ✅ 处理 JavaScript 渲染
- ✅ 绕过反爬机制
- ✅ 返回 Markdown 格式
- ✅ 无需维护基础设施
缺点:
- ❌ 需要 API Key
- ❌ 付费服务(免费额度 500/月)
- ❌ 数据发送到第三方
4.4 选型决策树
┌─────────────────┐
│ 你要爬什么网站? │
└────────┬────────┘
│
┌───────────────────┼───────────────────┐
│ │ │
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 静态文档站 │ │ 动态网页 │ │ 新闻文章 │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
┌─────┴─────┐ ┌─────┴─────┐ ┌─────┴─────┐
│ │ │ │ │ │
▼ ▼ ▼ ▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐
│Recursive│ │Sitemap │ │Fire- │ │Selenium│ │trafila-│
│URL │ │Loader │ │crawl │ │ │ │tura │
└────────┘ └────────┘ └────────┘ └────────┘ └────────┘
免费 有 sitemap 付费 免费 效果最好
五、方案对比与选型
5.1 数据类型 vs 推荐方案
| 数据类型 | 首选方案 | 备选方案 |
|---|---|---|
| TXT | 直接读取 + 分块 | - |
| CSV(轻量项目) | pandas | UnstructuredCSVLoader |
| CSV(LangChain) | CSVLoader | - |
| 静态网页 | trafilatura | requests+bs4 |
| 文档站 | RecursiveURLLoader | SitemapLoader |
| 动态网页 | Firecrawl | Selenium/Playwright |
| 新闻文章 | trafilatura | Unstructured |
| 多格式混合 | Unstructured | ww- |
5.2 依赖大小对比
| 方案 | 安装大小 | 安装命令 |
|---|---|---|
| requests + bs4 | ~5MB | pip install requests beautifulsoup4 |
| trafilatura | ~10MB | pip install trafilatura |
| pandas | ~15MB | pip install pandas |
| Unstructured | ~50MB | pip install unstructured + libmagic |
| LangChain 系列 | ~200MB+ | pip install langchain-community |
| Selenium | ~20MB + 浏览器 | pip install selenium |
| Firecrawl | ~5MB | pip install firecrawl-py |
5.3 成本对比
| 方案 | 免费额度 | 付费价格 |
|---|---|---|
| requests + bs4 | ✅ 完全免费 | - |
| trafilatura | ✅ 完全免费 | - |
| pandas | ✅ 完全免费 | - |
| LangChain 系列 | ✅ 完全免费 | - |
| Unstructured | ✅ 完全免费 | - |
| Firecrawl | 500 credits/月 | $16/月 起 |
| ScraperAPI | 5000 请求/月 | $29/月 起 |
六、最佳实践
6.1 轻量级项目(如 naive_rag.py)
推荐组合:pandas + trafilatura + requests
依赖:
pip install pandas trafilatura requests beautifulsoup4
理由:
- 总依赖 < 30MB
- 覆盖 CSV + 网页
- 完全免费
- 效果优秀
6.2 LangChain 项目
推荐组合:CSVLoader + WebBaseLoader + RecursiveURLLoader
依赖:
pip install langchain-community
理由:
- 无缝集成
- API 统一
- 文档丰富
6.3 生产环境
推荐组合:Firecrawl + Unstructured
依赖:
pip install firecrawl-py unstructured
理由:
- 处理动态网页
- 绕过反爬
- 多格式统一
- 有商业支持
6.4 编码处理最佳实践
python
# CSV 编码检测
import chardet
with open('data.csv', 'rb') as f:
result = chardet.detect(f.read(10000))
encoding = result['encoding']
df = pd.read_csv('data.csv', encoding=encoding)
6.5 网页加载 Fallback 策略
python
def load_webpage(url: str) -> str:
# 方案 1:trafilatura(优先)
try:
downloaded = trafilatura.fetch_url(url)
text = trafilatura.extract(downloaded)
if text:
return text
except:
pass
# 方案 2:requests + bs4(fallback)
try:
response = requests.get(url, headers={
'User-Agent': 'Mozilla/5.0'
}, timeout=10)
soup = BeautifulSoup(response.content, 'html.parser')
for tag in soup(['script', 'style']):
tag.decompose()
return soup.get_text()
except:
raise Exception("网页加载失败")
七、总结
7.1 核心要点
| 知识点 | 内容 |
|---|---|
| CSV 导入核心 | 结构化 → 自然语言转换 |
| 网页加载核心 | HTML 清理 + 正文提取 |
| 动态网页 | 需要浏览器渲染(Selenium/Firecrawl) |
| 文章提取 | trafilatura 效果最好 |
| 全站爬取 | RecursiveURLLoader / Firecrawl |
| 轻量级推荐 | pandas + trafilatura |
| 生产环境 | Firecrawl + Unstructured |
7.2 选型口诀
TXT 直接读,CSV 要转换
文章提取 trafilatura,文档站用 RecursiveURL
动态网页 Firecrawl,轻量项目 pandas + requests
有 sitemap 用 Sitemap,反爬严重用商业服务
文档整理日期:2026-04-17
基于 RAG 学习项目整理