使用tabula-py提取PDF表格时多行数据被拆分的替代解决方法
解决PDF多行词汇表提取合并问题的方案
除了调整Tabula-py的参数,你可以尝试以下几种直接有效的处理方式:
方法1:提取后用Pandas合并同组行
先通过Tabula-py提取原始表格数据,再用Pandas对拆分的行进行分组合并,这是最直接的补位方案:
- 读取PDF数据:
import pandas as pd from tabula import read_pdf # 读取全页表格,指定表头 df = read_pdf("your_vocab.pdf", pages="all", pandas_options={"header": 0}) # 重命名列(根据实际提取的列名调整) df = df.rename(columns={"原德语列名": "德语", "原拉丁语列名": "拉丁语"})
- 生成分组标识:以非空的德语词汇作为分组起点,给同一逻辑行的所有拆分行分配相同组ID:
# 标记德语列非空的行,作为新组的起始 df["group_id"] = df["德语"].notna().cumsum()
- 按组聚合合并内容:
# 合并同一组内的多行内容,用换行符连接(可替换为空格) merged_df = df.groupby("group_id").agg( 德语=("德语", lambda x: "\n".join([str(i) for i in x if str(i) != "nan"])), 拉丁语=("拉丁语", lambda x: "\n".join([str(i) for i in x if str(i) != "nan"])) ).reset_index(drop=True)
- 导出为CSV:
merged_df.to_csv("vocab.csv", index=False, encoding="utf-8-sig")
方法2:用PDFPlumber基于位置合并行
PDFPlumber可以获取文本的精确坐标信息,通过判断行的垂直位置(y坐标)识别同一逻辑行的拆分内容:
import pdfplumber import pandas as pd vocab_list = [] current_de = "" current_la = "" prev_y = None with pdfplumber.open("your_vocab.pdf") as pdf: for page in pdf.pages: # 提取页面文本,设置坐标容错值 words = page.extract_words(x_tolerance=5, y_tolerance=3) for word in words: # 判断当前行是否属于上一个逻辑行(y坐标差小于5则视为同一行) if prev_y is not None and abs(word["top"] - prev_y) < 5: # 根据x坐标区分德语(左)和拉丁语(右)列 if word["x0"] < page.width / 2: current_de += " " + word["text"] else: current_la += " " + word["text"] else: # 保存上一行内容,初始化当前行 if current_de: vocab_list.append({"德语": current_de.strip(), "拉丁语": current_la.strip()}) current_de = word["text"] if word["x0"] < page.width / 2 else "" current_la = word["text"] if word["x0"] >= page.width / 2 else "" prev_y = word["top"] # 保存最后一行内容 if current_de: vocab_list.append({"德语": current_de.strip(), "拉丁语": current_la.strip()}) # 转成DataFrame并导出CSV pd.DataFrame(vocab_list).to_csv("vocab.csv", index=False, encoding="utf-8-sig")
方法3:提取纯文本后用正则分组
如果PDF词汇表格式规律(比如德语词汇以大写开头),可以先提取全量文本,再用正则匹配合并多行内容:
import PyPDF2 import re import pandas as pd # 提取PDF所有文本 text = "" with open("your_vocab.pdf", "rb") as f: reader = PyPDF2.PdfReader(f) for page in reader.pages: text += page.extract_text() # 正则匹配每组词汇(根据实际格式调整表达式) pattern = r"([A-Z][a-zäöüß]+(?:\n.+?)*)\s+([A-Z][a-zāēīōū]+(?:\n.+?)*)(?=\n[A-Z]|$)" matches = re.finditer(pattern, text, re.DOTALL) vocab_list = [] for match in matches: de = match.group(1).replace("\n", " ").strip() la = match.group(2).replace("\n", " ").strip() vocab_list.append({"德语": de, "拉丁语": la}) pd.DataFrame(vocab_list).to_csv("vocab.csv", index=False, encoding="utf-8-sig")
内容的提问来源于stack exchange,提问作者Dustin
相关产品推荐
相关产品推荐

