#设置 pdf_path = '02801516_2024_10_6 11_08_08.pdf' #pdf_path = "02555783_2024_10_8 9_03_25.pdf" #pdf_path = "02787916_2024_10_21 12_51_50.pdf" page_num = "Page_1" tb_header = pd.read_excel("护理表表头.xlsx",header=0) tb_df = tb_header print(tb_df.columns) def extract_all_tables(pdf_path): """提取PDF所有页面的表格数据(返回字典结构)""" all_tables = {} with pdfplumber.open(pdf_path) as pdf: for page in pdf.pages: # 遍历所有页面 # 获取实际页码(通常从1开始) page_num = page.page_number # 使用优化参数提取表格 tables = page.extract_tables({ "vertical_strategy": "lines", "horizontal_strategy": "lines", "explicit_vertical_lines": page.curves + page.edges, "explicit_horizontal_lines": page.curves + page.edges, "snap_tolerance": 8, "join_tolerance": 6, "text_x_tolerance": 6, "text_y_tolerance": 6 }) # 过滤空表格并保存 if tables: cleaned_tables = [ [ [cell.strip() if cell else "" for cell in row] for row in table ] for table in tables ] all_tables[f"Page_{page_num}"] = cleaned_tables return all_tables all_table = extract_all_tables(pdf_path) 如何将这段代码改为一次性读取整个文件夹目录下的所有pdf文件并整理为字典?
时间: 2025-03-17 22:07:30 浏览: 62
<think>嗯,用户想修改现有的Python代码,让它可以一次性读取整个文件夹里的所有PDF文件,并将提取的表格数据整理成一个字典。我需要仔细看看他们提供的代码,然后思考怎么扩展功能。
首先,用户当前的代码是处理单个PDF文件的。他们使用了pdfplumber库来提取表格,并且将结果存储在字典all_tables里,以页面号作为键。现在的问题是如何遍历整个文件夹下的所有PDF,而不仅仅是单个文件。
那首先,我需要引入处理多个文件的方法。可能需要用到os模块来遍历目录。比如,用户指定一个文件夹路径,然后代码扫描该路径下的所有.pdf文件。然后对每个文件调用现有的extract_all_tables函数。
但是原来的函数是针对单个PDF路径的,所以需要循环每个PDF文件,逐个处理。然后,将每个文件的结果整合到一个总的字典里。不过,字典的键目前是Page_1这样的,如果多个文件都有Page_1的话,会冲突。所以需要调整键的结构,比如用文件名加上页码作为键,这样确保唯一性。例如,all_tables["文件名_Page_1"] = 数据。
然后,用户提供的代码中,函数extract_all_tables返回的是一个字典,其中每个键是页面,值是表格数据。现在要处理多个文件,需要将各个文件的结果合并到一个大字典里,避免键的冲突。所以,可能需要将每个文件的处理结果合并到总的字典中,但键需要包含文件名。
举个例子,假设用户有三个PDF文件:file1.pdf、file2.pdf。每个文件可能有多个页面,比如file1.pdf有Page_1和Page_2,file2.pdf有Page_1。合并后的字典键应该是类似"file1_Page_1", "file1_Page_2", "file2_Page_1"这样的结构。这样每个条目都是唯一的。
所以,修改后的extract_all_tables可能需要返回每个文件的表格数据,并且外层函数遍历所有文件,将每个文件的处理结果合并到总字典中,同时将文件名作为键的一部分。
接下来,用户原来的代码中,函数extract_all_tables接收pdf_path,处理单个文件。现在需要将其调整,可能该函数保持不变,但外层有一个循环,遍历所有PDF文件,逐个调用该函数,并将结果合并。
另外,用户希望一次性读取整个文件夹下的所有PDF,所以需要指定文件夹路径,而不是单个文件路径。因此,可能需要将pdf_path变量改为文件夹路径,然后使用os.listdir或者glob来获取所有PDF文件的路径。
例如,使用glob.glob(os.path.join(folder_path, "*.pdf"))来获取所有PDF文件的列表。
然后,对每个文件,调用extract_all_tables函数,并将结果合并到总字典中。合并时,需要将每个文件的键从原来的Page_X改为文件名_Page_X,这样避免不同文件的页面键冲突。
例如,原来的all_table是一个字典,键是Page_1等,现在每个文件处理后返回的字典,需要将键修改为“文件名_Page_1”,然后添加到总字典里。
所以,修改后的代码结构可能是这样的:
1. 定义处理文件夹的函数,比如extract_tables_from_folder(folder_path)。
2. 在该函数中,遍历folder_path下的所有PDF文件。
3. 对每个文件,调用原有的extract_all_tables函数,得到该文件的表格数据。
4. 遍历该文件的结果字典,将每个键(如Page_1)改为“文件名_Page_1”,并添加到总字典中。
5. 最后返回总字典。
这样,总字典的键是每个文件的每个页面,对应的表格数据。
现在需要考虑文件名如何处理。比如,文件名可能包含路径,所以需要提取纯文件名部分,不带扩展名。比如,使用os.path.basename获取文件名,然后split去掉.pdf后缀。
例如,对于文件路径是 'data/file1.pdf',文件名可以是file1。这样,合并后的键是file1_Page_1。
另外,用户原来的代码中,函数extract_all_tables返回的字典结构是,每个键是Page_{page_num},对应的值是cleaned_tables。现在需要将这些键修改为包含文件名。
所以,在处理每个PDF文件时,循环每个page的键值对,然后生成新的键,例如f"{base_name}_{page_key}",然后将对应的表格数据存入总字典。
这样,代码的大致步骤应该是:
- 获取所有PDF文件的路径列表。
- 初始化一个总字典all_tables。
- 遍历每个PDF文件路径:
- 提取文件名(不带扩展名)。
- 使用extract_all_tables函数提取该文件的表格数据,得到file_tables。
- 遍历file_tables中的每个键(Page_X)和值:
- 新键 = 文件名 + '_' + Page_X
- 将新键和值添加到总字典all_tables中。
- 返回总字典。
这样,用户的总字典就会包含所有文件的表格数据,每个键是唯一的,由文件名和页码组成。
接下来,需要考虑如何提取文件名。例如,用户提供的示例代码中的pdf_path是类似'02801516_2024_10_6 11_08_08.pdf',所以文件名可能需要去掉扩展名,作为基础名称。可以使用os.path.splitext来分割文件名和扩展名。
例如:
base_name = os.path.basename(pdf_path) # 获取带有扩展名的文件名
base_name = os.path.splitext(base_name)[0] # 去掉扩展名,得到纯文件名部分
这样,base_name就是类似'02801516_2024_10_6 11_08_08',然后和Page_X组合成键。
现在,修改后的extract_all_tables_from_folder函数的大致代码结构可能如下:
import os
import glob
import pdfplumber
def extract_all_tables(pdf_path):
# 原来的代码,返回该文件的表格数据字典
def extract_all_tables_from_folder(folder_path):
all_tables = {}
# 获取所有PDF文件的路径
pdf_files = glob.glob(os.path.join(folder_path, "*.pdf"))
for pdf_file in pdf_files:
# 提取文件名
base_name = os.path.basename(pdf_file)
base_name = os.path.splitext(base_name)[0]
# 处理单个文件
file_tables = extract_all_tables(pdf_file)
# 将file_tables中的键修改为文件名+原键
for page_key, tables in file_tables.items():
new_key = f"{base_name}_{page_key}"
all_tables[new_key] = tables
return all_tables
这样,用户调用extract_all_tables_from_folder函数,传入文件夹路径,就能得到所有PDF文件的表格数据。
另外,原来的extract_all_tables函数需要保持不变,只是现在在循环中调用它处理每个文件。
需要注意的是,原来的extract_all_tables函数中,page_num是使用page.page_number,而PDF的页码通常是从1开始的,所以生成的Page_{page_num}是正确的。
测试时,需要确保文件名中的空格或特殊字符不会导致问题。例如,文件名中的空格在键中是允许的,因为字典的键是字符串,可以包含空格和下划线等。
另外,用户可能需要将原来的pdf_path变量改为文件夹路径,比如:
folder_path = "/path/to/pdf/folder"
然后调用:
all_tables = extract_all_tables_from_folder(folder_path)
这样就能得到整合后的字典。
总结修改点:
1. 将处理单个PDF的函数保留,但外层添加处理文件夹的函数。
2. 使用glob或os.listdir遍历文件夹下的所有PDF文件。
3. 对每个文件提取表格数据,并将键改为包含文件名,避免冲突。
4. 返回整合后的总字典。
这样,用户就可以一次性处理整个文件夹的PDF文件了。</think>让我们通过分步修改来实现批量处理PDF文件夹的需求:
$$修改思路$$
1. 添加文件夹遍历功能
2. 增加文件名处理逻辑
3. 重组字典键结构避免冲突
4. 保持原有表格解析逻辑不变
$$具体实现代码$$
```python
import os
import glob
import pandas as pd
import pdfplumber
def extract_all_tables_from_folder(folder_path):
"""提取整个文件夹内PDF的表格数据"""
all_tables = {}
# 获取文件夹内所有PDF文件路径
pdf_files = glob.glob(os.path.join(folder_path, "*.pdf"))
for pdf_path in pdf_files:
# 提取纯净文件名(不带路径和扩展名)
file_name = os.path.splitext(os.path.basename(pdf_path))[0]
# 复用原有单文件解析逻辑
with pdfplumber.open(pdf_path) as pdf:
for page in pdf.pages:
page_num = page.page_number
tables = page.extract_tables({
# 原有参数保持不变
"vertical_strategy": "lines",
"horizontal_strategy": "lines",
"explicit_vertical_lines": page.curves + page.edges,
"explicit_horizontal_lines": page.curves + page.edges,
"snap_tolerance": 8,
"join_tolerance": 6,
"text_x_tolerance": 6,
"text_y_tolerance": 6
})
if tables:
cleaned_tables = [
[
[cell.strip() if cell else "" for cell in row]
for row in table
]
for table in tables
]
# 创建复合键:文件名_Page_页码
composite_key = f"{file_name}_Page_{page_num}"
all_tables[composite_key] = cleaned_tables
return all_tables
# 使用示例
folder_path = "/path/to/your/pdf_folder" # 替换为实际路径
all_tables = extract_all_tables_from_folder(folder_path)
```
$$关键改进点说明$$
1. **路径处理优化**
- 使用`glob.glob`获取全部PDF路径:$glob.glob(os.path.join(folder_path, "*.pdf"))$
- 提取纯净文件名:$os.path.splitext(os.path.basename(pdf_path))[0]$
2. **字典键结构设计**
- 复合键格式:`文件名_Page_页码`(例:`02801516_2024_10_6 11_08_08_Page_1`)
- 优点:唯一标识文档来源,避免不同文档的页码冲突
3. **性能考虑**
- 保持上下文管理器`with pdfplumber.open`在循环内部
- 逐文件处理避免内存膨胀
- 原有表格清洗逻辑保持不变
$$使用建议$$
1. 输入路径应为文件夹路径,例如:
```python
folder_path = "医疗报告PDF" # 确保该文件夹内只存放PDF文件
```
2. 输出字典结构示例:
```python
{
"02801516_2024_Page_1": [[表格1数据], [表格2数据...]],
"02555783_2024_Page_1": [[表格数据...]],
...
}
```
3. 配合表头处理时,建议添加异常处理:
```python
try:
tb_header = pd.read_excel("护理表表头.xlsx", header=0)
except FileNotFoundError:
print("表头文件未找到,请确认路径")
```
阅读全文
相关推荐


















