微信扫码
添加专属顾问
大量信息来源于文本数据,例如PDF文档。处理PDF可能特别具有挑战性,尤其是在处理表格和图像时。
如果您使用单模态语言模型,那么您可能已经知道它不具备直接解释或“读取”文档的能力。它只能处理一种类型的输入,例如纯文本或纯图像。如果您需要分析PDF中的图像或图表以用于下游任务,例如问答,您通常会使用专门的软件包来解析文档。这些工具可以将文档、文档中找到的图像和表格转换为模型可以理解和分析的文本格式。
有几种优秀的工具可用于解析PDF文档以用于下游任务。在本文中,我们将介绍一些优秀的工具,包括PyPDF、Adobe PDF Services API、Camelot和Tabula。
首先,让我们安装相关的库:
!pip install pdfservices-sdk
!pip install openpyxl
!pip install camelot-py
!pip install opencv-python
!pip install tabula-py==2.9.0
!pip install jpype1
!pip install langchain
!pip install langchain-core==0.1.40
Pypdf是一个用途广泛且常用的库,用于解析PDF文档。它可以解析文档,包括文档中的表格,并将其转换为文本。大多数情况下,使用PyPDF解析文档时,表格的格式也能得到很好的保留。
图片由作者提供
Langchain document_loaders 集成了许多不同的软件包,用于读取各种文件格式,包括PyPDF。以下脚本使用PyPDF处理文档并将其保存为数据框格式:
from langchain_community.document_loaders import PyPDFLoader
def extract_text_from_file(df, file_path):
file_name = file_path.split("/")[-1]
file_type = file_name.split(".")[-1]
if file_type == "pdf":
loader = PyPDFLoader(file_path)
else:
return df
text = ""
pages = loader.load_and_split()
for page in pages:
text += page.page_content
# Create a new df and concatenate
new_row = pd.DataFrame({"file": [file_name], "text": [text]})
df = pd.concat([df, new_row], ignore_index=True)
return df
#Apply the function:
folder_path = '../data/raw'
pathlist = Path(folder_path).glob('*.pdf')
filenames = []
for file_path in pathlist:
filename = os.path.basename(file_path)
filenames.append(filename)
df = pd.DataFrame()
for filename in filenames:
file_path = folder_path + "/" + filename
file_name = os.path.basename(file_path)
print(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')} process {file_name}")
# Initialize an empty df
df_file = pd.DataFrame(columns=["file", "text"])
print(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')} extract text")
try:
df_file = extract_text_from_file(df_file, file_path)
except Exception as e:
print("----Error: cannot extract text")
print(f"----error: {e}")
df = pd.concat([df, df_file])
df
您还可以单独处理每一页,例如,如果您想对每个块/页执行下游问答任务。在这种情况下,您可以修改脚本,如下所示:
def extract_text_from_file(df, file_path):
file_name = file_path.split("/")[-1]
file_type = file_name.split(".")[-1]
if file_type == "pdf":
loader = PyPDFLoader(file_path)
elif file_type == "docx":
loader = Docx2txtLoader(file_path)
else:
return df
pages = loader.load_and_split()
for page_number, page in enumerate(pages, start=1):
# Each page's text is added as a new row in the DataFrame
new_row = pd.DataFrame({
"file": [file_name],
"page_number": [page_number],
"text": [page.page_content]
})
df = pd.concat([df, new_row], ignore_index=True)
return df
PDF文档的每一页都可以包含任意数量的图像。您是否知道您也可以使用PyPDF从文档中提取所有图像?
以下代码块从pdf文件中提取所有图像,并创建一个新文件夹来存储提取的图像:
from pypdf import PdfReader
import os
output_directory = '../data/processed/images/image_pypdf'
if not os.path.exists(output_directory):
os.mkdir(output_directory)
reader = PdfReader("../data/raw/GPTsareGPTs.pdf")
for page in reader.pages:
for image in page.images:
with open(os.path.join(ouput_directory,image.name), "wb") as fp:
fp.write(image.data)
在文件夹中,您将找到PDF中的所有图像:
PyPDF提取的PDF中所有图像的列表。图片由作者提供
PDF Extract API(包含在PDF Services API中) 提供了基于云的功能,用于自动从PDF中提取内容。
PDF Services API 需要一个 access_token 来授权请求。为了使用访问令牌,您需要创建一个。当您收到包含 json 格式的 'client_id' 和 'client_secret' 的开发者凭据后,就可以使用它来处理您的 PDF。让我们首先导入相关的库:
```python
from adobe.pdfservices.operation.auth.credentials import Credentials
from adobe.pdfservices.operation.exception.exceptions import ServiceApiException, ServiceUsageException, SdkException
from adobe.pdfservices.operation.execution_context import ExecutionContext
from adobe.pdfservices.operation.io.file_ref import FileRef
from adobe.pdfservices.operation.pdfops.extract_pdf_operation import ExtractPDFOperation
from adobe.pdfservices.operation.pdfops.options.extractpdf.extract_pdf_options import ExtractPDFOptions
from adobe.pdfservices.operation.pdfops.options.extractpdf.extract_element_type import ExtractElementType
from adobe.pdfservices.operation.pdfops.options.extractpdf.extract_renditions_element_type import \
ExtractRenditionsElementType
import os.path
import zipfile
import json
import pandas as pd
import re
import openpyxl
from datetime import datetime
```
以下脚本使用必要的凭据设置 Adobe PDF Services API,处理 PDF 文件并将结果保存在 zip 文件中:
```python
def adobeLoader(input_pdf, output_zip_path,client_id, client_secret):
"""
运行 adobe API 并创建输出 zip 文件的函数
"""
# 初始化设置,创建凭据实例。
credentials = Credentials.service_principal_credentials_builder() \
.with_client_id(client_id) \
.with_client_secret(client_secret) \
.build()
# 使用凭据创建 ExecutionContext 并创建一个新的操作实例。
execution_context = ExecutionContext.create(credentials)
extract_pdf_operation = ExtractPDFOperation.create_new()
# 从源文件设置操作输入。
source = FileRef.create_from_local_file(input_pdf)
extract_pdf_operation.set_input(source)
# 构建 ExtractPDF 选项并将其设置到操作中
extract_pdf_options: ExtractPDFOptions = ExtractPDFOptions.builder() \
.with_elements_to_extract([ExtractElementType.TEXT, ExtractElementType.TABLES]) \
.with_elements_to_extract_renditions([ExtractRenditionsElementType.TABLES,
ExtractRenditionsElementType.FIGURES]) \
.build()
extract_pdf_operation.set_options(extract_pdf_options)
# 执行操作。
result: FileRef = extract_pdf_operation.execute(execution_context)
# 将结果保存到输出路径
if os.path.exists(output_zip_path):
os.remove(output_zip_path)
result.save_as(output_zip_path)
```
此 'adobeLoader' 操作的输出是一个 'sdk.zip' 包,其中包含以下内容:
'structuredData.json' 文件
文本存储在 json 文件中,并按上下文块提取——段落、标题、列表、脚注。
“table”文件夹:表格被提取并解析,并为每个单元格提供内容和表格格式信息。表格数据在生成的 JSON 中提供,也可以选择以 CSV 和 XLSX 文件输出。表格也输出为 PNG 图像,以便可以直观地验证表格数据。
“figures”文件夹:被识别为图形或图像的对象将提取为 PNG 文件。
输出文件夹结构
现在,您可以将该函数应用于您的文档:
```python
# Adobe 输出 zip 文件路径
input_pdf = 'data/raw/GPTsareGPTs.pdf'
output_zip_path = 'data/processed/adobe_result/sdk.zip'
output_zipextract_folder = 'data/processed/adobe_result/'
# 运行 adobe API
adobeLoader(input_pdf, output_zip_path)
```
您可以看到“figures”文件夹以 .png 格式返回我的 PDF 文档中的所有图像。表格文件夹返回表格的 Excel 工作表,这确保了高保真度和准确性,以及用于视觉比较目的的 .png 图像。
您还可以进一步处理结构化 JSON 文件 structuredData.json以收集文本和表格,并将这些数据组织到 pandas DataFrame 中,以用于进一步的下游任务:
Tabula 和 Camelot 是两个专门为从 PDF 中提取表格而设计的 Python 库。
以下脚本使用 Tabula 或 Camelot 处理 PDF 文档,将文档中的每个表格转换为 JSON 格式,同时捕获实际表格数据和元数据(例如表格编号和页码):
```python
def extract_tables(file_path, pages="all", package="tabula"):
if package == "camelot":
# 使用 camelot 提取表格
# flavor 可以是 'stream' 或 'lattice',对于表格没有清晰边框的文档,stream flavor 通常更合适。
tables = camelot.read_pdf(file_path, pages=pages, flavor="stream")
else:
tables = tabula.read_pdf(file_path, pages=pages, stream=True, silent=True)
# 将表格转换为 JSON
tables_json = []
for idx, table in enumerate(tables):
if package == "camelot":
page_number = table.parsing_report["page"]
data = table.df.to_json(orient="records")
else:
page_number = ""
data = table.to_json(orient="records")
data = {
"table_number": idx,
"page_number": page_number,
"data": data,
}
tables_json.append(data)
return tables_json
```
太棒了!现在我们有了处理表格的脚本,我们可以将该函数应用于相同的 Pdf 文档:
file_path = '../data/raw/GPTsareGPTs.pdf'
file_name = os.path.basename(file_path)
df_file = pd.DataFrame()
print(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')} process {file_name}")
print(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')} extract table")
all_tables = []
for package in ["camelot", "tabula"]:
print(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')} extract table with {package}")
try:
tables_from_package = extract_tables(file_path, pages="all", package=package) # list of json
for table in tables_from_package:
all_tables.append({"table": table, "source": package})
except Exception as e:
print("----Error: cannot extract table")
print(f"----error: {e}")
# Now you can access each table along with its source
for entry in all_tables:
print(f"Source: {entry['source']}, Table: {entry['table']}")
下面是源 PDF 文档中的一个表格示例:
Camelot 或 Tabula 操作的输出格式实际上是表格的字符串表示形式,如下面的 json 对象所示:
Tabula 的输出
当您切片 json 对象中的 ['data'] 键时,VS Code 似乎理解它是一种表格格式,并显示字符串的表格表示形式,这看起来与 PDF 文件中源表格中的完全相同。Tabula 似乎正确检测到了表格。棒极了!
Tabula 的输出
现在,让我们看一下 Camelot 的输出。以下显示了同一个表格的 json 对象。
Camelot 的输出
以及字符串的表格表示:
Camelot 的输出。Camelot 未能检测到表格的边界。当文本离表格太近时,它会包含文本。
在这个例子中,Tabula 和 Camelot 都能够检测到表格,但是 Tabular 的输出很干净,并且镜像了 PDF 中的原始表格。同时,Camelot 似乎未能检测到表格的边界。当文本离表格太近时,它会包含文本。
但是,在另一个例子中,当一个页面上有多个表格,并且没有像下面这样清晰的表格边界时:
Camelot 成功检测到两个表格,而 Tabula 未能检测到任何一个表格:
Camelot 的输出
Camelot 的输出
在考虑选择哪种选项来解析 PDF 文档时,PyPDF 是基本提取需求的理想选择,在这些需求中,表格结构可能不是优先事项。它是完全免费的,适合预算紧张且需要简单解决方案以高精度提取文本和图像的用户。根据我的经验,大多数情况下,将表格格式保留为文本是可以接受的。
Camelot 和 Tabula 专为表格提取而设计,最适合需要提取表格数据的场景。它们也是完全免费的,在我看来,如果您对偶尔的不准确性没有意见,那么它们就足够好了。
Adobe PDF Services API 为企业或应用程序提供了一个非常强大的解决方案,在这些企业或应用程序中,文本、表格和图像提取的高精度至关重要。但是,没有关于 API 定价的明确信息。这里说您需要联系销售人员获取报价。在这个 主题 上,Adobe Extract API 似乎相当昂贵。实际上,我** **愿意为实际使用付费,因为提取的输出质量是优质的!
在本文中,我们学习了四种不同的工具来解析 PDF 文档并从 PDF 文件中提取文本、表格和图像数据:PyPDF、Camelot、Tabula 和 Adobe PDF Services API。
感谢您的阅读。我希望它对您有效地将 PDF 内容转换为结构化和可操作的数据有所帮助。
53AI,企业落地大模型首选服务商
产品:场景落地咨询+大模型应用平台+行业解决方案
承诺:免费POC验证,效果达标后再合作。零风险落地应用大模型,已交付160+中大型企业
2026-07-01
一文了解|SkillScan 智能体技能安全扫描最佳实践
2026-07-01
协作的逆向演进:从 Agent 逻辑重构团队管理
2026-07-01
港科大郭毅可谈Agentic AI时代的核心命题:人机共生,人不可能退场
2026-07-01
Sonnet 5终于来了,然而Opus 4.8现在有点尴尬
2026-07-01
AI可观测性:Prompt、Tool Call、Trace、Token全链路追踪
2026-07-01
AI Infra 全景图:Agent Framework、调度、编排、沙箱、记忆管理、Tracing 分层拆解
2026-07-01
Claude Science发布:60+科学数据库一个对话搞定
2026-07-01
AI 的向量空间里藏着心理学,这是一场嵌入模型的情绪对决
2026-04-15
2026-04-07
2026-04-07
2026-04-24
2026-04-17
2026-04-05
2026-04-05
2026-04-14
2026-04-24
2026-04-22
欢迎您使用【53AI 官方网站】(以下简称“本网站”或“我们”)。本《会员服务协议》(以下简称“本协议”)是您(以下简称“会员”或“用户”)与【深圳市博思协创网络科技有限公司】之间关于注册、登录及使用本网站会员服务所订立的法律协议。
在您注册或登录前,请务必审慎阅读、充分理解各条款内容,特别是免除或限制责任的条款、知识产权条款、争议解决条款等。此类条款将以加粗形式提示您注意。 当您通过微信公众号授权、手机验证码验证或其他方式成功登录本网站时,即视为您已完全理解并同意接受本协议的全部内容。
一、 定义
本网站:指由【深圳市博思协创网络科技有限公司】运营的,域名为【53ai.com】的网站及相关移动端页面。
会员服务:指本网站向注册会员提供的知识库文章查阅、内容检索及其他相关增值服务。
知识库内容:指本网站发布的包括但不限于文字、图表、数据、研究报告、行业分析等数字化内容资源。
二、 账号注册与登录
登录方式:本网站支持以下登录方式,您可根据实际情况选择:
微信公众号授权登录:您同意将您的微信OpenID信息授权给本网站,用于创建或关联会员账号。
手机验证码登录:您需提供真实有效的手机号码,并通过短信验证码完成身份验证与登录/注册。
账号安全:您的账号仅限您本人使用,禁止赠与、借用、租用、转让或售卖。因您保管不善导致的账号被盗、密码泄露等损失,由您自行承担。
实名认证:根据相关法律法规要求,我们可能要求您在特定功能下完成实名认证。如您拒绝提供,可能无法使用部分或全部服务。
未成年人保护:若您未满18周岁,请在法定监护人的陪同下阅读本协议,并在征得监护人同意后使用本服务。
三、 服务内容与规范
知识库查阅权限:会员登录后,有权按照其会员等级对应的权限范围,在线浏览、检索本网站知识库中的相关文章及内容。
服务变更:我们有权根据业务发展需要,调整、变更或终止部分服务内容,并将以网站公告、公众号消息等方式提前通知。
禁止行为:您在使用服务时不得实施以下行为:
利用技术手段批量爬取、下载、转存知识库内容;
将知识库内容用于商业目的或未经授权地向第三方传播;
干扰本网站正常运行或侵犯其他用户合法权益;
发布违法违规信息或从事违反公序良俗的活动。
四、 知识产权声明
权利归属:本网站知识库中的排版设计、软件代码等内容的知识产权均归【公司全称】或原权利人所有,受《中华人民共和国著作权法》等法律保护。
有限许可:本网站授予会员一项非独占、不可转让、不可转授权的普通许可,仅限于个人学习、研究之目的在线查阅知识库内容。
侵权追责:未经书面许可,任何单位或个人不得以任何形式复制、转载、摘编、镜像、汇编或以其他方式使用上述内容。一经发现,我们保留追究其法律责任的权利。
五、 个人信息保护
我们重视对您个人信息的保护。关于我们如何收集、使用、存储和保护您的个人信息,请单独阅读 《隐私政策》。
您通过微信公众号授权或手机号验证所提供的信息,我们将严格按照《个人信息保护法》的规定处理,仅用于身份识别、服务提供及安全验证等必要用途。
您可以随时通过网站设置或联系客服行使查阅、更正、删除个人信息及撤回授权同意的权利。
六、 免责声明
内容准确性:知识库内容仅供参考,不构成专业建议。我们不对其完整性、准确性、时效性作任何明示或暗示的保证,您应自行判断并承担使用风险。
不可抗力:因自然灾害、政策法规变化、网络故障、第三方平台接口异常(如微信接口维护、运营商短信通道故障)等不可抗力导致的服务中断或延迟,我们不承担违约责任。
第三方链接:本网站可能包含指向第三方网站的链接,该等网站的内容和服务不受我们控制,请您自行甄别风险。
七、 违约责任
如您违反本协议约定,我们有权视情节采取警告、限制功能、暂停服务、注销账号等措施,并保留要求赔偿损失的权利。
如因您的违约行为导致我们遭受行政处罚、第三方索赔或商誉损失,您应承担全部赔偿责任(包括但不限于罚款、赔偿金、律师费、公证费等)。
八、 法律适用与争议解决
本协议的订立、执行和解释均适用中华人民共和国大陆地区法律。
因本协议产生的或与本协议有关的任何争议,双方应友好协商解决;协商不成的,任何一方均可向【公司所在地】有管辖权的人民法院提起诉讼。
九、 其他
本协议构成双方就本服务达成的完整协议,取代此前任何口头或书面约定。
本协议任一条款被认定为无效或不可执行的,不影响其他条款的效力。
我们对本协议享有最终解释权,并在法律允许的范围内保留随时修改的权利。修改后的协议一经公布即生效,继续使用服务即视为同意修订内容。