# LangChain 内置文档加载器使用技巧

LangChain 内部封装了大量不同类型的文档加载器,用于把各种来源的数据统一转换成 Document。常见类型包括 CSV、目录、HTML 网页、JSON、Markdown、PDF、Office 文档以及通用文件等。

不同加载器的使用流程大体一致:

  1. 根据文件路径、URL 或配置参数创建加载器实例。
  2. 调用 load() 或 lazy_load() 得到 Document。
  3. 检查 page_content 与 metadata。
  4. 再进入清洗、切分、向量化和入库流程。

差异主要体现在两个地方:一是实例化时传入的参数不同;二是返回的 Document 内容和 metadata 结构不同。例如 CSV 加载器可以指定列,DirectoryLoader 需要目录路径和文件匹配规则,JSONLoader 需要知道 JSON 中要抽取的结构。

BaseLoader 与常见文档加载器

# Markdown 文档加载器

Markdown 是常见的轻量级文本格式,很多 API 文档、产品说明、内部知识库都可以用 Markdown 保存。

LangChain 中可以使用 UnstructuredMarkdownLoader 加载 Markdown 文件。使用该加载器前,需要安装 unstructured:

pip install unstructured
1

示例代码:

from langchain_community.document_loaders import UnstructuredMarkdownLoader

loader = UnstructuredMarkdownLoader("./项目API资料.md")
documents = loader.load()

print(documents)
print(len(documents))
print(documents[0].metadata)
1
2
3
4
5
6
7
8

默认情况下,Markdown 文件通常会被加载为 Document 列表。后续可以继续使用文本分割器切分成更适合检索的 chunk。

如果希望按 Markdown 元素进行拆分,可以使用 mode="elements":

from langchain_community.document_loaders import UnstructuredMarkdownLoader

loader = UnstructuredMarkdownLoader("./项目API资料.md", mode="elements")
documents = loader.load()

for document in documents:
    print(document.page_content)
    print(document.metadata)
1
2
3
4
5
6
7
8

mode="elements" 更适合保留标题、段落等结构,但它不是最终的 chunk 策略。入库前仍然要根据内容长度和检索需求决定是否继续切分。

# Office 文档加载器

Office 文件不是普通文本文件,不能直接用 TextLoader 读取。Excel、Word、PPT 都需要对应的加载器处理。

示例代码:

from langchain_community.document_loaders import (
    UnstructuredPowerPointLoader,
)

# excel_loader = UnstructuredExcelLoader("./员工考勤表.xlsx", mode="elements")
# excel_documents = excel_loader.load()

# word_loader = UnstructuredWordDocumentLoader("./喵喵.docx")
# documents = word_loader.load()

ppt_loader = UnstructuredPowerPointLoader("./章节介绍.pptx")
documents = ppt_loader.load()

print(documents)
print(len(documents))
print(documents[0].metadata)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

Office 文档解析时要重点关注结构是否丢失。比如 Excel 的表格行列、PPT 的页面结构、Word 的标题层级,如果被解析成一大段无结构文本,后续检索效果会明显下降。

# URL 网页加载器

网页内容可以使用 WebBaseLoader 加载:

from langchain_community.document_loaders import WebBaseLoader

loader = WebBaseLoader("https://imooc.com")
documents = loader.load()

print(documents)
print(len(documents))
print(documents[0].metadata)
1
2
3
4
5
6
7
8

网页加载器适合快速把 URL 页面变成 Document,但网页通常包含导航、页脚、广告、登录入口、推荐位、重复链接等噪声。真实入库前,通常还需要做清洗:

  • 去掉导航和页脚。
  • 去掉重复链接和按钮文字。
  • 去掉空白行、Tab 和无意义换行。
  • 保留页面 URL、标题、发布时间等 metadata。

如果页面依赖前端动态渲染,普通网页加载器可能拿不到完整内容,需要考虑浏览器渲染类抓取工具或专门的网页解析服务。

# 通用文件加载器

当不确定文件类型,或者想快速验证不同文件的读取效果时,可以使用 UnstructuredFileLoader:

from langchain_community.document_loaders import UnstructuredFileLoader

loader = UnstructuredFileLoader("./项目API资料.md")
documents = loader.load()

print(documents)
print(len(documents))
print(documents[0].metadata)
1
2
3
4
5
6
7
8

通用文件加载器的优势是覆盖面广,适合作为兜底方案;缺点是对特定格式的结构保留不一定最好。能明确文件类型时,优先使用专用加载器。

# 加载器选型

数据源 推荐加载器 注意点
纯文本、源码、日志 TextLoader 需要指定正确编码
Markdown UnstructuredMarkdownLoader 可按元素解析,但仍要评估 chunk 粒度
Excel UnstructuredExcelLoader 关注表格结构是否保留
Word UnstructuredWordDocumentLoader 关注标题层级、段落、页码
PPT UnstructuredPowerPointLoader 关注每页内容和备注
HTML 文件 UnstructuredHTMLLoader、BSHTMLLoader 需要清洗噪声
网页 URL WebBaseLoader 或网页解析服务 动态页面可能抓不全
PDF PyPDFLoader、UnstructuredPDFLoader、其他 PDF 解析器 关注页码、表格、图片文字
不确定类型 UnstructuredFileLoader 适合兜底,不一定保留最佳结构

# 最新版 LangChain 用法提示

最新版 LangChain 仍然保留“文档加载器输出 Document”的整体思路。官方文档中也强调,Document loaders 提供标准接口,把不同来源的数据读入 Document 格式。

需要注意几点:

  • load() 和 lazy_load() 仍然是文档加载器的通用接口。
  • 大文件或大批量数据更推荐 lazy_load(),不要一次性把所有内容读进内存。
  • 社区加载器通常来自 langchain_community 或对应集成包,使用前要确认依赖是否安装。
  • load_and_split() 不优先作为新代码主路径,建议加载后显式调用分割器。
  • 对于 PDF、网页等复杂数据,最新版生态中也有 Docling、Unstructured 等不同解析方案,生产中要用样本对比解析质量。

推荐写法:

from langchain_community.document_loaders import UnstructuredMarkdownLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter

loader = UnstructuredMarkdownLoader("./项目API资料.md")
documents = loader.load()

splitter = RecursiveCharacterTextSplitter(
    chunk_size=1000,
    chunk_overlap=200,
    add_start_index=True,
)
chunks = splitter.split_documents(documents)
1
2
3
4
5
6
7
8
9
10
11
12

# 拓展

内置加载器只能解决常见格式。如果数据来自数据库、内部 API、对象存储、权限系统或业务平台,就需要自定义 Loader 或在 Loader 外层做适配。

另外,加载器只解决“读出来”的问题,不保证“适合检索”。入库前还要检查:

  • 正文是否完整。
  • 是否有乱码。
  • metadata 是否保留来源。
  • 表格和标题是否丢失。
  • 是否存在大量重复和无效内容。

# 常见问题

# 为什么专用 Loader 优先于通用 Loader?

专用 Loader 更了解文件结构,更容易保留页码、标题、表格、段落等信息。通用 Loader 覆盖面广,但结构保留不一定稳定。

# mode="elements" 是不是就不用切分了?

不是。mode="elements" 是解析阶段按元素拆分,最终是否适合作为 chunk,还要看长度、语义完整性和检索效果。

# 网页加载后为什么检索结果很差?

很多网页正文里混入导航、页脚、广告、推荐链接和版权信息。如果不清洗,这些噪声会进入向量库,导致召回质量下降。

# 面试题

# 文档加载器在 RAG 中解决什么问题?

它负责把不同来源的数据统一转换成 Document,从而让后续分割、向量化、检索都面向同一种数据结构。

# 如何选择内置 Loader?

先看数据源类型,能确定格式就选专用 Loader;不能确定格式或只是快速验证,可以用通用 Loader 兜底。选完后必须抽样检查正文和 metadata。

# 为什么 Loader 不应该负责向量化?

Loader 的职责是读取并转换成 Document。向量化属于索引阶段。如果混在一起,数据读取问题和索引问题会耦合,后续很难排查。

# 生产问题排查

问题 常见原因 处理方式
加载失败 依赖包没装、路径错误、文件格式不支持 安装对应依赖,检查路径和 Loader 类型
内容乱码 编码不匹配 显式指定 encoding 或换解析器
metadata 太少 通用 Loader 保留信息有限 使用专用 Loader 或手动补字段
网页噪声多 导航、页脚、广告进入正文 增加清洗规则
Office 表格丢失 解析器不适合该文件 对比不同 Loader,必要时专门解析表格
批量导入内存高 使用 load() 一次性加载 改用 lazy_load() 或队列处理