这个问题已经在这里坐了很长一段时间,但我会给出答案,因为几周前我遇到了一个非常相似的问题。
我有多个不同的文件(.docx
, .pdf
)位于不同的文件夹中。更复杂的是,这些.docx
文件分为三组:SS.docx
和ss.docx
plain .docx
。我的信息.docx
在每份文件的一个表格中一目了然。
我很努力地写了一个 Python 提取算法,现在我将引导你完成:
import os
import pandas as pd
import docx
from docx.api import Document
#fixed variable
location = 'C:\\Data_analysis\\N_TRACKING'
然后我添加了一个函数,该函数从 list 开始遍历完整的文件树location
并将所有文件名及其路径存储在 list 中targets_in_dir
。
#the function
def find_docx(location):
all_files = [] # Will contain found files
# Walk top-down through directory tree
for (root, dirs, files) in os.walk(location, topdown=True):
for f in files:
f = f.lower() # Make conditional case insensitive
if f.endswith('.pdf'):
continue # Skipping pdf
if f.endswith('ss.docx'):
continue # Skipping ss.docx or SS.docx
if f.endswith('.docx'):
# Desired docx (undesired docx has been filtered out by previous conditional)
all_files.append(os.path.join(root, f))
return all_files
该endswith
函数在这里非常有用,因为它将字符串的结尾(这里是我的列表元素)与括号中的字符串进行比较。本质上,我跳过了我不想要的所有内容,只添加了我想要all_files
的函数返回的内容。我将该函数应用于该位置并将我的结果存储在targets_in_dir
.
#main
targets_in_dir = find_docx(location)
然后我在提取循环中喂它
error_log =[]
empty =[]
processed_files =[]
final_df= pd.DataFrame(empty)
for idx, c in enumerate(targets_in_dir):
try:
document = Document(c)
table = document.tables[6]
processed_files.append(c)
except:
error_log.append(c)
data = []
keys = None
for i, row in enumerate(table.rows):
text = (cell.text for cell in row.cells)
if i == 0:
keys = tuple(text)
continue
row_data = dict(zip(keys, text))
data.append(row_data)
df = pd.DataFrame(data)
df['report'] = str(c)
final_df = final_df.append(df)
我在python-docx
这里使用库,它直接允许我选择表作为对象。奇怪的是,由于某种文档错误,我不得不pip install python-docx
并且只能将其导入,因为迭代许多文件通常会失败。docx
这就是try: except:
循环的用途
错误存储在error_log
. 算法经过的文件processed_files
.
final_df
是一个空数据框,我将在其中附加我的结果。
请注意,我从这一行的所有这些文档中指定了我想要的表格(编号 6):
table = document.tables[6]
然后,代码使用第一行作为字典的键并在其上映射内容来遍历表的行。然后我通过线路添加跟踪信息(总是知道你的数据来自哪里!)
df['report'] = str(c)
并将结果数据框化并从一开始就将其添加到我的空df中。然后你可以开始清理数据,因为人类往往很混乱!