纲要
- 数据加载器在 RAG 系统中的定位与 LangChain 统一契约
- 常见内置加载器实战
PyPDFLoader:文本型 PDF 解析- 多模态图文 PDF:结合视觉模型与 Base64 编码的解析方案
WebBaseLoader:基于 BeautifulSoup 的网页内容提取UnstructuredURLLoader:非结构化网页自动解析CSVLoader:CSV 文件逐行加载- Excel 加载方案:Azure Document Intelligence 与本地
pandas备选
- 自定义加载器开发
- 继承
BaseLoader,实现lazy_load迭代器 - 使用
yield返回Document对象,保留元数据
- 继承
- 完整可运行 Demo:整合
TextLoader、CSVLoader与自定义逐行加载器的本地演示
引言
在 RAG(检索增强生成)系统中,数据摄取是决定最终检索质量的首个关键环节。原始数据通常以 PDF、网页、表格等形式分散在不同存储中,格式各异。LangChain 通过定义统一的 Document 对象(包含 page_content 文本和 metadata 元数据)和丰富的加载器生态,将多源异构数据转化为标准流水线输入。本文以实战代码为主线,系统讲解常用加载器的用法、注意事项,并手把手实现一个支持逐行读取的自定义加载器,为后续文本切片、向量嵌入与检索打下基础。
文档加载器:从原始数据到 Document
LangChain 中所有加载器均遵循同一契约:输入为文件路径或网络 URL,输出为 Document 对象的列表(或迭代器)。每个 Document 包含:
page_content:字符串形式的文本内容metadata:字典,记录来源、页码、时间戳等上下文信息
该统一设计使得下游的文本分割器、嵌入模型和向量存储能够无缝对接,无需关心数据来源的具体格式。
常见加载器实战
PDF 加载:文本型 PDF
PyPDFLoader 是最基础的 PDF 文本提取工具,底层依赖 pypdf 库,支持按页解析。适用于原生文本型 PDF(非扫描件)。
from langchain_community.document_loaders import PyPDFLoader
loader = PyPDFLoader("example.pdf") # 替换为实际文件路径
pages = loader.load()
for page in pages:
print(f"Page {page.metadata['page']}: {page.page_content[:200]}")
若 PDF 为扫描图像或包含复杂表格,纯文本提取将丢失大量信息,需采用多模态方案。
多模态图文 PDF 解析
对于含图表、照片的 PDF,可将页面转换为 Base64 编码的图像,并借助多模态大模型(如 GPT‑4o)进行视觉理解。以下示例展示如何构建包含图像和文本的对话消息。
import base64
from langchain_core.messages import HumanMessage
from langchain_openai import ChatOpenAI
# 假设已有函数将 PDF 页面转为 Base64 字符串(实际可使用 pdf2image 或 PyMuPDF)
def pdf_page_to_base64(pdf_path, page_num=0):
# 此处省略具体转换逻辑,返回图片的 base64 编码
return "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg=="
image_base64 = pdf_page_to_base64("chart.pdf", page_num=0)
model = ChatOpenAI(model="gpt-4o-mini")
response = model.invoke([
HumanMessage(content=[
{"type": "text", "text": "图中一线城市消费者占比是多少?"},
{"type": "image_url", "image_url": {"url": f"data:image/png;base64,{image_base64}"}}
])
])
print(response.content)
注意:该方案依赖外部图像转换库,且会消耗较多 token,适用于对视觉信息要求较高的场景。
网页加载:WebBaseLoader
WebBaseLoader 基于 requests 和 BeautifulSoup,可从指定 URL 提取清洗后的纯文本内容。默认过滤掉脚本、样式等无关元素。
from langchain_community.document_loaders import WebBaseLoader
loader = WebBaseLoader("https://example.com")
docs = loader.load()
print(docs[0].page_content[:500])
若只需提取页面中特定区域(如某个 CSS 类),可通过 bs_kwargs 传递 SoupStrainer 进行精细控制。
from bs4 import SoupStrainer
loader = WebBaseLoader(
"https://example.com",
bs_kwargs={"parse_only": SoupStrainer(class_="main-content")}
)
docs = loader.load()
非结构化网页:UnstructuredURLLoader
当目标网页结构复杂或无法预知时,可使用 UnstructuredURLLoader,它内部调用 unstructured 库自动识别并提取正文,无需手动编写解析规则。
from langchain_community.document_loaders import UnstructuredURLLoader
loader = UnstructuredURLLoader(["https://example.com"])
docs = loader.load()
该加载器对动态渲染的页面(JavaScript 生成内容)支持有限,必要时可结合 Selenium 等工具。
CSV 加载:CSVLoader
CSVLoader 将 CSV 文件的每一行转换为一个独立的 Document,默认合并所有列内容。可通过 source_column 指定用作元数据来源的列(如标题)。
from langchain_community.document_loaders import CSVLoader
loader = CSVLoader(file_path="data.csv", source_column="Title")
docs = loader.load()
for doc in docs:
print(doc.metadata, doc.page_content[:50])
Excel 加载
Excel(.xlsx / .xls)的解析推荐使用云服务如 Azure Document Intelligence,它能智能识别表格结构和合并单元格。本地轻量替代方案是利用 pandas 读取后手动构造 Document 列表,但需自行处理表头、空值等细节。
自定义加载器:逐行读取文件
当内置加载器无法覆盖特殊格式(例如日志文件、自定义分隔符文本)时,可继承 BaseLoader 并实现 lazy_load 方法。该方法返回一个迭代器,使用 yield 逐个产出 Document,避免将所有内容一次性加载到内存。
以下示例实现了一个逐行读取文本文件的自定义加载器,每行生成一个 Document,并记录行号和来源路径。
from langchain_core.document_loaders import BaseLoader
from langchain_core.documents import Document
from typing import Iterator
class LineDocumentLoader(BaseLoader):
def __init__(self, file_path: str):
self.file_path = file_path
def lazy_load(self) -> Iterator[Document]:
with open(self.file_path, "r", encoding="utf-8") as f:
for line_no, line in enumerate(f, start=1):
yield Document(
page_content=line.strip(),
metadata={"line_number": line_no, "source": self.file_path}
)
完整可运行 Demo
以下示例整合了 TextLoader、CSVLoader 和上述自定义 LineDocumentLoader,全部使用临时文件,无需外部 API 即可直接运行。
环境依赖(确保已安装):
pip install langchain langchain-community
完整代码:
import tempfile
import os
from langchain_community.document_loaders import TextLoader, CSVLoader
from langchain_core.document_loaders import BaseLoader
from langchain_core.documents import Document
from typing import Iterator
# ---------- 自定义逐行加载器 ----------
class LineDocumentLoader(BaseLoader):
def __init__(self, file_path: str):
self.file_path = file_path
def lazy_load(self) -> Iterator[Document]:
with open(self.file_path, "r", encoding="utf-8") as f:
for line_no, line in enumerate(f, start=1):
yield Document(
page_content=line.strip(),
metadata={"line_number": line_no, "source": self.file_path}
)
# ---------- 使用临时目录演示 ----------
with tempfile.TemporaryDirectory() as tmpdir:
# 创建文本文件
txt_path = os.path.join(tmpdir, "sample.txt")
with open(txt_path, "w", encoding="utf-8") as f:
f.write("LangChain 是一个强大的 LLM 框架。\n它支持链式调用和 RAG。\n")
# 创建 CSV 文件
csv_path = os.path.join(tmpdir, "data.csv")
with open(csv_path, "w", encoding="utf-8") as f:
f.write("title,content\nAI Agent,智能体\nRAG,检索增强生成\n")
# 1. TextLoader 加载
text_loader = TextLoader(txt_path)
text_docs = text_loader.load()
print("--- TextLoader 结果 ---")
for doc in text_docs:
print(doc.page_content)
# 2. CSVLoader 加载
csv_loader = CSVLoader(csv_path)
csv_docs = csv_loader.load()
print("\n--- CSVLoader 结果 ---")
for doc in csv_docs:
print(doc.page_content)
# 3. 自定义 LineDocumentLoader 加载
line_loader = LineDocumentLoader(txt_path)
line_docs = list(line_loader.lazy_load())
print("\n--- 自定义逐行加载器结果 ---")
for doc in line_docs:
print(f"第{doc.metadata['line_number']}行: {doc.page_content}")
运行后,三种加载器分别输出相同源文件的不同粒度表示,充分展示 LangChain 加载器生态的灵活性与可扩展性。
API 速览
| 加载器 | 所属包 | 主要构造参数 | 关键方法 | 返回值 |
|---|---|---|---|---|
PyPDFLoader | langchain_community.document_loaders | file_path: str | load() | List[Document] |
WebBaseLoader | langchain_community.document_loaders | web_path: str, bs_kwargs: dict | load() | List[Document] |
UnstructuredURLLoader | langchain_community.document_loaders | urls: List[str] | load() | List[Document] |
CSVLoader | langchain_community.document_loaders | file_path: str, source_column: str | load() | List[Document] |
TextLoader | langchain_community.document_loaders | file_path: str | load() | List[Document] |
| 自定义加载器 | 用户实现 | 任意 | lazy_load() | Iterator[Document] |
参考文档
官方文档
参考链接
总结
本文系统梳理了 LangChain 中常用数据加载器的使用方法,涵盖 PDF、网页、CSV 等常见格式,并给出了多模态 PDF 解析和自定义加载器的开发范例。
通过统一 Document 结构,开发者可以轻松将不同来源的数据接入 RAG 流水线。
掌握这些工具后,下一步即可对 Document 列表进行文本切片、向量嵌入并存入向量数据库,从而构建完整的智能检索与生成应用。
2103



被折叠的 条评论
为什么被折叠?



